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);
              }

 

 

 

LM158是一款运算放大器芯片,不具备ADC功能,因此无法直接使用它来采集电压。如果你需要采集220V电压,建议使用外部电阻分压将电压降低到可接受的范围内,然后使用STM32内置的ADC模块进行采集。 针对你的具体问题,可以按照以下步骤进行配置: 1. 将电压通过外部电阻分压降低到STM32的ADC输入电压范围内,一般为0~3.3V。 2. 将PE3引脚配置为模拟输入引脚。 3. 配置ADC模块,设置采样时间、采样通道、采样精度等参数。 4. 在代码中启动ADC转换,并读取采样结果。 以下是一个简单的示例代码,仅供参考: ```c // 配置PE3为模拟输入引脚 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); // 配置ADC模块 ADC_HandleTypeDef hadc; hadc.Instance = ADC1; hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; hadc.Init.Resolution = ADC_RESOLUTION_12B; hadc.Init.ScanConvMode = DISABLE; hadc.Init.ContinuousConvMode = DISABLE; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.NbrOfDiscConversion = 0; hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.NbrOfConversion = 1; hadc.Init.DMAContinuousRequests = DISABLE; hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; HAL_ADC_Init(&hadc); // 启动ADC转换 uint32_t adcValue = 0; HAL_ADC_Start(&hadc); HAL_ADC_PollForConversion(&hadc, 100); adcValue = HAL_ADC_GetValue(&hadc); HAL_ADC_Stop(&hadc); // 将采样结果转换为电压值 float voltage = adcValue * 3.3 / 4095; float inputVoltage = voltage / (R2 / (R1 + R2)); ``` 其中,R1和R2分别为分压电阻的两个电阻值,可以根据实际情况进行调整。
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值