STM32F103C8T6 + RS485转TTL模块:手把手教你读取土壤传感器数据(附完整代码)

张开发
2026/5/24 12:27:57 15 分钟阅读
STM32F103C8T6 + RS485转TTL模块:手把手教你读取土壤传感器数据(附完整代码)
STM32F103C8T6 RS485转TTL模块手把手教你读取土壤传感器数据附完整代码在智慧农业和环境监测领域土壤参数的精准采集是系统决策的基础。STM32F103C8T6作为性价比极高的ARM Cortex-M3内核微控制器配合RS485工业总线能够稳定获取各类土壤传感器的数据。本文将完整呈现从硬件搭建到代码实现的全部细节特别针对Modbus-RTU协议的数据解析和常见故障给出实战解决方案。1. 硬件系统搭建1.1 核心器件选型指南主控芯片STM32F103C8T6Blue Pill开发板72MHz主频64KB Flash20KB RAM内置3个USART接口RS485转换模块MAX485芯片方案工作电压3.3V-5V兼容传输速率最高2.5Mbps土壤传感器典型Modbus-RTU设备测量参数湿度、温度、EC值、PH值供电范围5-30V DC通信协议Modbus-RTU 9600bps注意选购RS485模块时需确认是否自带自动流向控制功能传统模块需要手动控制DE/RE引脚1.2 硬件连接详解完整接线方案如下表所示设备引脚STM32连接点说明RS485模块A线传感器A线差分信号正极RS485模块B线传感器B线差分信号负极RS485模块RXDPA3(USART2_RX)数据接收RS485模块TXDPA2(USART2_TX)数据发送RS485模块DE/REPA7发送使能(高电平有效)传感器VCC12V电源独立供电传感器GND共地确保参考电平一致关键细节必须建立共地连接否则可能导致通信异常总线末端建议接入120Ω终端电阻长距离传输时使用双绞线电缆2. 软件环境配置2.1 开发工具链搭建推荐使用以下工具组合# STM32CubeMX配置生成 stm32cubecli --config deviceSTM32F103C8 --periphUSART2:9600-8-N-1 # 编译工具链 arm-none-eabi-gcc -mcpucortex-m3 -T stm32f103c8t6.ld2.2 USART2初始化代码在CubeMX中配置USART2参数波特率9600数据位8停止位1无校验硬件流控制None关键初始化代码片段void MX_USART2_UART_Init(void) { huart2.Instance USART2; huart2.Init.BaudRate 9600; huart2.Init.WordLength UART_WORDLENGTH_8B; huart2.Init.StopBits UART_STOPBITS_1; huart2.Init.Parity UART_PARITY_NONE; huart2.Init.Mode UART_MODE_TX_RX; huart2.Init.HwFlowCtl UART_HWCONTROL_NONE; HAL_UART_Init(huart2); }3. Modbus-RTU协议实现3.1 典型查询帧构造土壤传感器常用功能码03H读取保持寄存器示例查询帧字节位置值说明00x01设备地址10x03功能码2-30x0000起始寄存器地址4-50x0004寄存器数量6-7CRC16校验码(低字节在前)CRC16计算函数实现uint16_t Modbus_CRC16(uint8_t *buf, int len) { uint16_t crc 0xFFFF; for (int pos 0; pos len; pos) { crc ^ (uint16_t)buf[pos]; for (int i 8; i ! 0; i--) { if ((crc 0x0001) ! 0) { crc 1; crc ^ 0xA001; } else { crc 1; } } } return crc; }3.2 数据接收与解析响应帧典型结构以成功响应为例字节内容示例值说明0设备地址0x01应与查询帧一致1功能码0x03成功响应与查询相同2字节计数0x08后续数据字节数3-10数据域4个寄存器每个寄存器2字节11-12CRC16-校验码数据解析示例void Parse_SoilData(uint8_t *data) { float humidity (float)((data[3]8)|data[4])/10.0f; float temperature (float)((data[5]8)|data[6])/10.0f; uint16_t ec_value (data[7]8)|data[8]; float ph_value (float)((data[9]8)|data[10])/10.0f; printf(Humidity: %.1f%%\n, humidity); printf(Temperature: %.1fC\n, temperature); printf(EC: %d us/cm\n, ec_value); printf(PH: %.1f\n, ph_value); }4. 系统优化与故障排查4.1 时序控制要点发送模式切换后至少延迟1ms再发送数据发送完成后延迟1ms再切换回接收模式两次查询间隔建议≥200ms// 典型操作时序 GPIO_SetBits(GPIOA, GPIO_Pin_7); // 使能发送 delay_ms(1); HAL_UART_Transmit(huart2, query, 8, 100); delay_ms(1); GPIO_ResetBits(GPIOA, GPIO_Pin_7); // 切换接收4.2 常见问题解决方案问题1接收数据不全检查接线确认A/B线未接反验证终端电阻长距离时需120Ω电阻调整延时增加发送前后的切换延时问题2CRC校验失败确认设备地址匹配检查波特率设置示波器测量实际速率验证供电稳定性纹波过大影响通信问题3数据值异常检查寄存器映射表确认字节序大端/小端验证数据计算公式5. 完整工程代码实现核心代码结构├── Core/ │ ├── Src/ │ │ ├── main.c │ │ ├── stm32f1xx_it.c │ │ └── usart.c │ └── Inc/ │ ├── modbus.h │ └── rs485.h ├── Drivers/ └── STM32F103C8T6_FLASH.ld关键代码片段主循环逻辑uint8_t query[8] {0x01, 0x03, 0x00, 0x00, 0x00, 0x04, 0x44, 0x09}; while (1) { // 发送查询命令 RS485_SendMode_Enable(); HAL_UART_Transmit(huart2, query, 8, 100); RS485_ReceiveMode_Enable(); // 接收响应数据 if(HAL_UART_Receive(huart2, rx_buf, 12, 200) HAL_OK) { if(Verify_CRC16(rx_buf, 12)) { Process_SoilData(rx_buf); } } HAL_Delay(5000); // 5秒采集周期 }实际部署中发现当传感器供电电压低于10V时通信稳定性会显著下降。建议为传感器单独配置12V/1A以上的稳压电源并与控制器共地处理。对于多节点组网每个传感器应设置唯一地址总线拓扑采用菊花链连接方式。

更多文章