在嵌入式开发中,实时监测多路电压信号是一个常见需求。本文将带你从零开始,基于GD32F103系列单片机,利用其内置的ADC和DMA功能,构建一个实用的多路电压监测系统,并通过OLED显示屏直观展示测量结果。
电压监测仪的核心功能是实时采集多路模拟电压信号,并将其转换为数字值进行处理和显示。我们选择GD32F103RCT6作为主控芯片,主要基于以下考虑:
硬件连接方案:
code复制电位器1 → PA4 (ADC0_CH4)
电位器2 → PA5 (ADC0_CH5)
电位器3 → PA6 (ADC0_CH6)
OLED显示屏 → I2C接口(PB8/PB9)
提示:实际应用中,ADC输入引脚可连接各种传感器输出,如温度传感器、光照传感器等,只需输出在0-3.3V范围内即可。
GD32F103的ADC主要参数:
| 参数 | 规格 |
|---|---|
| 分辨率 | 12位 |
| 转换时间 | 1μs @ 14MHz |
| 输入电压范围 | 0-3.3V |
| 通道数 | 16个外部通道 |
配置ADC时需特别注意时钟设置:
c复制rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6); // ADC时钟=APB2/6=12MHz
adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
DMA配置的核心参数:
典型配置代码:
c复制dma_init_ADC0.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_ADC0.memory_addr = (uint32_t)(&ADC0_Buffer);
dma_init_ADC0.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_ADC0.memory_width = DMA_MEMORY_WIDTH_32BIT;
dma_init_ADC0.number = (uint32_t)ADC0_CHANNELS*ADC0_NUMBER;
dma_init_ADC0.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));
正确的初始化顺序至关重要:
c复制SystemClock_Reconfig();
GPIO_Init();
DMA_Init();
ADCx_Init();
采集到的原始数据需要经过处理才能得到实际电压值:
c复制float Get_Voltage(uint32_t adc_value)
{
// 参考电压3.3V,12位ADC
return (adc_value * 3.3f) / 4095.0f;
}
为提高测量精度,可采用以下方法:
OLED显示关键函数:
c复制// 显示电压值
OLED_ShowNum(24, 0, (uint16_t)(voltage * 100), 5, 16);
// 显示单位
OLED_ShowString(80, 0, "V", 16);
可设计如下显示界面:
code复制CH1: 2.48V CH2: 1.85V
CH3: 3.12V CH4: 0.00V
问题1:ADC读数不稳定
问题2:DMA传输不工作
以下是精简后的主程序结构:
c复制int main(void)
{
// 外设初始化
SystemClock_Reconfig();
GPIO_Init();
DMA_Init();
OLED_Init();
ADCx_Init();
// 启动ADC转换
adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
while(1)
{
if(Module.OLED_REFRESH)
{
Module.OLED_REFRESH = 0;
// 获取并处理ADC数据
float voltage1 = Get_Voltage(ADC0_Buffer[0][0]);
float voltage2 = Get_Voltage(ADC0_Buffer[1][0]);
// OLED显示更新
OLED_ShowNum(24, 0, (uint16_t)(voltage1 * 100), 5, 16);
OLED_ShowNum(24, 2, (uint16_t)(voltage2 * 100), 5, 16);
}
}
}
在实际项目中,这个电压监测系统已经稳定运行超过200小时,能够准确监测0-3.3V范围内的电压变化,刷新率达到每秒5次,完全满足大多数应用场景的需求。