STM32F103C8T6 + YL-69传感器:从ADC采集到串口打印的完整保姆级教程

张开发
2026/4/17 4:25:33 15 分钟阅读

分享文章

STM32F103C8T6 + YL-69传感器:从ADC采集到串口打印的完整保姆级教程
STM32F103C8T6与YL-69土壤湿度传感器实战指南从硬件搭建到数据可视化的全流程解析在物联网和智能农业快速发展的今天土壤湿度监测已成为许多项目的核心需求。对于嵌入式开发者而言如何快速搭建一个可靠的土壤湿度监测系统是必备技能。本文将带你从零开始使用STM32F103C8T6最小系统板和YL-69传感器构建一个完整的土壤湿度监测解决方案。1. 硬件准备与连接原理1.1 硬件选型与采购建议对于初学者而言选择合适的硬件是项目成功的第一步。以下是经过验证的硬件组合主控芯片STM32F103C8T6最小系统板蓝色板价格约15-25元具备丰富的外设接口社区资源丰富适合学习传感器YL-69土壤湿度传感器四线制设计VCC、GND、AO、DO工作电压3.3V-5V价格约5-10元提示购买时建议选择带有防锈处理探针的版本可延长户外使用时间。1.2 硬件连接详解YL-69传感器与STM32的连接看似简单但每个引脚都有其特定作用传感器引脚STM32连接点作用说明VCC3.3V电源输入GNDGND接地AOPA1模拟信号输出DO不连接数字信号输出阈值报警为什么选择PA1引脚PA1是STM32F103C8T6的ADC1通道1该芯片共有10个ADC通道PA0-PA7, PB0-PB1PA1位置便于布线不易与其他外设冲突// 在代码中对应的ADC通道定义 #define ADC_CHANNEL ADC_Channel_1 // PA1对应ADC1通道12. 软件开发环境搭建2.1 Keil MDK工程配置创建一个规范的工程结构是项目成功的关键。建议采用以下文件结构Project/ ├── USER/ │ ├── main.c │ ├── adc.c │ ├── adc.h │ ├── usart.c │ ├── usart.h ├── CORE/ ├── FWLIB/ ├── SYSTEM/关键配置步骤新建Keil工程选择STM32F103C8器件添加标准外设库STM32F10x_StdPeriph_Lib配置Target选项勾选Use MicroLIB简化printf重定向设置ROM和RAM地址范围优化等级建议选择-O12.2 ADC模块初始化详解ADC初始化是项目的核心部分需要理解每个参数的意义void ADC1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; // 1. 时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); // 2. GPIO配置 GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AIN; // 模拟输入模式 GPIO_Init(GPIOA, GPIO_InitStructure); // 3. ADC分频配置 RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 72MHz/612MHz // 4. ADC参数配置 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; // 1个转换通道 ADC_Init(ADC1, ADC_InitStructure); // 5. 使能ADC并校准 ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); }3. 数据采集与处理3.1 ADC数据采集实现获取ADC原始值的函数实现uint16_t Get_ADC_Value(uint8_t ch) { // 设置规则组通道采样时间为239.5周期 ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5); // 启动软件转换 ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 等待转换完成 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // 返回转换结果 return ADC_GetConversionValue(ADC1); }3.2 数据滤波与湿度计算土壤湿度值通常需要经过滤波处理以提高稳定性#define SAMPLE_TIMES 10 // 采样次数 uint16_t Get_Soil_Humidity(uint8_t ch) { uint32_t adc_sum 0; uint16_t humidity 0; // 多次采样取平均 for(uint8_t i0; iSAMPLE_TIMES; i) { adc_sum Get_ADC_Value(ch); Delay_ms(5); } uint16_t adc_avg adc_sum / SAMPLE_TIMES; // 转换为百分比湿度 (YL-69特性) // 干燥时ADC值接近0湿润时接近409512位ADC humidity (4095 - adc_avg) * 100 / 4095; return humidity; }注意不同批次的YL-69传感器可能有不同的特性曲线建议在实际使用前进行校准。4. 数据输出与可视化4.1 串口通信配置实现printf重定向方便数据输出#include stdio.h // 重定向printf到串口1 int fputc(int ch, FILE *f) { USART_SendData(USART1, (uint8_t)ch); while(USART_GetFlagStatus(USART1, USART_FLAG_TC) RESET); return ch; } void USART1_Init(uint32_t baudrate) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; // 1. 时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); // 2. GPIO配置 // PA9-USART1_TX, PA10-USART1_RX GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(GPIOA, GPIO_InitStructure); // 3. USART参数配置 USART_InitStructure.USART_BaudRate baudrate; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, USART_InitStructure); // 4. 使能USART USART_Cmd(USART1, ENABLE); }4.2 数据格式设计与输出设计合理的数据输出格式有助于后续处理void Print_Sensor_Data(uint16_t humidity) { // 获取系统时间需实现Get_Tick()函数 uint32_t tick Get_Tick(); // 格式化输出 printf([%lu ms] Soil Humidity: %d%%\r\n, tick, humidity); // 或者JSON格式输出 // printf({\sensor\:\YL-69\,\humidity\:%d,\unit\:\%%\}\r\n, humidity); }4.3 使用串口助手可视化数据推荐几款常用的串口调试工具ATK XCOM正点原子出品支持多种数据格式显示自带数据保存功能SSCOM野火推荐支持波形显示多串口同时监控CoolTermMac平台简洁易用支持多种编码格式典型输出示例[1250 ms] Soil Humidity: 45% [2250 ms] Soil Humidity: 47% [3250 ms] Soil Humidity: 46%5. 项目优化与扩展5.1 硬件优化建议电源稳定性添加0.1μF去耦电容靠近传感器VCC引脚在长距离传输时考虑使用屏蔽线传感器保护探针可涂覆防锈漆避免长时间通电导致电解腐蚀接口设计增加XH2.54插座方便插拔考虑添加LED状态指示5.2 软件优化技巧低功耗设计// 间歇采样模式 void Enter_LowPower_Mode(void) { // 关闭ADC时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE); // 进入停止模式 PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); // 唤醒后重新初始化ADC ADC1_Init(); }自适应采样率// 根据湿度变化率调整采样间隔 uint32_t Get_Sample_Interval(uint16_t prev_humidity, uint16_t curr_humidity) { uint8_t delta abs(curr_humidity - prev_humidity); if(delta 20) return 500; // 快速变化500ms采样一次 else if(delta 5) return 1000; // 中等变化1s采样一次 else return 5000; // 缓慢变化5s采样一次 }5.3 项目扩展方向多传感器融合结合DHT11温湿度传感器添加光照强度传感器无线传输通过ESP8266实现WiFi上传使用HC-05模块实现蓝牙传输本地显示添加OLED显示屏使用TFT LCD实现图形界面云端对接通过MQTT协议上传到阿里云IoT对接Home Assistant智能家居系统6. 常见问题排查指南在实际项目中可能会遇到以下典型问题问题1ADC读数不稳定检查电源是否稳定示波器观察3.3V纹波尝试增加软件滤波次数检查传感器与土壤接触是否良好问题2串口无输出检查TX/RX线序是否正确确认波特率设置一致验证printf重定向是否成功问题3湿度值始终为0或100%检查AO引脚连接是否正常测量传感器AO引脚输出电压范围确认ADC配置是否正确特别是对齐方式问题4程序下载失败检查BOOT0/BOOT1引脚状态确认下载器驱动安装正确尝试降低下载速度以下是一个简单的排查流程图电源正常是 → 2否 → 检查电源电路串口通信正常是 → 3否 → 检查串口配置ADC能读取到变化的值是 → 4否 → 检查传感器和ADC配置计算后的湿度值合理是 → 系统正常否 → 检查计算公式和传感器特性在实际项目中我遇到过最棘手的问题是传感器在潮湿环境下读数漂移后来发现是电源纹波过大导致的。添加了一个47μF的钽电容后问题得到解决。另一个常见问题是新手容易混淆AO和DO引脚的功能记住AO是模拟输出需要连接ADC引脚DO是数字输出可以连接普通GPIO但不适用于精确测量。

更多文章