一種用單片機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電壓
	}
}


 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM