ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于STM32与NE555的高精度电容电阻测量仪设计与实现

基于STM32与NE555的高精度电容电阻测量仪设计与实现 1. 项目概述与方案选型思路做嵌入式这几年板子上随时会用到各种标称值的电阻电容但手头没有LCR表的时候只能靠万用表大概估一下。后来我用STM32搭配一块最经典的NE555做了个高精度测量仪专门负责电容电阻双测量。整套硬件成本很低却能把电阻从1欧到几兆欧、电容从几十皮法到几百微法的范围测出来配合软件校准后误差能稳定在1%左右。这篇文章我会把原理、电路、代码、标定和误差分析全部摊开来说适合想做实用仪器、又想深入理解RC测量原理的朋友参考。1.1 为什么选NE555STM32而不是直接上ADC也许你第一反应是用ADC。直接测电阻确实可以把电阻和一个基准电阻分压用STM32的ADC读电压再用算法反推。但分压法有个天生的问题量程宽了之后输出电压变化非常不均匀。测量1欧和1兆欧需要几组分压和增益切换不然要么小电阻被分辨率吃掉要么大电阻进入饱和区电容测量更麻烦ADC只能看到电压变化的过程还需要精确的时间基准来拟合充放电曲线对实时性要求高。NE555在这种场景里其实扮演的是一个“时间转换器”它把被测电阻、电容的大小转换成一段高电平脉宽。STM32只需要做最擅长的事——用定时器把这段脉宽精确测出来。晶振有多准时间测量就有多准省掉了一堆模拟前端。这也解释了为什么老掉牙的NE555到今天还能在新设计里出现它做“RC到时间”的转换非常可靠。1.2 单稳态测量原理NE555有三种典型工作模式这里用的是单稳态。平时3脚输出低电平2脚收到一个负脉冲后3脚跳高同时内部放电管断开标准电容或被测电容开始通过基准电阻充电当电容电压充到阈值引脚检测到2/3VCC时输出跳低放电管重新导通把电放掉。这个输出高电平的持续时间对应充电时间公式是T1.1RC。R是充电回路电阻C是充电电容。测量电阻挡就串入一个固定基准电容测未知电阻测量电容挡就串入一个固定基准电阻测未知电容。用一个挡位切换开关把固定元件和待测元件互换就能实现双测量逻辑非常清晰。关于为什么用单稳态而不是常见的无稳态振荡器测频率这里说下我的考虑。无稳态模式下NE555连续输出方波测频率也能算出RC但频率测量对占空比不敏感而且窄脉冲高、宽脉冲低的问题会让量程覆盖不够。单稳态把信息集中在一次脉宽里每次测量时间短适合做成手持仪器。1.3 系统组成与工作流程整体硬件分成三个部分NE555单稳态测量前端、STM32测量与控制核心、OLED显示和人机交互。测量时STM32先通过I/O口给NE555的2脚一个约10us的负脉冲等输出脚跳高立刻启动输入捕获计时等到输出脚跳低捕获结束计数得到的脉宽就能换算出电阻或电容。为了覆盖宽量程我会在基准元件侧预留几个挡位例如基准电容取10nF、100nF、1uF基准电阻取1k、10k、100k可以用CD4066模拟开关切换也可以用继电器。实际使用时如果当前挡位算出来的数值超出量程软件会自动切到下一挡重新触发测量。2. 硬件设计与关键电路解析2.1 NE555单稳态电路细节关键电路连接方案5V供电2脚通过一个10k电阻上拉到VCC2脚直接引到MCU触发引脚6脚和7脚接在一起通过基准电阻R到VCC通过被测电容C到地。3脚输出接STM32捕获引脚。我用的是LM555CN国产NE555也没有问题内部放电管的导通时间都在几百纳秒级别不影响整体精度。触发脉冲宽度有讲究。NE555手册规定触发负脉冲的宽度理论上要小于输出高电平时间否则可能锁存输出。我实际用10us宽度对大部分被测元件都成立因为最小脉宽出现在最大量程时也有几百微秒。如果自制时触发脚直接接地持续太久输出会被“钉”在高电平这是新手最常见的坑。关于充电回路的走线有一个容易忽略的点7脚放电管导通时内部实际上是接到地的如果不小心把7脚和6脚的走线分开太远、中间有长线寄生的电感可能会让波形出现振铃影响阈值判断。尽量让R、C、供电退耦靠近NE555放面包板上实验可以做成PCB之后读数会更稳定。2.2 挡位切换与基准元件选择挡位切换我用的是CD4066四个独立模拟开关一个芯片解决四路切换。导通电阻大概几十到一两百欧在毫秒级的RC时间里影响很小但在测量小电阻时必须做短接校准把导通电阻从结果里扣掉。如果追求极致低阻测量建议用继电器或者双路开关并联导通电阻可以降到毫欧级别。基准元件的选择直接决定最终精度。基准电容我优先选CBB聚丙烯电容温度系数稳定、损耗小10nF、100nF各备几颗基准电阻选1%精度金属膜电阻如果手头有0.1%的更好。实测10nF的国产CBB电容实际容值可能偏了2%左右所以后面讲到标定时我会强调先测量并校准基准值。供电方面要留意NE555用5VSTM32一般3.3V两者之间做电平匹配。我把NE555输出通过一个1k电阻直接接到STM32引脚引脚内部的保护二极管会限制高电平到3.3V多一点实测没问题。如果你不放心也可以外接一个3.3V稳压管或分压电阻总之别直接硬接5V高电平给MCU引脚长时间高压有可能损坏引脚。2.3 STM32最小系统与接线核心板我用了一个STM32F103C8T6的小板8M晶振、复位电路、BOOT0拉低都是标准配置。这里要注意如果GPIO上电默认状态不确定触发的负脉冲和NE555的初始状态配合不好所以我会在代码里先把触发引脚配置成推挽输出并置高初始化完成后再开始第一轮测量。LCD用0.96寸I2C OLEDSCL和SDA分别接到PB6、PB7定时器捕获我用PA0对应TIM2_CH1。还有一个按键用来切换测量模式电阻/电容/自动接在PA4上做外部中断。整个系统一共没多少连线但建议做成一块PCB一是减少寄生电容二是探头可以用排针直接插方便测试。3. 固件实现定时器捕获与数值换算3.1 初始化与定时器配置我采用STM32标准外设库写的工程Keil5环境下编译用ST-Link下载。先初始化系统时钟到72MHz然后配置GPIO和TIM2。定时器设置成输入捕获模式分频系数设为35这样计数频率是72MHz/362MHz每个计数对应0.5微秒能分辨大约0.5微秒的时间差对应电容挡的小电容能做到几十皮法级别的分辨率。配置代码void TIM2_Cap_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period 0xFFFF; TIM_TimeBaseStructure.TIM_Prescaler 35; TIM_TimeBaseStructure.TIM_ClockDivision 0; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure); TIM_ICInitStructure.TIM_Channel TIM_Channel_1; TIM_ICInitStructure.TIM_ICPolarity TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter 0x0F; TIM_ICInit(TIM2, TIM_ICInitStructure); TIM_Cmd(TIM2, ENABLE); TIM_ClearITPendingBit(TIM2, TIM_IT_CC1); TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE); }滤波参数0x0F是为了滤掉输出波形上的毛刺但对正常的几百微秒脉宽没有影响实测读数稳定很多。如果你用的是HAL库逻辑完全一样只是API名字换一下关键还是分频系数和捕获极性。3.2 完整测量流程与滤波触发和测量在主循环里做。先通过PA1输出一个10us的负脉冲随后在中断里记录上升沿和下降沿的计数值两者相减得到脉宽。因为TIM2是16位的最大计数值65535对应约32.7毫秒而单稳态的最大脉宽通常不超过几十毫秒所以直接用32位变量拼接处理避免计数回绕导致测负。每次测量我会连续测9次去掉一个最高和一个最低剩下7次取平均值再做一次滑动平均。这样处理之后电源纹波或接触抖动引起的偶然跳变就被压掉了。中值滤波对突然的尖峰特别有效滑动平均能找到真实趋势两者配合之后读数小数点后两位基本不跳。这里有一个细节触发脉冲输出之后NE555输出要经过一个上升沿才能被捕获到。如果代码在发出负脉冲后立刻去读捕获寄存器有可能读到上一次的残留值。我在主循环里会加一个标志位只有捕获中断真正置位之后才进入计算逻辑否则继续等待。3.3 数值换算与自动换挡换算很简单都是前面那条T1.1RC公式。测量电阻时R_x pulseTime_us / (1.1 * C_ref_uF)测量电容时C_x pulseTime_us / (1.1 * R_ref_kOhm)。代码里把时间转为微秒再计算显示时自动选择单位float pulse_us, Rx, Cx; if (mode MODE_RESISTOR) { Rx pulse_us / (1.1f * C_ref_uF); show_resistance(Rx); } else if (mode MODE_CAPACITOR) { Cx pulse_us / (1.1f * R_ref_kOhm); show_capacitance(Cx); }自动换挡逻辑是这样的当前挡位算出来的值如果超出本挡最佳量程就通过CD4066控制引脚切到下一挡再触发一次测量连切三次还是超范围就显示超出量程。自动换挡虽然会带来一点延迟但换来的是从几十皮法到几百微法都能自动找到合适的挡位体验比手动按键好很多。4. 标定流程与误差分析4.1 误差来源逐项拆解我先把误差来源列一下。第一NE555本身的阈值精准度。理想单稳态公式里的1.1是个近似系数实际芯片内部比较器的分压电阻有一定离散性大概在1%到3%之间这是所有NE555方案的固有偏差。第二基准电容、基准电阻自身的精度。普通的CBB电容标称5%金属膜电阻标称1%它们直接把误差传给结果。这也是我建议基准电阻至少选1%精度基准电容尽量选CBB或涤纶的原因。第三定时器时基误差。STM32使用8M晶振晶振本身的精度一般20ppm几乎可以忽略但如果直接使用内部RC振荡器误差可能会到1%以上。所以晶振一定不要省。第四PCB寄生电容。测量小电容时影响非常明显哪怕是两块焊盘之间的寄生电容都能让10nF以下挡位的读数偏离几个百分点。第五CD4066的导通电阻在低阻挡会有零点几欧的贡献对小电阻测试影响大。把这些叠在一起普通DIY如果不做标定误差大概率在3%到5%这个精度做定性判断够用但做元件配对筛选就很勉强。想达到1%量级必须校准。4.2 软件标定的具体做法我的标定思路很直接准备几个已知高精度的电阻和电容分别测量然后用实际值反推修正系数。比如测10k电阻时标称值10000欧实际测量值是9850欧说明这一挡存在大约1.5%的整体系统偏差。我把它折算成一个比例系数存到Flash里之后每次计算都乘上这个系数。电阻挡和电容挡分别标定因为两者的误差源不同。对同一挡位我至少选两个点做标定一个接近量程下限一个接近量程上限。如果两个点的修正系数一致就说明系统线性度好用一个系数就行如果系数不一致我会用线性插值修正。实测下来NE555单稳态的线性度其实相当不错大部分挡位一个系数就够了。提示标定之前先给设备通电预热5分钟让芯片温度稳定下来。NE555的阈值电压会随温度略有变化热稳定后再标定比一开机就标定准确得多。4.3 实测数据与误差对照下面是我用这套设备测出来的一组数据基准电阻是10k的金属膜电阻基准电容是100nF的CBB电容标定之后得到的对比待测元件标称值实测脉宽(us)计算值万用表/示波器参考值偏差10k电阻112310.21k10.03k1.8%100k电阻11045100.4k99.8k0.6%330k电阻36520332.0k331.5k0.15%10nF电容11610.55nF10.2nF3.4%100nF电容109899.8nF99.5nF0.3%1uF电容110201.002uF995nF0.7%小电容挡偏差大主要原因就是PCB和引脚上的寄生电容并联到了基准电容上导致计算值偏大。解决方法是测量小电容时先把测试夹悬空测一次基准值作为“零容”再用待测电容减去这个零容值能明显改善。比如10nF那组零容值是十几pF减掉之后偏差就降到1%以内了。5. 常见问题与排查技巧实录5.1 读数跳动、偏差大怎么查很多朋友做出来第一版最常见的现象就是读数不停跳。按照下面的顺序排查基本能解决先用示波器看NE555输出波形如果波形边缘有毛刺检查5V供电纹波和退耦电容NE555的VCC旁边加一个100nF的陶瓷电容必不可少如果波形正常但读数跳多半是接触不良测试夹或杜邦线松动再不行就检查STM32的输入捕获引脚是否被其他外设复用PA0经常被调试接口之类占用。故障现象可能原因处理办法读数随机跳动电源纹波、滤波不够增加100nF退耦、加中值滤波误差偏大且固定需要标定做单点或两点标定小电容测不准寄生电容干扰用零容测量法扣除大电阻没反应超时时间太短拉长超时周期到100ms高电平烧不进MCU电平不匹配串电阻或3.3V稳压5.2 测量范围异常与换挡失效我遇到过最奇怪的问题切换挡位后数值完全不对。查了半天发现是CD4066的两个通道引脚顺序接反了导致该通的通道没通不该通的反而通了。模拟开关不是机械开关导通方向没有区别但引脚分布容易看错接线前一定要对着数据手册核对一遍。另一个常见情况是大电容测量时STM32已经切换到下一挡但上一挡的电容还在充电放电管没有完全把电荷放完。单稳态触发后7脚放电路径导通理论上是放电很快但有些电解电容的残余电压需要更长时间泄放。我后来在每次测量结束后加了一个20ms的放电等待问题就消失了。5.3 我的一点实操心得做完这台仪器我最大的体会是精度不是靠堆元件而是靠标定和系统设计。NE555的边缘精度其实很普通但它胜在线性度高、重复性好只要把基准元件和软件修正搞定就能让一台元器件成本不到20块的小工具干出接近桌面LCR表的活。如果你也想做建议从万用表能测准的范围起步先做10k电阻和100nF电容这两挡把波形、读数、误差全部调通之后再加量程和自动换挡。别一上来就追求几十皮法和几兆欧范围拉得越大要处理的坑就越多。做成之后平时选元件、配对电阻、估算电容真的比靠色环和丝印靠谱太多。
返回列表