ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

STM32F103农业传感节点:SHT31+GY30多传感器协同采集实战

STM32F103农业传感节点:SHT31+GY30多传感器协同采集实战 简介本资源是一套基于STM32F103C8T6开发的智能大棚温湿度传感系统完整课程设计源码面向计算机、自动化、人工智能等专业的在校学生及初学者解决农业物联网场景下环境参数采集与无线传输的核心实践问题适用于课程设计、毕业设计或项目原型开发。压缩包共179个文件含26个C源文件如stm32f1xx_hal_i2c.c、stm32f1xx_hal_uart.c等驱动实现、49个头文件h、27个编译中间文件o/d及Makefile、.ioc工程配置等关键构建文件总大小6.35MB结构规范便于理解HAL库移植与模块化开发逻辑。已有3416人学习下载项目经实机验证运行稳定答辩平均分94.5分。读者可直接部署SHT31温湿度与GY30光照传感器I2C协议通过HC-05蓝牙模块实现串口无线上传并复用LCD1602本地显示驱动代码配套完整引脚分配与模式说明为后续扩展CO₂、土壤湿度等功能提供清晰接口与架构基础。1. 这不是玩具级Demo一个跑在STM32F103C8T6上的真实农业传感节点能直接进田间部署你手头那块不到20元的STM32F103C8T6最小系统板真能扛起智能大棚的实时监测任务很多人以为课程设计只是“点亮LED串口打印”但这份源码证明它已具备工业级传感节点的核心能力——SHT31温湿度GY30光照双传感器I2C协同采集、LCD1602本地显示、HC-05蓝牙透传、全HAL库驱动、低功耗周期唤醒逻辑且所有模块在答辩现场持续运行超48小时无丢帧。它不依赖上位机轮询主控自主完成采样→校验→格式化→发送闭环不靠仿真器硬调引脚分配严格对应CH340下载电路与实际PCB布局更关键的是它把HAL库的TIM定时器中断、I2C非阻塞传输、UART DMA收发这些易出错环节全部封装成可复用函数。适合自动化/物联网方向学生做毕设原型也适合农技站工程师快速验证传感器组网方案——你拿到的不是教学示例而是一个经过94.5分答辩验证的、可裁剪可扩展的嵌入式传感基线。2. HAL库驱动下的多传感器协同采集为什么选SHT31GY30而非DHT22BH17502.1 传感器选型背后的工程权衡精度、协议与供电稳定性课程设计中放弃常见的DHT22单总线、±2℃温漂和BH1750I2C但仅支持单一分辨率转而采用SHT31±0.2℃/±2%RH与GY30即BH1750升级版支持0.11–100klux宽量程根本原因在于农业场景对数据可信度的刚性要求。SHT31的I2C地址固定为0x44避免了DHT22单总线时序抖动导致的读取失败GY30在周期转换模式下可设置100ms/200ms/400ms采样间隔恰好匹配大棚环境变化速率温度每分钟波动通常0.1℃。更重要的是二者均支持CRC校验——SHT31的16位CRC由硬件生成GY30需软件校验这直接规避了农田电磁干扰引发的数据错包。源码中Drivers/Peripheral/sht31.c第87行明确调用HAL_I2C_Master_Transmit()后立即执行SHT31_CheckCRC()而gy30.c第124行则通过GY30_ReadData()返回值判断CRC有效性未通过则触发重试机制最多3次这是DHT22类传感器无法实现的可靠性保障。2.2 I2C总线冲突规避PB10/PB11引脚复用与时钟配置实操STM32F103C8T6的I2C1外设默认映射到PB6/PB7但本项目强制使用PB10SCL/PB11SDA原因在于PB6/PB7已被LCD1602数据线占用见引脚分配表而PB10/PB11属于I2C1的重映射通道。这要求在Core/Src/stm32f1xx_hal_msp.c中必须启用重映射功能void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) { GPIO_InitTypeDef GPIO_InitStruct {0}; if(hi2c-InstanceI2C1) { __HAL_RCC_I2C1_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); // 关键启用I2C1重映射PB10/PB11 __HAL_AFIO_REMAP_I2C1_ENABLE(); GPIO_InitStruct.Pin GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode GPIO_MODE_AF_OD; // 开漏输出 GPIO_InitStruct.Speed GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, GPIO_InitStruct); } }提示若跳过__HAL_AFIO_REMAP_I2C1_ENABLE()I2C通信将始终失败示波器抓取PB10/PB11无任何波形。此配置在STM32CubeIDE中需手动勾选AFIO Remap选项GUI自动生成代码常遗漏该宏。2.3 单次转换与周期转换的混合调度TIM3中断驱动的采集节拍器SHT31采用单次转换模式避免连续采样导致的自热误差GY30则启用周期转换自动每200ms更新寄存器。源码通过TIM3定时器100ms中断统一调度每次中断检查GY30数据就绪标志同时启动SHT31新一次采样。核心逻辑在Core/Src/main.c的HAL_TIM_PeriodElapsedCallback()中void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim-Instance TIM3) { // 每100ms触发先读GY30周期模式数据已就绪 if(GY30_IsDataReady()) { gy30_lux GY30_ReadLux(); lcd_update_light(gy30_lux); // 刷新LCD光照值 } // 每500ms执行一次SHT31采样5次中断触发1次 sht31_counter; if(sht31_counter 5) { sht31_counter 0; SHT31_Measure(); // 发送测量命令 // 启动15ms延时等待转换完成SHT31单次转换最大耗时15ms HAL_Delay(15); SHT31_ReadData(temp, humi); // 读取结果并校验CRC lcd_update_temp_humi(temp, humi); } } }注意HAL_Delay(15)在此处不可替换为HAL_TIM_Base_Start_IT()延时因SHT31转换时间存在器件离散性硬延时比中断等待更可靠。实测中若改用中断等待部分批次SHT31会出现1~2ms延迟偏差导致读取失败。3. HC-05蓝牙透传与LCD1602本地显示的双路数据出口设计3.1 UART2 DMA收发架构解决HC-05 AT指令响应粘包问题HC-05默认波特率9600但课程设计将其配置为115200Core/Src/stm32f1xx_hal_conf.h中#define USART2_BAUDRATE 115200以提升数据吞吐量。关键突破在于放弃轮询发送采用UART2DMA双缓冲机制// 初始化DMA双缓冲Core/Src/main.c uint8_t tx_buffer[64]; uint8_t rx_buffer[128]; DMA_HandleTypeDef hdma_usart2_tx; DMA_HandleTypeDef hdma_usart2_rx; HAL_UARTEx_ReceiveToIdle_DMA(huart2, rx_buffer, sizeof(rx_buffer)); __HAL_DMA_DISABLE_IT(hdma_usart2_rx, DMA_IT_HT); // 禁用半传输中断当HC-05发来AT指令响应如OK\r\n时DMA在检测到空闲线状态后自动触发HAL_UARTEx_RxEventCallback()此时rx_buffer中已完整存储响应帧无需手动拼接。发送端则通过HAL_UART_Transmit_DMA()将结构化JSON数据如{T:25.3,H:62.1,L:12500}一次性推入TX FIFO避免传统HAL_UART_Transmit()在高频率调用时因中断嵌套导致的丢字节。3.2 LCD1602四线制驱动优化减少GPIO占用与刷新频次控制16个引脚直连LCD1602会耗尽STM32F103C8T6的GPIO资源本项目采用四线制模式D4-D7仅占用8个IOPA5-PA7 PB3-PB9。核心优化在于Drivers/Peripheral/lcd1602.c中的写操作void LCD_Write4Bits(uint8_t data) { HAL_GPIO_WritePin(LCD_D4_GPIO_Port, LCD_D4_Pin, (data 0x01) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(LCD_D5_GPIO_Port, LCD_D5_Pin, (data 0x02) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(LCD_D6_GPIO_Port, LCD_D6_Pin, (data 0x04) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(LCD_D7_GPIO_Port, LCD_D7_Pin, (data 0x08) ? GPIO_PIN_SET : GPIO_PIN_RESET); // 关键E引脚脉冲宽度精确控制为1μs非标准500ns HAL_GPIO_WritePin(LCD_E_GPIO_Port, LCD_E_Pin, GPIO_PIN_SET); __NOP(); __NOP(); __NOP(); // 插入3个空操作确保建立时间 HAL_GPIO_WritePin(LCD_E_GPIO_Port, LCD_E_Pin, GPIO_PIN_RESET); }提示标准LCD手册要求E脉冲≥450ns但实测发现STM32F103C8T6在72MHz主频下HAL_GPIO_WritePin()执行时间约120ns插入3个__NOP()后总脉宽达360ns仍低于手册下限。解决方案是改用__DSB()内存屏障指令替代__NOP()确保时序稳定。3.3 双路数据同步策略避免LCD刷新与蓝牙发送竞争总线当温湿度数据更新时需同时刷新LCD和发送蓝牙帧。若直接调用lcd_update_temp_humi()与uart_send_json()可能因UART发送耗时约5ms导致LCD显示卡顿。源码采用状态机解耦typedef enum { DISPLAY_IDLE, DISPLAY_UPDATING, DISPLAY_COMPLETE } lcd_state_t; lcd_state_t lcd_status DISPLAY_IDLE; // 主循环中 if(lcd_status DISPLAY_COMPLETE bluetooth_ready) { uart_send_json(temp, humi, gy30_lux); bluetooth_ready 0; }LCD刷新在TIM3中断中置位DISPLAY_UPDATING完成后回调函数置DISPLAY_COMPLETE蓝牙发送仅在LCD空闲时触发彻底消除资源争用。实测LCD刷新帧率稳定在2Hz蓝牙数据包间隔1s互不干扰。4. STM32CubeIDE工程配置与CH340下载链路调试实战4.1 CubeIDE工程迁移关键点HAL库版本与编译器参数适配原始工程基于STM32CubeIDE 1.11.0生成若使用新版如1.15.0打开常见报错为undefined reference to HAL_TIM_Base_Start_IT。根本原因是HAL库版本升级导致函数签名变更。修复步骤删除Drivers/STM32F1xx_HAL_Driver文件夹在CubeIDE中右键工程 →STM32CubeMX→Initialize Peripherals→ 重新生成HAL库修改Core/Inc/stm32f1xx_hal_conf.h确保启用所需模块#define HAL_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED编译器参数追加-stdgnu11Project → Properties → C/C Build → Settings → Tool Settings → MCU GCC Compiler → Miscellaneous → Other flags4.2 CH340下载失败的五层排查法排查层级检查项验证命令/现象典型错误物理层CH340芯片供电是否正常万用表测VCC引脚电压USB线缆供电不足4.75V驱动层Windows设备管理器中COM端口是否存在查看“端口(COM与LPT)”CH340驱动未安装需Win10兼容版协议层STM32 BOOT0/BOOT1电平是否正确BOOT01, BOOT10进入系统存储器BOOT引脚虚焊或电容漏电固件层GreenhouseSensorSystem.bin是否为正确格式file GreenhouseSensorSystem.bin应显示ARM binary使用Keil生成的.axf未转换为bin工具层STM32CubeProgrammer连接参数波特率115200接口SWD目标电压3.3V误选JTAG接口导致识别失败提示若CubeProgrammer提示Cannot connect to target90%概率是BOOT0未拉高。用杜邦线将BOOT0接至3.3V短按复位键后再连接成功后立即断开BOOT0恢复正常运行。4.3 蓝牙AT指令预配置清单HC-05与PC端的握手协议HC-05出厂默认为从机模式需通过AT指令配置为特定角色。课程设计采用以下最小化配置使用USB-TTL模块串口助手指令参数作用响应ATNAME?—查询当前设备名NAME:HC-05ATROLE00从机1主机设为从机便于PC连接OKATPSWD1234密码4位数字设置配对密码OKATUART115200,0,1波特率,停止位,校验位匹配STM32 UART2配置OKATCMODE00指定地址1任意地址允许任意设备配对OK配置完成后Windows蓝牙设置中搜索HC-05输入密码1234即可配对。配对成功后PC端串口助手如XCOM选择对应COM口即可实时接收JSON数据流。5. 从课程设计到田间部署三个可立即落地的增强方案5.1 加入看门狗防死锁独立看门狗IWDG的低开销集成农田环境存在电源波动风险可能导致I2C总线锁死或UART发送卡住。在现有工程中加入IWDG仅需3步在main.c开头添加#include stm32f1xx_hal_iwdg.h初始化函数中插入IWDG_HandleTypeDef hiwdg; hiwdg.Instance IWDG; hiwdg.Init.Prescaler IWDG_PRESCALER_32; // 32kHz LSI/321kHz hiwdg.Init.Reload 4000; // 4秒超时1kHz/40004s HAL_IWDG_Init(hiwdg);在主循环末尾喂狗while (1) { // ...原有逻辑 HAL_IWDG_Refresh(hiwdg); // 必须在4秒内执行 }注意IWDG一旦使能无法关闭reload值需根据最慢任务周期设定。实测中将Reload40004s可覆盖SHT31采样LCD刷新蓝牙发送全链路耗时实测峰值3.2s。5.2 温湿度数据本地存储利用STM32内部Flash模拟EEPROM为应对蓝牙断连场景可将最近100组数据存入Flash。利用stm32f1xx_hal_flash_ex.c提供的扇区擦除功能#define DATA_SECTOR FLASH_SECTOR_3 // 1KB扇区 uint32_t data_buffer[100][3]; // [温度][湿度][光照] void SaveToFlash(void) { HAL_FLASH_Unlock(); HAL_FLASHEx_Erase(erase_struct, SECTOR_ERROR); // 先擦除 for(int i0; i100; i) { HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_BASE_ADDR i*12, data_buffer[i][0]); // 温度 HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_BASE_ADDR i*12 4, data_buffer[i][1]); // 湿度 } HAL_FLASH_Lock(); }提示Flash写入寿命约10k次建议每100次采集才写入1次避免频繁擦写。实际部署时可将SaveToFlash()挂载到RTC闹钟中断每天凌晨2点批量保存。5.3 低成本LoRa远距离升级SX1278模块接入指南若大棚面积超500米蓝牙传输失效可替换HC-05为SX1278SPI接口。硬件只需增加3根线NSS/CLK/MISO/MOSI和1个天线接口。软件层面修改Core/Src/main.c移除huart2初始化新增hspi1配置将uart_send_json()替换为LoRa_SendPacket()使用Semtech官方LoRaMac协议栈关键参数扩频因子SF7兼顾速率与距离带宽125kHz编码率4/5实测数据显示SX1278在开阔地传输距离达3.2km功耗仅12.5mA发送态完全满足农业物联网长距离、低功耗需求。此方案成本增加不足15元却将系统适用范围从温室扩展至整个农场。本文还有配套的精品资源点击获取
返回列表