基于GD32F407使用ADC读取电压
背景
手上一个新的项目需要用到ADC进行电压检测,由于我也是第一次使用GD32所以在这里记录下,项目上有20多处需要进行电压检测,根据需求采用的是轮询的方式去查看电压值。
代码实现
以下都是我需要进行的ADC配置引脚
初始化IO和时钟
rcu_periph_clock_enable(RCU_GPIOF); //使能GPIO
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOB);
gpio_mode_set(GPIOF, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | \
GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10); //配置读取ADC引脚
gpio_mode_set(GPIOB, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \
GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \
GPIO_PIN_4 | GPIO_PIN_5);
rcu_periph_clock_enable(RCU_ADC1); //使能ADC时钟
rcu_periph_clock_enable(RCU_ADC2);
adc_clock_config(ADC_ADCCK_PCLK2_DIV6); //配置ADC时钟为PCLK2的4分频
ADC相关配置
adc_external_trigger_config(ADC2, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_DISABLE); //配置触发方式为软件触发
adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_DISABLE);
adc_software_trigger_enable(ADC2, ADC_REGULAR_CHANNEL); //使能ADC软件触发
adc_software_trigger_enable(ADC2, ADC_REGULAR_CHANNEL);
adc_data_alignment_config(ADC2 ,ADC_DATAALIGN_RIGHT); //数据对齐方式,靠右对齐
adc_data_alignment_config(ADC1 ,ADC_DATAALIGN_RIGHT);
adc_channel_length_config(ADC2, ADC_REGULAR_CHANNEL, 8); //配置使用ADC2规则通道,使用8个
adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, 15); //配置使用ADC1规则通道,使用15个
adc_resolution_config(ADC1, ADC_RESOLUTION_12B); //设置分辨率为12位
adc_resolution_config(ADC2, ADC_RESOLUTION_12B);
adc_external_trigger_config(ADC2, ADC_REGULAR_CHANNEL, ENABLE); //外部触发
adc_enable(ADC2);
mdelay(1);
adc_calibration_enable(ADC2); //进行ADC子校准
adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE);
adc_enable(ADC1);
mdelay(1);
adc_calibration_enable(ADC1); //进行ADC子校准
获取ADC转换值
static u16 get_adc_ch(u32 bus, u8 num, u8 ch)
{
adc_regular_channel_config(bus, 0, ch, ADC_SAMPLETIME_56); //ch参数为ADC通道:ADC_CHANNEL_x x = 0...15
adc_software_trigger_enable(bus, ADC_REGULAR_CHANNEL); //使用软件触发
while(!adc_flag_get(bus, ADC_FLAG_EOC)); //等待转换结束
adc_flag_clear(bus, ADC_FLAG_EOC);
return (adc_regular_data_read(bus) & 0xFFFF);
}
ADC求平均
为了得到相对稳定的值可以进行求平均的方式得到
u16 adc_channel_value(u32 bus, u8 num, u8 ch)
{
u32 adc_value = 0;
u32 i = 0;
for(i = 0; i < 5; i++)
{
adc_value += get_adc_ch(bus, num, ch);
}
//return ((adc_value / 5) * 3.3f / 4096.0f);
return (adc_value / 5);
}
将ADC值转换为电压值
芯片使用的是3.3V供电,根据上面的配置ADC,精度为12位可以得到
电压值 = ADC数值 * 3.3 / 4096
Vin = adc_value * 3.3 /4096
voltage = data * 3.3f / 4096.0f;