STM32 小白实战 07:ADC 单通道排错与四通道轮询采样
摘要昨天完成了 STM32F103 ADC1 单次转换和四通道轮询采样的代码整理。已确认的问题包括中文逗号导致 ADC_Init() 无法编译以及 ADC_DataAlign 字段误填 ADC_Mode_Independent。在多通道工程中PA0PA3 被配置为模拟输入程序并未开启扫描模式而是在每次调用 AD_GetValue() 时动态选择一个通道并完成一次软件触发转换。工程构建日志已确认 0 Error、0 Warning四路实物采样值和电压换算结果尚未提供统一标记为待确认。开发环境MCUSTM32F103C8T6IDEKeil μVision 5.35编译器ARMCC V5.06 update 7固件库STM32F10x 标准外设库ADCADC1独立模式输入引脚PA0、PA1、PA2、PA3对应通道ADC_Channel_0ADC_Channel_3ADC 时钟72 MHz ÷ 6 12 MHz转换方式软件触发、单次转换、软件轮询多通道显示模块OLED问题与解决1. ADC_Init() 出现乱码、参数不足等连续报错现象Keil 在 ADC_Init(ADC1ADC_InitStructure); 处连续报告 unrecognized token、标识符未定义和参数数量不足。原因ADC1 后使用了中文全角逗号。ARMCC 无法把中文标点识别为 C 语言分隔符因此一个中文逗号会连带触发多条编译错误。解决方法切换到英文输入法将中文逗号改为英文半角逗号ADC_Init(ADC1, ADC_InitStructure);验证结果该语法错误已定位并修正。后续上传的多通道工程构建日志显示 0 Error、0 Warning。2. ADC_DataAlign 字段填入了错误的枚举值现象ADC 初始化代码写成 ADC_InitStructure.ADC_DataAlign ADC_Mode_Independent;而上传工程仍能正常编译。原因ADC_DataAlign 应填写左/右对齐枚举。ADC_Mode_Independent 属于 ADC_Mode 字段。工程未报错是因为标准库里 ADC_Mode_Independent 与 ADC_DataAlign_Right 的宏值恰好都为 0数值碰巧相同不代表语义正确。解决方法明确分开配置工作模式和数据对齐ADC_InitStructure.ADC_Mode ADC_Mode_Independent;ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right;验证结果原因已确认。当前上传源码仍保留旧写法状态为“代码可编译但仍建议修正”。3. 四个模拟输入如何共用一个 ADC1现象PA0PA3 都需要采样但 ADC_NbrOfChannel 仍为 1扫描模式和连续转换均关闭。原因这份工程采用软件轮询多通道而不是扫描模式。每次 AD_GetValue() 先把指定通道配置到规则组第 1 顺位再完成一次软件触发转换因此单次转换始终只有一个通道。解决方法初始化时把 PA0PA3 配置为模拟输入读取时把通道作为参数传入uint16_t AD_GetValue(uint8_t ADC_Channel){ADC_RegularChannelConfig(ADC1, ADC_Channel, 1,ADC_SampleTime_55Cycles5);ADC_SoftwareStartConvCmd(ADC1, ENABLE);while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) RESET){}return ADC_GetConversionValue(ADC1);}图 1 工程源码中的四通道 ADC 软件轮询核心代码验证结果源码结构已确认是四通道软件轮询工程已成功编译。四路实物数值是否随输入电压正确变化待确认。4. AD_GetValue() 返回的不是电压现象OLED 直接显示 AD_GetValue() 返回值容易把显示数字当成伏特值。原因ADC 返回的是 12 位量化结果右对齐时范围通常为 04095不是直接的电压单位。解决方法先用原始值确认各通道能独立变化需要换算时使用实际参考电压Voltage AD_Value * Vref / 4095.0f;验证结果当前工程只显示四路原始 ADC 数值。实际 Vref、换算电压和误差待确认。5. ADC 初始化与单次采样流程容易混乱现象初始化涉及时钟、GPIO、工作模式、校准和转换等待代码较长学完后不容易记住。原因没有把代码压缩成“初始化主线”和“单次采样主线”。解决方法初始化主线开启时钟 → ADC 分频 → 模拟输入 → 独立单次模式 → 使能 → 校准。采样主线选择通道 → 软件启动 → 等待 EOC → 读取转换值。ADC_ResetCalibration(ADC1);while (ADC_GetResetCalibrationStatus(ADC1) SET){}ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1) SET){}图 2 上传工程的 Keil 构建日志0 Error、0 Warning验证结果上传工程构建日志确认 0 Error、0 Warning。该结果只证明完成编译和链接不代表实物采样已经正确。整理后的核心代码AD.c#include stm32f10x.h#include AD.hvoid AD_Init(void){GPIO_InitTypeDef GPIO_InitStructure;ADC_InitTypeDef ADC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_ADCCLKConfig(RCC_PCLK2_Div6);GPIO_InitStructure.GPIO_Mode GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_1 |GPIO_Pin_2 | GPIO_Pin_3;GPIO_Init(GPIOA, GPIO_InitStructure);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) SET) { }ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1) SET) { }}uint16_t AD_GetValue(uint8_t ADC_Channel){ADC_RegularChannelConfig(ADC1, ADC_Channel, 1,ADC_SampleTime_55Cycles5);ADC_SoftwareStartConvCmd(ADC1, ENABLE);while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) RESET) { }return ADC_GetConversionValue(ADC1);}main.cuint16_t AD0, AD1, AD2, AD3;int main(void){OLED_Init();AD_Init();OLED_ShowString(1, 1, AD0:);OLED_ShowString(2, 1, AD1:);OLED_ShowString(3, 1, AD2:);OLED_ShowString(4, 1, AD3:);while (1){AD0 AD_GetValue(ADC_Channel_0);AD1 AD_GetValue(ADC_Channel_1);AD2 AD_GetValue(ADC_Channel_2);AD3 AD_GetValue(ADC_Channel_3);OLED_ShowNum(1, 5, AD0, 4);OLED_ShowNum(2, 5, AD1, 4);OLED_ShowNum(3, 5, AD2, 4);OLED_ShowNum(4, 5, AD3, 4);Delay_ms(100);}}固定排查清单检查逗号、括号、分号是否误用了中文全角符号。检查 ADC_Mode 和 ADC_DataAlign 是否填入各自对应的枚举值。检查 ADC 输入引脚是否配置为 GPIO_Mode_AIN。检查 PA0PA3 是否分别对应 ADC_Channel_03。检查 ADC 时钟分频本工程为 12 MHz。单次轮询方案中确认 ADC_NbrOfChannel1、扫描模式关闭。每次采样前确认 ADC_RegularChannelConfig() 选择正确通道。软件启动后等待 ADC_FLAG_EOC 再读取结果。ADC 使能后完成复位校准和启动校准。原始 ADC 值是 04095不是直接电压值。编译 0 错误只证明软件可以生成目标文件仍需逐路接入已知电压验证。多通道数据异常时检查接线、共地、参考电压和信号源输出阻抗。