Files
STM32F4-Base/Drivers/BSP/RS485/rs485.c
2026-07-19 15:27:49 +08:00

105 lines
4.4 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
/*
* 模å<C2A1>—å<E28094><C3A5>称:RS-485 å<>Šå<C5A0>Œå·¥é€šä¿¡é©±åЍ
* 模å<C2A1>—功能:RS-485 å<>Šå<C5A0>Œå·¥é€šä¿¡é©±åŠ¨å®žçŽ°ï¼Œæ ¸å¿ƒè¦<C3A8>ç¹ï¼š
* 1. å<>é€<C3A9>å‰<C3A5>æ‰é«˜ DE(切æ<E280A1>¢åˆ°å<C2B0>é€<C3A9>æ€<C3A6>)
* 2. HAL_UART_Transmit 内部已等ï¿?TC(å<CB86>é€<C3A9>完æˆ<C3A6>)标志
* 3. å<>é€<C3A9>完毕å<E280A2>Žæ‰ä½Ž DEï¼ˆåˆ‡åžæŽ¥æ”¶æ€<C3A6>)
* 4. 使用 HAL_UARTEx_ReceiveToIdle_IT 实现å<C2B0>˜é•¿å¸§æŽ¥ï¿? * å<>考:ST AN3070 应用笔记ã€<C3A3>controllerstech.com RS485 教程
* é€ç”¨å¹³å<C2B3>°ï¼šSTM32F4 系列
* 作者:王建� * 创建日期�026-07-18
* 修改记录ï¿? * 2026-07-18 王建ï¿? åˆå»ºåˆ<C3A5>å§ç‰ˆæœ¬
*/
#include "rs485.h"
/*
* 内部辅助ï¿?- æ¹å<C2B9>控åˆ
*/
#define RS485_DIR_TX(h) HAL_GPIO_WritePin((h)->dir_port, (h)->dir_pin, GPIO_PIN_SET)
#define RS485_DIR_RX(h) HAL_GPIO_WritePin((h)->dir_port, (h)->dir_pin, GPIO_PIN_RESET)
/*
* 公共函数实现
*/
/*
* 函数功能:åˆ<C3A5>å§åŒ RS-485 å<>¥æŸ„
* å…¥å<C2A5>£å<C2A3>数:handle - RS-485 å<>¥æŸ„指éˆ
* huart - UART å¤è®¾å<C2BE>¥æŸ„
* dir_port - DE 引脚 GPIO 端å<C2AF>£
* dir_pin - DE 引脚 GPIO ç¼å<E28093>·
* 返回值:ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šUART ï¿?GPIO 须先ï¿?CubeMX 完æˆ<C3A6>åˆ<C3A5>å§ï¿? * 函数说明:åˆ<C3A5>å§åŒå<E28093>Žç«å<E280B9>³å°† DE 拉低,使 RS-485 æ”¶å<C2B6>器处于接收状ï¿? */
void rs485_init(rs485_handle_t *p_handle,
UART_HandleTypeDef *p_huart,
GPIO_TypeDef *p_dir_port,
uint16_t dir_pin) {
p_handle->huart = p_huart;
p_handle->dir_port = p_dir_port;
p_handle->dir_pin = dir_pin;
p_handle->rx_size = 0;
/* 默认进入接收状�?*/
RS485_DIR_RX(p_handle);
}
/*
* 函数功能:阻塞æ¹å¼<C3A5>å<EFBFBD>é€<C3A9>æ•°ï¿? * å…¥å<C2A5>£å<C2A3>数:handle - RS-485 å<>¥æŸ„指éˆ
* data - å¾…å<E280A6>é€<C3A9>æ•°æ<C2B0>®ç¼“冲区
* len - å¾…å<E280A6>é€<C3A9>å­—èŠæ•°
* timeout - å<>é€<C3A9>超时(ms),ï¿?0 使用默认ï¿? * è¿”åžå€¼ï¼šHAL_OK / HAL_TIMEOUT / HAL_ERROR
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šé¡»åœ¨ä¸»å¾ªçޝï¿?RTOS 任务中调用,ä¸<C3A4>å<EFBFBD>¯ï¿?UART 中断中调ï¿? * 函数说明ï¿? * æ—¶åº<C3A5>:DE=HIGH ï¿?UART å<>�?N 字节 ï¿?ï¿?TC ï¿?DE=LOW
* HAL_UART_Transmit 内部会等ï¿?TXE(å<CB86>é€<C3A9>寄存器空)é€<C3A9>å­—èŠæ<E2809A>¬æ•°æ<C2B0>®ï¿? * 最å<E282AC>Žè¿˜ä¼šç­‰ï¿?TC(å<CB86>é€<C3A9>完æˆ<C3A6>)标志,确ä¿<C3A4>最å<E282AC>Žä¸€å­—èŠçš„å<E2809E>œæ­¢ä½<C3A4>已移出�? * å æ­¤è¿”åžå<C5BE>Žå†<C3A5>æ‰ä½Ž DE 是安全的
*/
HAL_StatusTypeDef rs485_transmit(rs485_handle_t *p_handle,
const uint8_t *p_data,
uint16_t len,
uint32_t timeout) {
HAL_StatusTypeDef status = HAL_OK;
if (timeout == 0U) {
timeout = RS485_TIMEOUT_DEFAULT;
}
/* 1. 切æ<E280A1>¢åˆ°å<C2B0>é€<C3A9>状ï¿?*/
RS485_DIR_TX(p_handle);
/* 2. 阻塞å<C5BE>é€<C3A9>(内部等待 TCï¿?*/
status = HAL_UART_Transmit(p_handle->huart,
(uint8_t *)p_data,
len,
timeout);
/* 3. å<>é€<C3A9>完毕æˆè¶…æ—¶ï¼Œåˆ‡åžæŽ¥æ”¶çŠ¶ï¿?*/
RS485_DIR_RX(p_handle);
return status;
}
/*
* 函数功能:å<C5A1>¯åŠ¨ä¸­æ­æ¹å¼<C3A5>接收(IDLE 空闲帧检测)
* å…¥å<C2A5>£å<C2A3>数:handle - RS-485 å<>¥æŸ„指éˆ
* buf - 接收缓冲ï¿? * buf_size - 缓冲区最大容ï¿? * è¿”åžå€¼ï¼šHAL_OK / HAL_ERROR
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šUART 须已开å<E282AC>¯å…¨å±€ä¸­æ­ï¼ˆNVIC 使能ï¿? * 函数说明ï¿? * 使用 HAL_UARTEx_ReceiveToIdle_IT 实现å<C2B0>˜é•¿å¸§æŽ¥æ”¶ï¿½? * ï¿?UART 总线空闲超过 1 个字符时间å<C2B4>Žï¼Œç¡¬ä»¶è§¦ï¿?IDLE 中断ï¿? * HAL 自动调用 HAL_UARTEx_RxEventCallback 并返回已接收字节数�? * 用户须在该åžè°ƒä¸­é‡<C3A9>æ°è°ƒç”¨æœ¬å‡½æ•°é‡<C3A9>æ°å¼€å<E282AC>¯æŽ¥ï¿? */
HAL_StatusTypeDef rs485_receive_start(rs485_handle_t *p_handle,
uint8_t *p_buf,
uint16_t buf_size) {
p_handle->rx_size = 0;
return HAL_UARTEx_ReceiveToIdle_IT(p_handle->huart, p_buf, buf_size);
}
/*
* 函数功能:缓存最近一次接收的字节ï¿? * å…¥å<C2A5>£å<C2A3>数:handle - RS-485 å<>¥æŸ„指éˆ
* size - 本次接收到的字节ï¿? * 返回值:ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šé¡»ï¿?HAL_UARTEx_RxEventCallback 中调ï¿? */
void rs485_rx_set_size(rs485_handle_t *p_handle, uint16_t size) {
p_handle->rx_size = size;
}
/*
* 函数功能:获å<C2B7>最è¿ä¸€æ¬¡æŽ¥æ”¶çš„å­—èŠï¿? * å…¥å<C2A5>£å<C2A3>数:handle - RS-485 å<>¥æŸ„指éˆ
* 返回值:字节� */
uint16_t rs485_rx_get_size(const rs485_handle_t *p_handle) {
return p_handle->rx_size;
}