下面介绍一种用单片机AD采样的方式检测市电电压的方法
要检测交流市电的电压,通常有两种方法
一、通过频繁的采样后再求平均值来获得实际电压值
二、通过采样交流市电的峰值,再通过算法得出实际电压值
这里我们讲述峰值采样法的步骤:
1、在正半波时,频繁采样市电AD值,在每次采样后进行
从小到大排序并保存几个最大值的结果,分别放在R_SaveVolAC[0]..R_SaveVolAC[3]
2、在负半波时,把刚才所采样到的几个值中,提取R_SaveVolAC[1]的值作为
上个正半波的的最大值。(R_SaveVolAC[2]、R_SaveVolAC[3]当作干扰给滤掉)
3、把N个上述这些正半波的最大值进行累加后除以N得到一个平均值,这个值就是峰值电压值
电路图如下:
以下为参考源代码实例: uint8 R_VolAc = 0 ; //输入电压值 uint8 R_SaveVolAC[4] = {0,0,0,0} ;//保存读AD时的峰值 //************************************** // 函数名称:ReadZ0 // 函数功能:检测过零信号 // 入口参数:无 // 出口参数:无 //*************************************** void ReadZ0(void) { uint8 Tcon=0 ; uint8 F_OK=0 ; do{ ReadVol_AC() ; //上半波时读AC电压值 Nop(5); if((P_ZER0 == 0)&&(F_PZL)) { Tcon++; } else if((P_ZER0 == 1)&&(!F_PZL)) { Tcon++; } else { Tcon = 0 ; } if(Tcon >= 5)F_OK = 1 ; }while(F_OK == 0); if(F_PZL) F_PZL = 0 ; else F_PZL = 1 ; } //************************************* // 函数名称:Order_Byte_F2 // 函数功能:选择法对数组从小到大排序 // 直接对传递的地址进行操作 // 入口参数:排序数据的首地址 // 出口参数:无 // 返 回 值:该列数据是的中间值 //*************************************** uint8 Order_Byte_F2(uint8 *a,uint8 DataLong) { uint8 i,j,k; uint8 tmp; for(i=0;i<DataLong-1;i++) { k=i; /*给记号赋值*/ for(j=i+1;j<DataLong;j++) { if(a[k]>a[j]) k=j; /*是k总是指向最小元素*/ } if(i!=k) { /*当k!=i是才交换,否则a[i]即为最小*/ tmp = a[i]; a[i] = a[k]; a[k] = tmp; } } i = DataLong >> 1 ; return a[i] ; } //************************************* // 函数名称:TestVolage // 函数功能:检测电源电压 // 入口参数:无 // 出口参数:无 //***************************************/ void ReadVol_AC(void) { if(F_PZL) //正半波检测电压 { Adc_Mode_Scan(DIS) ;//ADC AdcSwitch(ADC_Chanel2) ; R_SaveVolAC[0] = ADC_DRH ; Order_Byte_F2(R_SaveVolAC,4) ;//从小到大排序 } } //======================================= void CalculateVol_AC(void) { uint8 Tmp ; static uint16 R_SaveSum = 0 ; static uint8 Tcon = 0 ; if(!F_PZL) //在负半波时计算AC值 { //AC的在上半波的最大值-已经是最大值的中值 Tmp = R_SaveVolAC[1] ; R_SaveSum += Tmp ; ClrDataBuf_Byte(R_SaveVolAC,4) ; //清除AC缓冲区 Tcon ++ ; if(Tcon >= 32) { Tcon = 0 ; R_VolAc = R_SaveSum >> 5 ; //AC电压对应的AD值 R_SaveSum = 0 ; //再通过查表或算法得到实际AC电压值 } } } //******************************************** //********** 主函数 *********** //******************************************** void main(void) { Init_Device() ; while(1) { ReadZ0() ; //读过零信号 CalculateVol_AC() ; //计算AC电压 } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架