STM32F103ZET6 ADC实战:从零搭建电压监测系统(附完整代码)

张开发
2026/4/17 2:28:13 15 分钟阅读

分享文章

STM32F103ZET6 ADC实战:从零搭建电压监测系统(附完整代码)
STM32F103ZET6 ADC实战从零搭建电压监测系统附完整代码在嵌入式开发领域精确的电压监测是许多项目的基础需求。无论是电池管理系统、环境传感器网络还是工业控制设备实时获取电压数据都至关重要。STM32F103ZET6作为一款广泛应用的ARM Cortex-M3内核微控制器其内置的12位ADC模块为开发者提供了高性价比的模拟信号采集方案。本文将带你从零开始基于STM32CubeMX和HAL库构建一个完整的电压监测系统。不同于简单的功能演示我们会深入探讨ADC配置的底层逻辑、数据处理的最佳实践以及实际工程中可能遇到的坑点。无论你是刚接触STM32的新手还是需要快速实现原型的有经验开发者这套方案都能为你节省大量摸索时间。1. 硬件设计与环境搭建1.1 核心硬件选型电压监测系统的核心是STM32F103ZET6芯片这款芯片的ADC模块具有以下关键特性12位分辨率可识别的最小电压变化约0.8mV3.3V参考电压时多通道支持16个外部通道2个内部通道灵活的工作模式单次/连续转换、扫描模式、间断模式等内置电压参考无需外部分压电路即可测量芯片供电电压硬件连接上我们需要将待测电压接入PA0~PA7或PB0~PB1等ADC引脚确保参考电压稳定通常使用芯片的3.3V供电为模拟信号添加适当的滤波电路RC低通滤波典型值1kΩ100nF1.2 开发环境配置推荐使用以下工具链组合工具类型推荐选择备注IDEKeil MDK或STM32CubeIDE官方支持完善配置工具STM32CubeMX 6.x图形化配置外设调试器ST-Link V2性价比高支持SWD接口串口工具Tera Term或Putty查看ADC输出结果安装STM32CubeMX时务必同步下载STM32F1系列的HAL库支持包。新建工程时选择正确的芯片型号STM32F103ZE并配置好系统时钟通常设置为72MHz主频。2. CubeMX的ADC配置详解2.1 时钟树配置ADC性能与时钟配置密切相关。在CubeMX的Clock Configuration标签页中确保系统时钟SYSCLK设置为72MHz配置APB2分频器为不分频72MHz设置ADC预分频为6得到12MHz的ADC时钟不超过14MHz限制// 生成的时钟配置代码片段 RCC_PeriphCLKInitTypeDef PeriphClkInit {0}; PeriphClkInit.PeriphClockSelection RCC_PERIPHCLK_ADC; PeriphClkInit.AdcClockSelection RCC_ADCPCLK2_DIV6; HAL_RCCEx_PeriphCLKConfig(PeriphClkInit);2.2 ADC参数设置在Analog→ADC1配置界面中关键参数如下ModeIndependent mode独立模式Data AlignmentRight alignment右对齐Scan Conversion ModeDisabled除非使用多通道Continuous Conversion ModeEnabled连续转换DMA Continuous RequestsDisabled除非需要高速采样End Of Conversion SelectionEOC flag at the end of single conversion通道配置示例以通道0为例选择IN0对应引脚PA0设置Sampling Time为55.5 cycles平衡速度和精度启用Regular Conversions提示采样时间计算公式为Tconv (采样周期12.5)/ADCCLK。对于12MHz时钟和55.5周期转换时间约5.7μs。3. HAL库的ADC编程实践3.1 基本采集流程完整的ADC操作包含以下步骤初始化ADC外设CubeMX已生成启动ADC校准开始转换等待转换完成读取结果转换为实际电压值// ADC初始化示例 ADC_HandleTypeDef hadc1; void ADC_Init(void) { hadc1.Instance ADC1; hadc1.Init.ScanConvMode DISABLE; hadc1.Init.ContinuousConvMode ENABLE; hadc1.Init.DataAlign ADC_DATAALIGN_RIGHT; // ...其他参数初始化 HAL_ADC_Init(hadc1); // 执行校准 HAL_ADCEx_Calibration_Start(hadc1); }3.2 三种数据获取方式对比根据应用场景不同HAL库提供了多种数据获取方式方式适用场景优点缺点轮询模式简单应用低采样率实现简单占用CPU资源中断模式中等采样率需要及时响应实时性较好中断频繁可能影响系统DMA模式高速采样大数据量不占用CPU效率最高配置复杂轮询模式示例代码float Get_Voltage(void) { HAL_ADC_Start(hadc1); if(HAL_ADC_PollForConversion(hadc1, 10) HAL_OK) { uint32_t raw HAL_ADC_GetValue(hadc1); return (raw * 3.3f) / 4095.0f; } return 0.0f; }3.3 电压计算与数据处理原始ADC值到实际电压的转换需要考虑以下因素参考电压通常为VDDA3.3V分辨率12位ADC满量程值为4095输入阻抗信号源阻抗应小于10kΩ以保证采样精度电压计算公式Vactual (ADC_RAW × VREF) / 4095为提高测量稳定性建议采用以下技巧软件滤波移动平均或中值滤波#define SAMPLE_SIZE 5 float filtered_voltage(void) { static float samples[SAMPLE_SIZE]; static int index 0; samples[index] Get_Voltage(); index (index 1) % SAMPLE_SIZE; float sum 0; for(int i0; iSAMPLE_SIZE; i) { sum samples[i]; } return sum / SAMPLE_SIZE; }校准补偿在已知电压点进行校准存储偏移量无效值检测丢弃超出合理范围的数据4. 串口输出与系统集成4.1 串口配置要点在CubeMX中配置USART时注意波特率匹配常用115200启用发送功能根据需要配置DMA提高传输效率// 串口发送浮点数示例 void UART_SendFloat(UART_HandleTypeDef *huart, float value) { char buffer[10]; int len snprintf(buffer, sizeof(buffer), %.2f, value); HAL_UART_Transmit(huart, (uint8_t*)buffer, len, 100); }4.2 完整系统工作流程将各模块整合后的主循环示例int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); MX_USART1_UART_Init(); HAL_ADCEx_Calibration_Start(hadc1); while (1) { float voltage filtered_voltage(); UART_SendFloat(huart1, voltage); HAL_Delay(200); } }4.3 常见问题解决方案数据跳动大检查电源稳定性示波器观察纹波增加硬件滤波如100nF电容优化采样时间适当延长应用软件滤波算法转换值始终为0或4095确认输入电压在0~3.3V范围内检查引脚配置是否正确模拟输入模式验证参考电压连接采样速率不达标检查ADC时钟配置不超过14MHz减少采样周期数牺牲精度考虑使用DMA双缓冲模式实际项目中我在一个电池监测系统上遇到ADC读数周期性波动的问题最终发现是电源模块的开关噪声导致的。通过在ADC输入引脚添加π型滤波电路100Ω100nF100nF同时将采样时间延长到239.5个周期成功将测量波动控制在±5mV以内。

更多文章