STM32 测量交流电压的方法

关于STM32测量交流电的一种方法.

关于交流电压测量的难点有以下几点:1.电压过大,比如市电220V,2.交流电和直流电区别很大,例如值一直在变不稳定.3.交流电压存在负值,STM32 的AD模块没法测量.4.STM32读取的电压值是瞬时值和交流电的有效值还要转换.

针对以上几点:可以采取合适的硬件设计和算法设计解决.采用电流互感器将电压从高变低,采用直流电压叠加的方式将整体的交流波形抬升,抬升到最低都大于零.至于读取到的数值采用均方根的算法算出交流有效值.另外还要注意一点是采样周期的设置.

电路设计:

出自https://wenku.baidu.com/view/7afdd93bb9f3f90f77c61bee.html

这个硬件电路设计很完善.还有一种:

 

第二种电路结构更简单,但是运放采用的是用于测量交流信号的MCP6292.

两种设计的思路大致相同,都是互感器降压,降压信号放大,直流叠加,然后测量.

下面是对交流电压有效值算法的数学推导,(这里我用的是和交流电压相似的一个物理量,可以理解成交流电压的有效值算法)

 

针对第二种电路图程序如下:

取一百个点测算变压器二次端的电压有效值然后根据放大倍数和变压器的比率算出实际接入电压的有效值.

注意转换时间要短.Uac的值除以放大倍数(4),就是接在160Ω电阻的电压,再除以160就是流过电流互感器两边的电流,乘以300K就是接入的交流电压有效值.

 

        void  Adc_Init(void)
{ 	
	ADC_InitTypeDef ADC_InitStructure; 
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1	, ENABLE );	 
 

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);                      
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		
	GPIO_Init(GPIOA, &GPIO_InitStructure);	

	ADC_DeInit(ADC1);  

	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	
	ADC_InitStructure.ADC_NbrOfChannel = 1;	
	ADC_Init(ADC1, &ADC_InitStructure);	
	ADC_Cmd(ADC1, ENABLE);	
	ADC_ResetCalibration(ADC1);	
	 
	while(ADC_GetResetCalibrationStatus(ADC1));	
	
	ADC_StartCalibration(ADC1);	
 
	while(ADC_GetCalibrationStatus(ADC1));	
 


}				  

u16 Get_Adc(u8 ch)   
{
  	
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_13Cycles5 );	 			    
  
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		
	 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));

	return ADC_GetConversionValue(ADC1);	
}

u16 Get_Adc_Average(u8 ch,u8 times)
{
	u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val+=Get_Adc(ch);
		delay_ms(5);
	}
	return temp_val/times;
} 	 




                int main() 
               {
                for(j=0;j<100;j++)
		{
				adcx=Get_Adc_Average(ADC_Channel_1,1);
				Num[j] = (float)adcx*(3.3/4096)-1.24;
				u1+=Num[j]*Num[j];
				
		}
			u1 = sqrt(u1/100);
		temp = u1*468.75;
		LCD_ShowxNum(172,192,temp,3,24,0);
              }

 

 

 

  • 51
    点赞
  • 461
    收藏
    觉得还不错? 一键收藏
  • 26
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值