1.STM32CubeMX的基础配置
首先勾选Serial Wire(串行线配置调试), 使用内部时钟
勾选ADC1,根据需要配置对应的采集通道(见下图)
Clock Prescaler:是ADC工作频率,选择Asynchronous clock mode divided by 2(2分频)。
Resolution :ADC分辨率,设置为12位分辨率。
Data Alignment:数据对齐方式,配置为右对齐。
Sequencer:Sequencer set to fully configurable (完全序列模式)。
Scan Conversion Mode:ENABLE扫描转化模式。
Continuous Conversion Mode:ENABLE连续转换模式,这种模式下,ADC会持续不断地采样并转换模拟信号,并且对所有通道进行一 次转换,随后会自动重启并持续执行相同的转换序列
DMA Continuous Requests:ENABLE允许外设在每次数据传输完成后自动发出请求。这个请求会持续地触发DMA传输,直到传输完成或被外部事件停止。
End Of Conversion Selection:ENABLE End of Single Conversion(单次转换结束)。
SamplingTime Common 1 :设定采样周期。
Number Of Conversion:转换通道数,数值代表一次性转换几个通道。
External Trigger Conversion Source :此处选择软件触发方式。
配置DMA:
DMA选择Circular,开启不断循环;Half Word存放uint16_t类型数据
采用内部时钟,DMA中断默认打开,ADC中断不打开,定义好之后直接生成。
ADC采样时间计算:
1.ADC采样时间长短由分频系数和采样周期决定,计算公式:转换时间=采样周期+12.5周期
eg:工程里面的时钟频率是64MHZ,T = 1/f = 1/64=0.015625;则55.5+12.5 = 68周期,68*1/64 = 1.0625us。
2.由于要采集频率为50HZ,220V的交流电,硬件方面需要做好采集和隔离使其产生的信号能快速的让ADC采集到,此处具体电路不做论述;ADC采集的思路:利用交流电20ms产生一个周期的波形,设置定时器1ms触发一次中断,在中断服务函数里面循环读取20msADC采集的瞬时值,这20ms的值就是市电的一个周期,之后将20次数据之和就可以判断市电是否接入。
static uint8_t ADC_Count = 0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
if(AdcHandle->Instance == ADC1)
{
ADC_Count++;
if(ADC_Count >= 20)
{
// 清零临时存储
adcValue.value1 = 0;
adcValue.value2 = 0;
adcValue.value3 = 0;
adcValue.value4 = 0;
adcValue.value5 = 0;
adcValue.value6 = 0;
for(uint8_t i=0;i<20;i++)
{
adcValue.value1 += ADC_value[0+6*i];
adcValue.value2 += ADC_value[1+6*i];
adcValue.value3 += ADC_value[2+6*i];
adcValue.value4 += ADC_value[3+6*i];
adcValue.value5 += ADC_value[4+6*i];
adcValue.value6 += ADC_value[5+6*i];
}
ADC_Count = 0;
}
}
}
uint8_t Collect_data() //采集单次瞬时数据
{
// 处理瞬时值
total_sum1[count] = (adcValue.value1/20);
total_sum2[count] = (adcValue.value2/20);
total_sum3[count] = (adcValue.value3/20);
total_sum4[count] = (adcValue.value4/20);
total_sum5[count] = (adcValue.value5/20);
total_sum6[count] = (adcValue.value6/20);
count++;
if(count >= 20)
{
total_1 = 0;
total_2 = 0;
total_3 = 0;
total_4 = 0;
total_5 = 0;
total_6 = 0;
for(uint8_t i=0;i<20;i++)
{
total_1 += total_sum1[i];
total_2 += total_sum2[i];
total_3 += total_sum3[i];
total_4 += total_sum4[i];
total_5 += total_sum5[i];
total_6 += total_sum6[i];
}
if(total_1>=200) {PDU_stusta |= (1<<0);}
else {PDU_stusta &= ~(1 << 0);}
if(total_2>=200) {PDU_stusta |= (1<<1);}
else {PDU_stusta &= ~(1 << 1);}
if(total_3>=200) {PDU_stusta |= (1<<2);}
else {PDU_stusta &= ~(1 << 2);}
if(total_4>=200) {PDU_stusta |= (1<<3);}
else {PDU_stusta &= ~(1 << 3);}
if(total_5>=200) {PDU_stusta |= (1<<4);}
else {PDU_stusta &= ~(1 << 4);}
if(total_6>=200) {PDU_stusta |= (1<<5);}
else {PDU_stusta &= ~(1 << 5);}
count = 0;
}
return 0;
}