zoukankan      html  css  js  c++  java
  • 一种用单片机AD采样方式来检测交流市电电压的方法


    下面介绍一种用单片机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电压
    	}
    }
    


     

  • 相关阅读:
    Mysql复制表格
    MySql的导入与导出
    jQuery语法
    JavaScript中的test()方法
    Android解决java.lang.OutOfMemoryError: bitmap size exceeds VM budget(转)
    Android图片压缩方法总结
    Android实现app长时间未操作时自动退出app
    银行卡号的检测
    Android大图片裁剪终极解决方案(上:原理分析)
    Windows环境下Android Studio v1.0安装教程
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3278103.html
Copyright © 2011-2022 走看看