STM32 RS485读取SHT20

硬件配置

采用RS3485芯片,供电电压3V3,EN引脚连接GPIOA1(可更改)

采用SHT20芯片RS485版本,V+接5V,V-接GND;

另外单片机再接一路串口给电脑用来显示。

引脚设置

PA1设置为GPIO_OUTPUT,默认拉低

USART1使能,配置默认;

USART2使能,波特率改为9600并开启NVIC中断;

协议知识

RS485是一种硬件电气标准,它定义了设备之间如何进行物理连接和信号传输。你可以把它想象成一条专为工业环境设计的高速公路。

一条RS485总线可以连接多个设备(理论上最多32个标准负载,使用中继器可扩展至更多),形成总线型网络,大大简化了布线。

在大多数应用中,RS485采用半双工模式,即数据在同一时间只能单向传输,要么发,要么收,这简化了总线结构并避免了冲突。

Modbus是一种通信协议,它定义了设备之间交换数据的格式和规则。如果说RS485是路,Modbus就是路上车辆必须遵守的交通规则,确保所有设备都能"说同一种语言"。

通信流程:

  • 主芯片想要读取1号从站(如温度传感器)的数据。
  • 主站按照Modbus协议的规则,打包一个请求报文,其中包含从站地址(1)、功能码(如"读寄存器")等信息。
  • 这个报文通过RS485接口转换成电信号,在总线上广播出去。
  • 总线上所有设备都能收到信号,但只有地址为1的从站会识别并处理这个请求。
  • 1号从站将温度值打包成Modbus响应报文,通过RS485接口发回给主站。

本次所用到的是标准Modbus RTU协议

代码编写

逻辑比较简单,发送指令,收到指令开启中断并将结果拷贝通过另一路串口发送到电脑

cpp 复制代码
#ifndef __SHT20_H
#define __SHT20_H

#include "main.h"
#include <string.h>
#include "usart.h"
//------------------------数据变量定义------------------------------------
extern uint8_t uart2_rx_buf[];
extern uint8_t uart1_tx_buf[];
//------------------------外部接口函数------------------------------------
void UART2_To_UART1_Forward(void);
void RS485_Send(uint8_t *data, uint16_t len);
void Test_Sht20(void);
//------------------------硬件接口配置------------------------------------
#define RS485_EN_GPIO_Port  GPIOA
#define RS485_EN_Pin        GPIO_PIN_1
#define RS485_RX_MODE()     HAL_GPIO_WritePin(RS485_EN_GPIO_Port, RS485_EN_Pin, GPIO_PIN_RESET)   // 低电平=接收
#define RS485_TX_MODE()     HAL_GPIO_WritePin(RS485_EN_GPIO_Port, RS485_EN_Pin, GPIO_PIN_SET)     // 高电平=发送
//-----------------------------------------------------------------------
#endif
cpp 复制代码
#include "sht20.h"

//------------------------数据变量定义------------------------------------
uint8_t uart2_rx_buf[16];
uint8_t uart1_tx_buf[16];
volatile uint16_t rx_len = 0;

const uint8_t SHT20_CMD_READ_TEMP[8] = {0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x60, 0x0A};
const uint8_t SHT20_CMD_READ_HUMI[8] = {0x01, 0x04, 0x00, 0x02, 0x00, 0x01, 0x90, 0x0A};
const uint8_t SHT20_CMD_READ_BOTH[8] = {0x01, 0x04, 0x00, 0x01, 0x00, 0x02, 0x20, 0x0B};
const uint8_t SHT20_CMD_READ_ADDR[8] = {0x01, 0x03, 0x01, 0x01, 0x00, 0x01, 0x20, 0x0B};

//-----------------------具体函数实现------------------------------------
void UART2_To_UART1_Forward(void)
{
    if (rx_len == 0) return;
    memcpy(uart1_tx_buf, uart2_rx_buf, rx_len);
    HAL_UART_Transmit(&huart1, uart1_tx_buf, rx_len, 100); 
    rx_len = 0;
}
//-----------------------------------------------------------------------
void RS485_Send(uint8_t *data, uint16_t len)
{
    RS485_TX_MODE();  //切换为发送模式
    HAL_UART_Transmit(&huart2, data, len, 100);
    while (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TC) == RESET);  
    RS485_RX_MODE();  //切回接收
}
//-----------------------------------------------------------------------
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    static uint16_t rx_index = 0;
    static uint32_t last_rx_time = 0;
    
    if (huart->Instance == USART2)
    {
        uint32_t now = HAL_GetTick();
        if (now - last_rx_time > 10 && rx_index > 0)  rx_index = 0;
        last_rx_time = now;
        if (rx_index < 16 - 1) rx_index++;		
        HAL_UART_Receive_IT(&huart2, &uart2_rx_buf[rx_index], 1);
		
        if (rx_index >= 7) {  
            rx_len = rx_index;
            rx_index = 0;
            UART2_To_UART1_Forward();  
        }
    }
}
//-----------------------------------------------------------------------
void Test_Sht20(void)
{
	HAL_UART_Receive_IT(&huart2, uart2_rx_buf, 1);
	while(1)
	{
		RS485_Send((uint8_t *)SHT20_CMD_READ_TEMP, 8);
		HAL_Delay(1000);
		RS485_Send((uint8_t *)SHT20_CMD_READ_HUMI, 8);
		HAL_Delay(1000);
		RS485_Send((uint8_t *)SHT20_CMD_READ_BOTH, 8);
		HAL_Delay(1000);	
	}
}

测试结果

以上就完成了模块的测试,后续优化可参考

①目前是根据字节数判断截止,但是返回字节数量并不固定,可以用时间戳来实现

②后续不可能都在节点1上,可以考虑自动CRC生成,但器件少的情况更建议手动配置数组

相关推荐
2401_827501289 小时前
51单片机(二):GPIO、中断、定时器与PWM
单片机·嵌入式硬件·51单片机
尼喃11 小时前
HDMI/DP高速差分接口ESD保护:0.3pF超低电容PWESD-5VSDF方案详解
嵌入式硬件
ACP广源盛1392462567311 小时前
GSV6155@ACP# 搭配 AI 服务器、AI PC 完整适配方案
大数据·服务器·人工智能·分布式·单片机·嵌入式硬件
Saniffer_SH12 小时前
NAND技术(二):从 Channel、Die/LUN、P/E Cycle 到 LDPC,一次讲透 NAND 里那些最容易误解的概念
人工智能·驱动开发·嵌入式硬件·测试工具·fpga开发·计算机外设·压力测试
辰哥单片机设计14 小时前
STM32音乐播放器
stm32·单片机·嵌入式硬件
周洲083014 小时前
STM32 串口指令控制系统|上位机下发命令控制 LED、继电器,通用指令解析框架
stm32·嵌入式硬件·mongodb
集芯微电科技有限公司14 小时前
PC3100H 专为TFT-LCD面板偏置电源设计双输出100m电流
人工智能·单片机·嵌入式硬件·神经网络·生成对抗网络
广州灵眸科技有限公司15 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) 系统操作-线进程操作
数据库·单片机·嵌入式硬件·算法·php
集芯微电科技有限公司16 小时前
各种大小尺寸TFT-LCD面板供电偏压电源方案IC
人工智能·单片机·嵌入式硬件·神经网络·生成对抗网络
FREEDOM_X16 小时前
嵌入式——定时器工作原理
linux·c语言·单片机·嵌入式硬件·ubuntu