ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

STM32交流采样链路设计:互感器信号调理与RMS计算全解析

STM32交流采样链路设计:互感器信号调理与RMS计算全解析 简介一套基于STM32F103的智能电表交流电压电流检测与远程监控方案采用TV1005M电压互感器与TA1005M电流互感器采集交流信号结合WiFi模块与手机APP可实时查看电压、电流、功率、电量当功率超过200W时自动断开继电器也可手动控制。整个资源包共84个文件以带详细备注的C语言源程序为主36个.h、34个.c同时包含Keil工程文件、hex烧录文件、PCB设计PDF、元器件清单xls以及手机端apk安装包压缩后仅952KB结构清晰便于查找。已有607人浏览学习配套资料完整器件清单可一对一无缝使用。这套设计不仅适合电子竞赛、课程设计直接参考也可作为智能电表、物联网能耗监测产品的原型基础。通过源码和PCB文件读者能深入理解交流采样原理、互感器接线方法、WiFi透传通信、继电器过流保护等关键技术并快速移植到自己的项目中。1. 互感器进 STM32 之前先把测量链路想清楚做智能电表最容易被低估的不是 ADC 精度而是“电压电流怎么安全地送进单片机”。市电 220V 是致命信号任何直接分压进 ADC 的方案在工程上都不合格。用 TV1005M 电压互感器和 TA1005M 电流互感器把强电转为弱电小信号再经运放调理进 STM32 的 ADC是当前最稳妥也最主流的做法。这篇写的就是这条完整链路从互感器输出特性、信号调理参数计算到 STM32 的多通道采样策略、有效值算法、校准方法和常见坑。适合正在做电能计量、智能断路器、物联网电表或者实验室交流测量项目的开发者默认你已经能跑通 STM32 的基础工程本文重点放在模拟链路设计和采样程序上。很多人把程序写对了但读数不对问题几乎都出在偏置电压没算准或者两个互感器的输出没有统一到同一个 ADC 量程内。下面先从互感器的真实输出说起。2. TV1005M 与 TA1005M 的输出特性及信号调理电路参数计算2.1 两种互感器的本质区别电压型与电流型输出TV1005M 是电压互感器外形像一个小变压器本质是一个微型电压隔离器原边和副边绕组匝比接近 1:1但原边串了大阻值电阻把市电高压转换成额定的小电流副边并联精密电阻取电压信号。TA1005M 是电流互感器穿心式结构原边是穿过互感器中心孔的那根导线副边输出与初级电流成比例的交流电流信号按照 1000:1 的匝比原边 5A 时副边输出 5mA。千万不要直接把这个 5mA 电流送 ADC必须先经过并联取样电阻转换成电压。这两种互感器共用一个关键设计思路次级输出的是与待测信号成线性比例的小信号必须经过 I-V 转换或者分压匹配把信号幅度调整到 STM32 ADC 的最佳输入范围同时加上 1.65V 左右的直流偏置让交流信号在 ADC 的 03.3V 输入范围内心摆动。2.2 电压通道信号调理采样电阻与偏置电路参数计算TV1005M 的典型线性工作区是输入电压在 01000V 范围内保持比例输出。数据手册给出的额定输入是 2mA原边和副边的电流相同副边输出也是 2mA。副边并联的取样电阻决定了你能得到多大的交流电压摆幅。以市电 220V 为例原边需要串联一个限流电阻R 限流 220V / 0.002A 110kΩ工程上常用 100kΩ 和 10kΩ 两个电阻串联既达到阻值又留出耐压余量避免单个贴片电阻承受 220V 的峰值约 311V可能导致击穿。两个电阻各分担一半电压应力可靠性明显更好。副边取样电阻选多大取决于你给后级运放分配多少的输入摆幅。住往取 100Ω 左右这样在 220V 输入时副边输出有效值为 0.2V峰值约 0.28V。这个幅度直接进 STM32 ADC 太小了因为 ADC 参考电压是 3.3V最小分辨率约 0.8mV0.28V 的峰值摊到 4096 个码值上只用了约 340 个码严重浪费分辨率。所以电压通道要加一级放大把 0.2Vrms 放大到 1.3Vrms 左右。放大倍数 Av 1.3 / 0.2 6.5用同相比例运放电路来搭Rf 5.6kΩRg 1kΩAv 1 5.6 / 1 6.6非常接近。运放供电用 3.3V 单电源同相端需要提供一个 1.65V 的偏置常用两个 10kΩ 电阻分压 3.3V 得到 1.65V再经过一个 10uF 电容并联一个 0.1uF 电容做低阻抗去耦。2.2.1 电压通道运放直流偏置必须为 ADC 量程中点为什么偏置一定要放在 1.65V因为 STM32 ADC 只接受正电压交流信号有正有负不抬高电平就会削底导致负半周完全测量不到。把信号整体平移 1.65V 后交流波形的峰谷在 0.3V 到 3.0V 范围内摆动满足 ADC 输入要求。注意一个细节偏置电压的精度直接影响测量结果的零点偏移。如果分压电阻误差导致偏置漂到 1.62V软件做 RMS 计算时如果仍按 1.65V 减掉偏置就会产生一个恒定的直流分量误差。这个误差在低电压小电流时会被放大成很大的百分比误差。更稳的做法是运放输出端加一个 1kΩ 电阻再加 100nF 电容到地构成一个低通滤波器截止频率约 1.6kHz滤掉高频噪声和采样开关引入的毛刺同时保护 ADC 引脚不过压。2.3 电流通道信号调理取样电阻决定量程TA1005M 的副边额定输出电流为 2mA 对应初级 2A 穿心电流时。不对这里要校准一下说法TA1005M 的变比是 1000:1副边输出电流等于原边电流除以 1000原边 5A 时副边 5mA。如果副边取样电阻用 10Ω则 5A 输入时取样电压为 50mVrms用 33Ω 就是 165mVrms。实际设计时先确定最大测量电流再反推取样电阻。比如计划最大测 10A副边电流 10mA希望 ADC 输入端满幅约 1.5Vrms那么取样电阻和放大倍数的组合可以这样计算取样电阻取 20Ω得到 0.2Vrms再放大 6 倍就是 1.2Vrms。这个幅值在 12 位 ADC 下已经足够保证 0.1A 以下小电流的测量分辨率。电流通道的运放电路与电压通道完全一致偏置同样是 1.65V放大倍数根据取样电阻单独调整。注意 TA1005M 的相位误差在中大电流段比较小但在 1A 以下会明显增大低功率因数场景下功率计算的误差会变大这个后面在程序里可以通过软件校准修正。电压通道: TV1005M - 取样电阻100Ω - 同相放大6.6倍 - RC滤波 - PA0(ADC1_IN0) 电流通道: TA1005M - 取样电阻20Ω - 同相放大6倍 - RC滤波 - PA1(ADC1_IN1)两个通道最好用同一路运放的同一个偏置源这样共模抑制比更高电源纹波对两路信号的影响方向一致在软件里做差分计算时能抵消一部分。这个接法在模拟布局上很关键很多自制电表在电源纹波大时读数跳动就是因为两个通道偏置各走各的纹波引入的方向不一致。3. STM32 交流采样程序设计的关键过零对齐与 RMS 算法选型3.1 为什么不能用直流采样那套直接读 ADC 求平均直流信号采样只需要读一次或者多次取平均交流信号则完全不同。市电 50Hz周期 20ms如果只在一个随机时刻点采样一次你读到的是正弦波上的某个瞬时值完全不能代表有效值。即使多采几次取平均只要采样点没有覆盖完整的整数个周期平均结果里会残留与初相位相关的分量。由此得到交流采样设计的第一原则必须同步采样一个完整周期或多个完整周期的等间隔点才能算出正确的 RMS 有效值。等间隔要求对 STM32 来说就是用定时器触发 ADC而不是靠软件循环里ADC_GetFlagStatus轮询。同时采样窗口必须是整周期。对 50Hz 信号采样 20ms 就能覆盖一个整周期。如果采样点数是 N采样频率就是 N / 20ms。常见选择是每周波采样 128 点或 256 点对应采样频率 6.4kHz 或 12.8kHz远低于 STM32 ADC 的最高采样率所以 CPU 负担并不重。3.2 软件过零检测做周期同步的问题与替代方案有些方案通过检测交流信号的过零点来触发采样中断实现每周波自动同步。具体做法是比较器输出过零信号STM32 的外部中断捕获过零时刻然后启动定时器按固定间隔采样 N 个点。这个思路理论可行但工程上有两个难点一是过零时刻容易受谐波和噪声干扰信号在零点附近抖动超过比较器滞回窗口就会产生误触发造成采样窗口错位RMS 结果周期性跳变二是过零触发后需要软件精确调整第一个采样点的相位逻辑复杂且调试成本高。更常用的做法是用固定频率采样配合 1s 滑动窗口内的平均整周期对齐。但更简洁的做法是用定时器固定频率连续采样连续采集超过一个周期长度例如 20ms 采 128 个点实际上可以连续采 129 个点取最后 128 个点计算 RMS。下一个周期重新取新的一组 128 点。由于采样时钟与市电频率存在微小偏差每周波的采样点数会有轻微波动但只要保证窗口长度覆盖足够的完整周期RMS 结果的精度在 0.5% 以内是可以做到的。3.3 RMS 有效值计算的两种实现标准公式与逐点累加标准交流有效值的定义是对 u(t) 在一个周期内先平方、再求平均、最后开方。离散化到 N 个采样点U_rms sqrt( (1/N) * Σ u[i]^2 )这个公式在 STM32 上直接用浮点算每周波 128 次平方和累加循环次数很少20ms 内完成计算完全没问题。关键是每个 u[i] 要先减掉直流偏置再平方否则偏置的直流分量会被当成有效值算进去导致结果虚高。拿上一章的电路参数来说如果偏置是 1.65VADC 读到 1.65V 对应 2048 码采样值减 2048 再按比例换算成实际电压才是真正的交流瞬时值。电流通道同理。但要注意互感器在大电流时会轻微饱和导致有效值输出略偏低。校正的办法是在程序里做分段线性修正电流在 0.5A 以下乘修正系数 1.020.5A 到 5A 乘 1.0055A 以上乘 0.98。这种处理不能完全消除互感器的非线性但对智能电表常见的 0.5 级计量要求已经足够。// 伪代码: 128点RMS计算忽略定时器配置细节 float adc_value, sum_sq 0; for (i 0; i SAMPLES; i) { adc_value (float)adc_buf[i] / 4096.0f * 3.3f; // ADC码转实际电压 adc_value - 1.65f; // 减去直流偏置 sum_sq adc_value * adc_value; } float rms sqrtf(sum_sq / SAMPLES);这段代码的关键在第二行减法。adc_buf[i]是 DMA 搬运到内存的原始采样值转成电压后先减偏置再平方累加。这样求出的 rms 是纯交流有效值。如果偏置漂移了最简单的方法是运行时定期采一个静态零点通道把偏置实时测出来而不是用一个常量。4. STM32 多通道 ADC 采样程序设计定时器触发、DMA 双缓冲与任务调度4.1 用定时器触发 ADC 实现精确等间隔采样交流采样最忌讳用while(1)循环里软件延时来触发 ADC因为中断响应延迟和代码执行时间抖动会直接变成采样间隔的相位噪声。正确的做法是用定时器的更新事件作为 ADC 的外部触发源。STM32 系列里典型配置是TIM2 的更新事件连接到 ADC 的触发输入预分频器和自动重载寄存器把触发频率设置为 6.4kHz即每周波 128 点。这样 ADC 的采样时刻由定时器硬件精确控制软件不需要干预CPU 可以在采样间隙做显示刷新、按键扫描和通讯任务。配置时的注意点是ADC 要工作在扫描模式并设置好通道采样时间。交流信号采样不需要太快的采样时间把采样周期设定为 28 个 ADC 时钟周期左右即可太短反而容易采到前一次采样保持电容上的残余电荷导致相邻采样点之间出现通道串扰。// ADC 和定时器初始化要点以 STM32F103 为例 void ADC_TIM_Sample_Init(void) { TIM_TimeBaseInitTypeDef TIM_InitStructure; ADC_InitTypeDef ADC_InitStructure; // TIM2 触发频率 72MHz / (711) / (1571) ≈ 6.4kHz TIM_InitStructure.TIM_Period 157; // 自动重装载值 TIM_InitStructure.TIM_Prescaler 71; // 预分频 TIM_TimeBaseInit(TIM2, TIM_InitStructure); ADC_InitStructure.ADC_Mode ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode ENABLE; // 多通道扫描 ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_T2_TRGO; ADC_InitStructure.ADC_NbrOfChannel 2; // 电压电流两通道 ADC_Init(ADC1, ADC_InitStructure); }定时器的 Period 和 Prescaler 计算方法很简单72MHz 时钟先除以 72 得 1MHz再除以 158 约等于 6329Hz对应每周波 126.6 点与 128 点目标略有偏差。要精确做到 6400Hz需要预分频改大一些但保持整除关系或者直接使用 64MHz 主频配合整除参数。对 RMS 计算来说采样频率偏差在 1% 以内对结果影响非常小因为算法本身对非整周期采样有平均效应所以不用追求绝对精确。4.2 DMA 双缓冲避免采样与计算互相阻塞单缓冲模式下DMA 采样满 128 点会产生一次传输完成中断CPU 在中断里计算 RMS计算期间如果定时器继续触发 ADCDMA 会覆盖正在使用的缓冲区数据就乱了。解决方法是双缓冲机制。双缓冲的逻辑是开辟两个同样大小的数组DMA 交替填充。CPU 处理 Buffer A 时DMA 正在写 Buffer B下一次 DMA 写满 Buffer B 后自动切回 Buffer A同时 CPU 刚好处理完 Buffer B 的数据。两个环节乒乓交替互不阻塞。在 STM32F1 系列里没有硬件双缓冲寄存器需要自己在 DMA 传输完成中断里切换缓冲区指针。F4 及以上系列有双缓冲模式寄存器可以直接配置。以 F103 为例// 两个缓冲区, DMA 交替写入 volatile uint16_t adc_buf[2][128]; volatile uint8_t buf_index 0; void DMA1_Channel1_IRQHandler(void) { if (DMA_GetITStatus(DMA1_IT_TC1)) { DMA_ClearITPendingBit(DMA1_IT_TC1); buf_index ^ 1; // 切换缓冲区 Process_RMS((uint16_t *)adc_buf[buf_index ^ 1]); // 处理刚填满的那一半 DMA_SetCurrDataCounter(DMA1_Channel1, 128); DMA_Cmd(DMA1_Channel1, ENABLE); } }Process_RMS函数接收刚被 DMA 填满的缓冲区指针计算电压、电流有效值。由于 DMA 需要关闭再重新打开才能重新装载传输计数器在这个空档里定时器不会停止所以会丢掉几微秒的采样但 128 点的窗口偶尔少一个点对 RMS 精度影响可以忽略。把计算放在中断里确实会增加中断服务的执行时间但如果主循环还需要做其他事情更好的做法是中断里只设置一个data_ready标志位主循环检测到标志后处理数据。不过要注意两个周期的时间是 20ms主循环只要在 20ms 内完成计算就不会丢数据。4.3 多通道采样时的通道顺序与采样周期分配ADC 扫描模式下通道的转换顺序由ADC_RegularChannelConfig里的 Rank 参数决定。电压通道和电流通道要交替转换避免两个通道在同一个扫描周期内相隔太远导致电流采样时刻相对电压采样时刻有明显偏移。假设 Rank1 是电压通道Rank2 是电流通道ADC 会先转换 PA0 再转换 PA1两个通道转换完成的时间间隔约为 28 个 ADC 时钟周期在 72MHz 下约 0.39us。这个时间差折算到 50Hz 信号上约为 0.007°完全可以忽略。更关键的一点是每通道的采样时间要分别配置。如果电压通道输出阻抗较高需要更长的采样时间让采样电容充分充电电流通道输出阻抗低则可以短一些。两种通道用同一个采样时间如果阻抗特性差异太大读数会有可见的幅度误差。ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_28Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_28Cycles5);通道配置函数最后那个参数就是采样周期28Cycles5表示采样阶段占 28.5 个 ADC 时钟周期。如果前级运放的输出阻抗在 1kΩ 以下这个采样时间足够如果输出阻抗偏高应改用55Cycles5甚至71Cycles5换取更准确的采样值。判断是否够用可以在输入一个直流电平时观察 ADC 转换结果是否稳定如果相邻采样点之间有明显的阶梯波动就要提高采样周期。4.4 三相场景下的通道扩展问题如果做三相四线电表需要采集三路电压和三路电流一共 6 个通道。STM32F103 的 ADC1 有 16 个外部通道可以一次扫描 6 个通道顺序配置成 Ua、Ia、Ub、Ib、Uc、Ic 交替排列。但要注意两个问题。一是 ADC 扫描 6 个通道后一路完整扫描的周期变长在 28.5 周期采样时间和每种通道各 6 个通道的情况下一次扫描约为 171 个 ADC 时钟周期约 2.4us。这个时间对 50Hz 信号不是问题但定时器每次触发只能完成一轮扫描6 点一组速率为定时器频率。要保证每周波每组有 128 点触发频率依然是 6.4kHz每组 6 个通道共需要 6.4k × 6 38.4k 次转换每秒F103 的 ADC 最大约 1MHz 转换速度完全能承受。二是多通道时 DMA 缓冲区要相应扩大adc_buf[6][128]或者线性数组adc_buf[768]。处理数据时注意每个通道的数据分布在一个扫描周期内的固定位置也就是每 6 个点里第 0 号是 Ua第 1 号是 Ia依次类推。取第 k 个采样点时实际数组下标是 k × 6 channel_index。5. 校准方法与误差修正技巧用标准源把读数校准到 0.5% 以内5.1 空载校零消除偏置电压漂移在输入端不加任何信号电压通道短接电流通道不穿导线的情况下程序里读到的 RMS 值应该是零。但实际上由于偏置电路电阻误差、运放失调电压和 ADC 本身的零点偏移计算出来的 RMS 通常不是零而是一个几毫伏的小值。解决方法是做软件校零上电启动后延时 2 秒待电路稳定连续采集 20 个周期计算平均 RMS 值把这个值记录为零点基准后续每次测量结果都减去这个基准。注意校零时一定要保证输入端确实没有信号如果设备已经接在电路上校零会把真实信号误当成零点减掉造成严重测量误差。5.2 用标准源做分段增益校正增益校准的思路是用一个已知精度的交流源输出标准电压比如 220.0V程序读取计算出的 RMS 原始值得到增益系数 K 标准值 / 测量值。把这个系数存进 Flash运行测量时乘以 K 即可。但一个系数不够用因为 TV1005M 和 TA1005M 在小信号时线性度下降。所以要做分段增益校正在满量程的 5%、20%、50%、80%、100% 五个点分别记录增益系数存储在 Flash 里。程序运行时根据当前测量值所在的区间用相邻两个点的系数做线性插值。电压通道的分段校准相对简单电流通道要特别注意相位差的影响。如果后续要做功率计算电流和电压之间还有一个相位偏移这个偏移来自互感器和运放的相位延迟。功率因数为 1.0 时相位误差影响不明显但功率因数为 0.5 时1° 的相位误差会造成约 3% 的功率误差。所以高精度智能电表一定要做相位校准。5.3 相位误差修正旋转矢量法相位校准的方法是在标准源上设置一个纯阻性负载即电压和电流同相位功率因数为 1.0记录此时计算出的功率值 P1。然后在相同电压电流幅值下把负载换成纯感性或容性功率因数为 0功率计的示数应该接近零。不为零的部分就是相位误差导致的。修正时需要把电压和电流的离散采样点分别做正余弦变换用旋转矢量法把电流的采样点相对于电压做微小的时间偏移。具体做法是对电流通道的 128 个采样点在软件里按照偏移角度对相邻两个采样点做线性插值等效于把电流波形沿时间轴平移。相位校准系数用一个浮点数保存范围通常是 -0.1° 到 0.1°。计算功率时每周期把角度换算成采样点数对电流采样序列做插值平移后再与电压相乘累加。这个操作在 F103 上占用约几百微秒20ms 的周期内做一次完全可行。5.4 用示波器验证采样时序是否符合预期程序写完以后先在输入端加载一个稳定的正弦信号用示波器观察 PA0 和 PA1 的波形确认运放输出没有削顶或者削底。然后加一个干路电阻测量实际的电压电流数值与标准万用表比对。如果程序里配置了合适的调试引脚可以在 DMA 传输完成中断里输出一个 10us 的高电平脉冲用示波器测量脉冲间隔是否正好等于 156.25us对应 6.4kHz验证 ADC 触发频率是否正确。这个技巧在查采样频率配置错误时非常有效不需要仿真器也能定位。最后一招是用内置的 CRC 或串口打印方式输出原始采样值在 PC 端用 Python 脚本做离线 FFT观察频谱里的 50Hz 分量是否正常如果频谱出现了明显的 100Hz 分量说明偏置减法没有做干净回去检查零点校准逻辑。这个验证方法不花成本但能直接暴露很多隐蔽的问题。本文还有配套的精品资源点击获取
返回列表