Files
STM32F4-Base/Drivers/BSP/RS485/rs485.h
T
wandering1 bb76cfd779 修复规范矛盾并定案5项规则,保护宏统一XXX_H
规则定案:常量在右(a>5)、保护宏XXX_H(禁双下划线)、
头文件常量用#define、存储类前缀(g_/s_)优先、允许void返回值
全库32个.h头文件保护宏 __XXX_H → XXX_H 改名(字节级替换)
S1检查规则同步更新(拒绝双下划线),Inc/gpio.h 反向验证被正确拦截
规范示例矛盾修复:K&R括号、标准类型、变量初始化、命名常量、注释字段补全
2026-09-01 16:07:00 +08:00

127 lines
4.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称:RS-485 半双工通信驱动
* 模块功能:RS-485 半双工通信驱动,封装任意 UART 外设实现 485 方向控制,
* 提供阻塞发送、中断接收(IDLE 空闲帧检测)、DMA 发送等功能。
* 参考 ST AN3070 应用笔记《IO-Link master: USART communication》
* 及 controllerstech.com RS485 教程
* 适用平台:STM32F4 系列
* 作者:王建锋
* 创建日期:2026-07-18
* 修改记录:
* 2026-07-18 王建锋 创建初始版本
*/
#ifndef RS485_H
#define RS485_H
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
/*
* 常量定义
*/
#define RS485_TIMEOUT_DEFAULT 1000U /* 默认发送超时(ms) */
#define RS485_RX_BUF_SIZE 256U /* 接收缓冲区大小 */
/*
* RS-485 句柄结构体
* 将任意 UART + 任意 GPIO 组合绑定为一个 RS-485 半双工通信实例
*/
typedef struct {
UART_HandleTypeDef *huart; /* UART 外设句柄 */
GPIO_TypeDef *dir_port; /* 方向控制 GPIO 端口 */
uint16_t dir_pin; /* 方向控制 GPIO 引脚号 */
volatile uint16_t rx_size; /* 最近一次接收的字节数 */
uint8_t rx_buf[RS485_RX_BUF_SIZE]; /* 接收缓冲区 */
} rs485_handle_t;
/*
* 公共函数声明
*/
/*
* 函数功能:初始化 RS-485 句柄,绑定 UART 和方向控制引脚
* 入口参数:handle - RS-485 句柄指针
* huart - UART 外设句柄指针(已由 CubeMX 初始化)
* dir_port - 方向控制 GPIO 端口(如 GPIOD)
* dir_pin - 方向控制 GPIO 引脚号(如 GPIO_PIN_0)
* 返回值:无
* 限定条件:UART 和 GPIO 须先由 CubeMX 完成初始化
* 函数说明:初始化后默认处于接收状态(DE 引脚拉低),并自动启动 IDLE
* 中断接收,无需再手动调用 rs485_receive_start。
*/
void rs485_init(rs485_handle_t *p_handle,
UART_HandleTypeDef *p_huart,
GPIO_TypeDef *p_dir_port,
uint16_t dir_pin);
/*
* 函数功能:阻塞方式发送数据
* 入口参数:handle - RS-485 句柄指针
* data - 待发送数据缓冲区
* len - 待发送字节数
* timeout - 发送超时(ms),传 0 使用 RS485_TIMEOUT_DEFAULT
* 返回值:HAL_OK / HAL_TIMEOUT / HAL_ERROR
* 限定条件:在主循环或任务中调用,不可在 UART 中断中调用
* 函数说明:发送前自动拉高 DE,发送完成后等待 TC 标志再拉低 DE,
* 确保最后一字节完全移出后再切换到接收状态
*/
HAL_StatusTypeDef rs485_transmit(rs485_handle_t *p_handle,
const uint8_t *p_data,
uint16_t len,
uint32_t timeout);
/*
* 函数功能:启动中断方式接收(IDLE 空闲帧检测)
* 入口参数:handle - RS-485 句柄指针
* 返回值:HAL_OK / HAL_ERROR
* 限定条件:UART 须已开启全局中断,NVIC 中须使能对应 UART 中断
* 函数说明:使用 HAL_UARTEx_ReceiveToIdle_IT 实现变长帧接收,
* 接收缓冲固定使用句柄内部的 rx_buf(RS485_RX_BUF_SIZE)。
* 当 UART 总线空闲超过 1 个字符时间后硬件触发 IDLE 中断,
* HAL 自动调用 HAL_UARTEx_RxEventCallback 并返回已接收字节数。
* 用户须在回调中重新调用本函数重新开启接收。
*/
HAL_StatusTypeDef rs485_receive_start(rs485_handle_t *p_handle);
/*
* 函数功能:将 RS-485 句柄与 HAL 回调关联
* 入口参数:handle - RS-485 句柄指针
* 返回值:无
* 限定条件:须在 HAL_UART_RxCpltCallback / HAL_UARTEx_RxEventCallback 中调用
* 函数说明:将 HAL 回调中接收到的数据大小回写到句柄的 rx_size 字段
*/
void rs485_rx_set_size(rs485_handle_t *p_handle, uint16_t size);
/*
* 函数功能:获取最近一次接收的字节数
* 入口参数:handle - RS-485 句柄指针
* 返回值:最近一次接收的字节数
* 限定条件:须在 HAL_UARTEx_RxEventCallback 触发后调用
*/
uint16_t rs485_rx_get_size(const rs485_handle_t *p_handle);
/*
* 全局 RS-485 实例(由 rs485.c 定义,应用层通过 extern 引用)。
* 接收缓冲已内聚到 rs485_handle_t 的 rx_buf 字段,随实例统一管理。
*/
extern rs485_handle_t g_rs485;
/*
* 应用层接收钩子:RS-485 收到完整帧(IDLE 空闲帧)后由驱动回调调用,
* 传入本次接收缓冲区与有效字节数。默认弱实现为空,应用可重定义此函数
* 处理业务数据。
* 注意:此函数在 UART 中断上下文执行,应尽快拷贝数据后返回,不要在内部
* 调用阻塞式 API(如 rs485_transmit 会切换 DE 并等待 TC)。
*/
void rs485_on_rx(uint8_t *buf, uint16_t size);
#ifdef __cplusplus
}
#endif
#endif /* RS485_H */