1.添加了必要的注释和readme文件以提高代码可读性和项目文档化。2.增加了按键按下时LCD屏幕显示功能
This commit is contained in:
@@ -1,127 +1,134 @@
|
||||
/******************************************************************************
|
||||
* @file rs485.c
|
||||
* @brief rs485串口配置,主要配置两种模式 中断接收模式 和 DMA 接收模式
|
||||
* @details
|
||||
* 1. DMA模式是主要工作模式
|
||||
* 2. 中断模式用于错误恢复和接收第一个短帧
|
||||
* 3. 中断处理完后自动切换回DMA模式
|
||||
* 4. 中断接收主要用于异常情况处理
|
||||
* @brief RS485 串口驱动 - DMA 与中断接收
|
||||
* @details 本文件实现 RS485 串口通信驱动,支持两种模式:
|
||||
* 1. DMA 模式:主工作模式,使用 ReceiveToIdle 接收不定长帧
|
||||
* 2. 中断模式:用于错误恢复或短帧接收,RXNE 逐字节接收
|
||||
* 收发通过 DE 引脚(PA1)切换:低电平发送,高电平接收。
|
||||
* @author 阜阳师范大学物电学院
|
||||
* @version V0.01
|
||||
* @date 2026.1.24
|
||||
* @note 通信协议:Modbus RTU
|
||||
* 通信接口:RS485
|
||||
* 主站地址:0x01
|
||||
* @note USART2,TX=PA2,RX=PA3,DE=PA1;波特率 700000
|
||||
******************************************************************************/
|
||||
|
||||
#include "rs485.h"
|
||||
|
||||
/* ============================================================================
|
||||
* USART 与引脚宏定义
|
||||
* ============================================================================ */
|
||||
#define RS485_UX USART2
|
||||
#define RS485_UX_IRQn USART2_IRQn
|
||||
#define RS485_UX_IRQHandler USART2_IRQHandler
|
||||
#define RS485_UX_CLK_ENABLE() do{ __HAL_RCC_USART2_CLK_ENABLE(); }while(0) /* 时钟使能 */
|
||||
#define RS485_UX_CLK_ENABLE() do{ __HAL_RCC_USART2_CLK_ENABLE(); }while(0) /**< USART2 时钟使能 */
|
||||
|
||||
#define RS485_SEND_ENABLE() do{HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);}while(0)
|
||||
#define RS485_RECEIVE_ENABLE() do{HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);}while(0)
|
||||
#define RS485_SEND_ENABLE() do{HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);}while(0) /**< DE 低:发送 */
|
||||
#define RS485_RECEIVE_ENABLE() do{HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);}while(0) /**< DE 高:接收 */
|
||||
|
||||
#define RS485_ENABLE_GPIO_PORT GPIOA
|
||||
#define RS485_ENABLE_GPIO_PIN GPIO_PIN_1
|
||||
#define RS485_ENABLE_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */
|
||||
#define RS485_ENABLE_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)
|
||||
|
||||
#define RS485_TX_GPIO_PORT GPIOA
|
||||
#define RS485_TX_GPIO_PIN GPIO_PIN_2
|
||||
#define RS485_TX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */
|
||||
#define RS485_TX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)
|
||||
|
||||
#define RS485_RX_GPIO_PORT GPIOA
|
||||
#define RS485_RX_GPIO_PIN GPIO_PIN_3
|
||||
#define RS485_RX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */
|
||||
#define RS485_RX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)
|
||||
|
||||
RS485_REGISTER_TYPE RS485REG = {RESET, {0}, {0}}; /* 零初始化定义 */
|
||||
#define BAUDRATE (700000) /**< 波特率 */
|
||||
|
||||
// HAL库UART句柄
|
||||
UART_HandleTypeDef rs485_handle; /* UART句柄 */
|
||||
// HAL库DMA句柄(接收)
|
||||
DMA_HandleTypeDef hdma_rs485_rx;
|
||||
// HAL库DMA句柄(发送)
|
||||
DMA_HandleTypeDef hdma_rs485_tx;
|
||||
/* ============================================================================
|
||||
* 全局变量定义
|
||||
* ============================================================================ */
|
||||
RS485_REGISTER_TYPE RS485REG = {RESET, {0}, {0}}; /**< RS485 收发寄存器,零初始化 */
|
||||
|
||||
UART_HandleTypeDef rs485_handle; /**< HAL UART 句柄 */
|
||||
DMA_HandleTypeDef hdma_rs485_rx; /**< HAL DMA 接收句柄(DMA1 Channel6) */
|
||||
DMA_HandleTypeDef hdma_rs485_tx; /**< HAL DMA 发送句柄(未使用,保留) */
|
||||
|
||||
#define BAUDRATE (700000)
|
||||
/* ============================================================================
|
||||
* 初始化函数
|
||||
* ============================================================================ */
|
||||
|
||||
/**
|
||||
* @brief 串口X初始化函数
|
||||
* @param baudrate: 波特率, 根据自己需要设置波特率值
|
||||
* @note 注意: 必须设置正确的时钟源, 否则串口波特率就会设置异常.
|
||||
* 这里的USART的时钟源在sys_stm32_clock_init()函数中已经设置过了.
|
||||
* @retval 无
|
||||
* @brief RS485 初始化(DMA 接收模式)
|
||||
* @note 配置流程:
|
||||
* 1. 使能 GPIO、USART 时钟
|
||||
* 2. 配置 TX(PA2)、RX(PA3)、DE(PA1)
|
||||
* 3. 配置 DMA1 Channel6 接收,关联 UART
|
||||
* 4. 使能 DMA、USART 中断
|
||||
* 5. 初始化 UART(8N1,无流控,波特率 BAUDRATE)
|
||||
* 6. 切换为接收,启动 ReceiveToIdle DMA
|
||||
* USART 时钟源需在 sys_stm32_clock_init 中已配置。
|
||||
* @retval 无
|
||||
*/
|
||||
void RS485_DMA_init()
|
||||
void RS485_DMA_init(void)
|
||||
{
|
||||
/* 开启时钟 */
|
||||
RS485_TX_GPIO_CLK_ENABLE(); /* 使能串口TX脚时钟 */
|
||||
RS485_RX_GPIO_CLK_ENABLE(); /* 使能串口RX脚时钟 */
|
||||
RS485_ENABLE_GPIO_CLK_ENABLE(); /* 使能串口RX脚时钟 */
|
||||
RS485_UX_CLK_ENABLE(); /* 使能串口时钟 */
|
||||
/* 使能时钟 */
|
||||
RS485_TX_GPIO_CLK_ENABLE();
|
||||
RS485_RX_GPIO_CLK_ENABLE();
|
||||
RS485_ENABLE_GPIO_CLK_ENABLE();
|
||||
RS485_UX_CLK_ENABLE();
|
||||
|
||||
/*GPIO 初始化设置*/
|
||||
/* GPIO 初始化 */
|
||||
GPIO_InitTypeDef gpio_init_struct = {0};
|
||||
gpio_init_struct.Pin = RS485_TX_GPIO_PIN; /* 串口发送引脚号 */
|
||||
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
|
||||
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
|
||||
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* IO速度设置为高速 */
|
||||
gpio_init_struct.Pin = RS485_TX_GPIO_PIN;
|
||||
gpio_init_struct.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_init_struct.Pull = GPIO_PULLUP;
|
||||
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(RS485_TX_GPIO_PORT, &gpio_init_struct);
|
||||
|
||||
gpio_init_struct.Pin = RS485_RX_GPIO_PIN; /* 串口RX脚 模式设置 */
|
||||
gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
|
||||
HAL_GPIO_Init(RS485_RX_GPIO_PORT, &gpio_init_struct); /* 串口RX脚 必须设置成输入模式 */
|
||||
|
||||
gpio_init_struct.Pin = RS485_ENABLE_GPIO_PIN;
|
||||
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
HAL_GPIO_Init(RS485_ENABLE_GPIO_PORT, &gpio_init_struct);
|
||||
gpio_init_struct.Pin = RS485_RX_GPIO_PIN;
|
||||
gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
|
||||
HAL_GPIO_Init(RS485_RX_GPIO_PORT, &gpio_init_struct);
|
||||
|
||||
/* 配置DMA接收句柄 */
|
||||
gpio_init_struct.Pin = RS485_ENABLE_GPIO_PIN;
|
||||
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
HAL_GPIO_Init(RS485_ENABLE_GPIO_PORT, &gpio_init_struct);
|
||||
|
||||
/* DMA 接收配置 */
|
||||
hdma_rs485_rx.Instance = DMA1_Channel6;
|
||||
hdma_rs485_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; // 外设到内存
|
||||
hdma_rs485_rx.Init.PeriphInc = DMA_PINC_DISABLE; // 外设地址不递增
|
||||
hdma_rs485_rx.Init.MemInc = DMA_MINC_ENABLE; // 内存地址递增
|
||||
hdma_rs485_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; // 外设数据对齐:字节
|
||||
hdma_rs485_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; // 内存数据对齐:字节
|
||||
hdma_rs485_rx.Init.Mode = DMA_NORMAL; // 正常模式
|
||||
hdma_rs485_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH; // 最高优先级
|
||||
HAL_DMA_Init(&hdma_rs485_rx); /*初始化DMA 接收*/
|
||||
hdma_rs485_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
hdma_rs485_rx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_rs485_rx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_rs485_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_rs485_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_rs485_rx.Init.Mode = DMA_NORMAL;
|
||||
hdma_rs485_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
|
||||
HAL_DMA_Init(&hdma_rs485_rx);
|
||||
|
||||
/* 关联 DMA 到 UART(重要!)*/
|
||||
__HAL_LINKDMA(&rs485_handle, hdmarx, hdma_rs485_rx);
|
||||
|
||||
/* 使能DMA传输完成中断 */
|
||||
HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
|
||||
HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0);
|
||||
|
||||
/* UART 初始化设置 */
|
||||
rs485_handle.Instance = RS485_UX; /* USART_UX */
|
||||
rs485_handle.Init.BaudRate = BAUDRATE; /* 波特率 */
|
||||
rs485_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
|
||||
rs485_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
|
||||
rs485_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
|
||||
rs485_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
|
||||
rs485_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
|
||||
/* UART 初始化 */
|
||||
rs485_handle.Instance = RS485_UX;
|
||||
rs485_handle.Init.BaudRate = BAUDRATE;
|
||||
rs485_handle.Init.WordLength = UART_WORDLENGTH_8B;
|
||||
rs485_handle.Init.StopBits = UART_STOPBITS_1;
|
||||
rs485_handle.Init.Parity = UART_PARITY_NONE;
|
||||
rs485_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
|
||||
rs485_handle.Init.Mode = UART_MODE_TX_RX;
|
||||
rs485_handle.Init.OverSampling = UART_OVERSAMPLING_16;
|
||||
HAL_UART_Init(&rs485_handle); /* 初始化UART */
|
||||
HAL_UART_Init(&rs485_handle);
|
||||
|
||||
HAL_NVIC_EnableIRQ(RS485_UX_IRQn); /* 使能USART中断通道 */
|
||||
HAL_NVIC_SetPriority(RS485_UX_IRQn, 1, 0); /* 组2,抢占优先级1,子优先级0 */
|
||||
|
||||
/* 启动DMA接收 */
|
||||
RS485_RECEIVE_ENABLE();
|
||||
HAL_NVIC_EnableIRQ(RS485_UX_IRQn);
|
||||
HAL_NVIC_SetPriority(RS485_UX_IRQn, 1, 0);
|
||||
|
||||
/* 启动 DMA 接收 */
|
||||
RS485_RECEIVE_ENABLE();
|
||||
HAL_UARTEx_ReceiveToIdle_DMA(&rs485_handle, (uint8_t *)RS485REG.DR, UART_RX_LEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 串口X初始化函数
|
||||
* @note 注意: 必须设置正确的时钟源, 否则串口波特率就会设置异常.
|
||||
*
|
||||
* @retval 无
|
||||
* @brief RS485 初始化(中断接收模式)
|
||||
* @note 配置 GPIO、UART,使能 RXNE 中断。不启用 DMA。
|
||||
* 用于错误恢复或接收短帧。USART 时钟源需已配置。
|
||||
* @retval 无
|
||||
*/
|
||||
void RS485_init()
|
||||
void RS485_init(void)
|
||||
{
|
||||
/* 开启时钟 */
|
||||
RS485_TX_GPIO_CLK_ENABLE(); /* 使能串口TX脚时钟 */
|
||||
@@ -129,80 +136,94 @@ void RS485_init()
|
||||
RS485_ENABLE_GPIO_CLK_ENABLE(); /* 使能串口RX脚时钟 */
|
||||
RS485_UX_CLK_ENABLE(); /* 使能串口时钟 */
|
||||
|
||||
/*GPIO 初始化设置*/
|
||||
GPIO_InitTypeDef gpio_init_struct;
|
||||
gpio_init_struct.Pin = RS485_TX_GPIO_PIN; /* 串口发送引脚号 */
|
||||
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
|
||||
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
|
||||
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* IO速度设置为高速 */
|
||||
/* GPIO 初始化 */
|
||||
GPIO_InitTypeDef gpio_init_struct = {0};
|
||||
gpio_init_struct.Pin = RS485_TX_GPIO_PIN;
|
||||
gpio_init_struct.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_init_struct.Pull = GPIO_PULLUP;
|
||||
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(RS485_TX_GPIO_PORT, &gpio_init_struct);
|
||||
|
||||
gpio_init_struct.Pin = RS485_RX_GPIO_PIN; /* 串口RX脚 模式设置 */
|
||||
gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
|
||||
HAL_GPIO_Init(RS485_RX_GPIO_PORT, &gpio_init_struct); /* 串口RX脚 必须设置成输入模式 */
|
||||
|
||||
gpio_init_struct.Pin = RS485_ENABLE_GPIO_PIN;
|
||||
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
HAL_GPIO_Init(RS485_ENABLE_GPIO_PORT, &gpio_init_struct);
|
||||
gpio_init_struct.Pin = RS485_RX_GPIO_PIN;
|
||||
gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
|
||||
HAL_GPIO_Init(RS485_RX_GPIO_PORT, &gpio_init_struct);
|
||||
|
||||
gpio_init_struct.Pin = RS485_ENABLE_GPIO_PIN;
|
||||
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
HAL_GPIO_Init(RS485_ENABLE_GPIO_PORT, &gpio_init_struct);
|
||||
|
||||
/*UART 初始化设置*/
|
||||
rs485_handle.Instance = RS485_UX; /* USART_UX */
|
||||
rs485_handle.Init.BaudRate = BAUDRATE; /* 波特率 */
|
||||
rs485_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
|
||||
rs485_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
|
||||
rs485_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
|
||||
rs485_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
|
||||
rs485_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
|
||||
HAL_UART_Init(&rs485_handle); /* 使能UART */
|
||||
/* UART 初始化 */
|
||||
rs485_handle.Instance = RS485_UX;
|
||||
rs485_handle.Init.BaudRate = BAUDRATE;
|
||||
rs485_handle.Init.WordLength = UART_WORDLENGTH_8B;
|
||||
rs485_handle.Init.StopBits = UART_STOPBITS_1;
|
||||
rs485_handle.Init.Parity = UART_PARITY_NONE;
|
||||
rs485_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
|
||||
rs485_handle.Init.Mode = UART_MODE_TX_RX;
|
||||
rs485_handle.Init.OverSampling = UART_OVERSAMPLING_16;
|
||||
HAL_UART_Init(&rs485_handle);
|
||||
|
||||
/* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */
|
||||
__HAL_UART_ENABLE_IT(&rs485_handle, UART_IT_RXNE);
|
||||
HAL_NVIC_EnableIRQ(RS485_UX_IRQn); /* 使能USART中断通道 */
|
||||
HAL_NVIC_SetPriority(RS485_UX_IRQn, 1, 0); /* 组2,抢占优先级1,子优先级0 */
|
||||
__HAL_UART_ENABLE_IT(&rs485_handle, UART_IT_RXNE);
|
||||
HAL_NVIC_EnableIRQ(RS485_UX_IRQn);
|
||||
HAL_NVIC_SetPriority(RS485_UX_IRQn, 1, 0);
|
||||
RS485_RECEIVE_ENABLE();
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* 回调与中断服务函数
|
||||
* ============================================================================ */
|
||||
|
||||
/**
|
||||
* @brief UART 接收事件回调(ReceiveToIdle 完成时由 HAL 调用)
|
||||
* @param huart UART 句柄
|
||||
* @param Size 本帧接收到的字节数
|
||||
* @note 当为 RS485 所用 UART 时:置位 NewMessageFlag,并重新启动 ReceiveToIdle DMA。
|
||||
* @retval 无
|
||||
*/
|
||||
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
|
||||
{
|
||||
if(huart->Instance == RS485_UX)
|
||||
if (huart->Instance == RS485_UX)
|
||||
{
|
||||
RS485REG.NewMessageFlag = SET;
|
||||
HAL_UARTEx_ReceiveToIdle_DMA(&rs485_handle, (uint8_t *)RS485REG.DR, UART_RX_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 485串口中断服务函数
|
||||
* @param 无
|
||||
* @retval 无
|
||||
* @brief RS485 所用 USART 中断服务函数
|
||||
* @note 调用 HAL_UART_IRQHandler 处理 UART 及关联 DMA 中断。
|
||||
* @retval 无
|
||||
*/
|
||||
void RS485_UX_IRQHandler(void)
|
||||
{
|
||||
HAL_UART_IRQHandler(&rs485_handle);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* FunctionName : DMA1_Channel6_IRQHandler()
|
||||
* Description : 串口接收中断
|
||||
* EntryParameter : none
|
||||
* ReturnValue : none
|
||||
********************************************************************************/
|
||||
/**
|
||||
* @brief DMA1 Channel6 中断服务函数(RS485 接收 DMA)
|
||||
* @note 调用 HAL_DMA_IRQHandler,在 ReceiveToIdle 完成等事件时触发。
|
||||
* @retval 无
|
||||
*/
|
||||
void DMA1_Channel6_IRQHandler(void)
|
||||
{
|
||||
HAL_DMA_IRQHandler(&hdma_rs485_rx);
|
||||
HAL_DMA_IRQHandler(&hdma_rs485_rx);
|
||||
}
|
||||
/***********************************************************************
|
||||
* FunctionName : RS485_SendBuff()
|
||||
* Description : 485发送数组
|
||||
* EntryParameter : *ptr:待发送的字符串, len:待发送的数据个数
|
||||
* ReturnValue : ptrLen:发送的数据个数
|
||||
**************************************************************************/
|
||||
|
||||
/* ============================================================================
|
||||
* 发送接口
|
||||
* ============================================================================ */
|
||||
|
||||
/**
|
||||
* @brief RS485 发送数据
|
||||
* @param ptr 待发送数据指针
|
||||
* @param len 待发送字节数
|
||||
* @note 切换为发送(DE 低)→ 阻塞发送 → 切换回接收(DE 高)。超时 1000ms。
|
||||
* @retval 无
|
||||
*/
|
||||
void RS485_SendBuff(uint8_t *ptr, uint32_t len)
|
||||
{
|
||||
RS485_SEND_ENABLE();
|
||||
|
||||
HAL_UART_Transmit(&rs485_handle, ptr,len, 1000);
|
||||
|
||||
HAL_UART_Transmit(&rs485_handle, ptr, len, 1000);
|
||||
RS485_RECEIVE_ENABLE();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,29 +1,70 @@
|
||||
/******************************************************************************
|
||||
* @file rs485.h
|
||||
* @brief RS485 串口通信驱动头文件
|
||||
* @details 本文件声明 RS485 通信相关接口与数据结构,支持 DMA 接收与中断接收两种模式。
|
||||
* 使用 USART2,收发切换通过 DE 引脚(PA1)控制。
|
||||
* @author 阜阳师范大学物电学院
|
||||
* @version V0.01
|
||||
* @date 2026.1.24
|
||||
* @note USART:USART2
|
||||
* TX:PA2,RX:PA3,DE:PA1
|
||||
* 波特率:700000
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __RS485_H__
|
||||
#define __RS485_H__
|
||||
|
||||
|
||||
|
||||
#include "./SYSTEM/sys/sys.h"
|
||||
#include "./SYSTEM/delay/delay.h"
|
||||
|
||||
#define UART_RX_LEN (3208)
|
||||
#define UART_TX_LEN (8)
|
||||
/* ============================================================================
|
||||
* 宏定义
|
||||
* ============================================================================ */
|
||||
#define UART_RX_LEN (3208) /**< 接收缓冲区长度(字节),与 Modbus 数据帧长度一致 */
|
||||
#define UART_TX_LEN (8) /**< 发送缓冲区长度(字节) */
|
||||
|
||||
/* ============================================================================
|
||||
* 数据结构定义
|
||||
* ============================================================================ */
|
||||
|
||||
/**
|
||||
* @brief RS485 收发寄存器结构体
|
||||
* @note 用于存放一帧接收数据及发送缓存,与 Modbus 处理模块配合使用
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
volatile FlagStatus NewMessageFlag; //一帧数据接收完整
|
||||
volatile uint8_t DR[UART_RX_LEN]; //接收缓存
|
||||
volatile uint8_t TDR[UART_TX_LEN]; //发送缓存
|
||||
{
|
||||
volatile FlagStatus NewMessageFlag; /**< 新消息标志:一帧数据接收完成时置位 */
|
||||
volatile uint8_t DR[UART_RX_LEN]; /**< 接收缓存 */
|
||||
volatile uint8_t TDR[UART_TX_LEN]; /**< 发送缓存 */
|
||||
} RS485_REGISTER_TYPE;
|
||||
|
||||
extern RS485_REGISTER_TYPE RS485REG;
|
||||
extern RS485_REGISTER_TYPE RS485REG; /**< 全局 RS485 收发寄存器 */
|
||||
|
||||
/* ============================================================================
|
||||
* 函数声明
|
||||
* ============================================================================ */
|
||||
|
||||
|
||||
|
||||
void USART2_Init(void);
|
||||
/**
|
||||
* @brief RS485 初始化(DMA 接收模式)
|
||||
* @note 配置 GPIO、UART、DMA,启动 ReceiveToIdle DMA 接收。为主工作模式。
|
||||
* @retval 无
|
||||
*/
|
||||
void RS485_DMA_init(void);
|
||||
|
||||
/**
|
||||
* @brief RS485 初始化(中断接收模式)
|
||||
* @note 配置 GPIO、UART,使能 RXNE 中断接收。用于异常恢复或短帧接收。
|
||||
* @retval 无
|
||||
*/
|
||||
void RS485_init(void);
|
||||
|
||||
/**
|
||||
* @brief RS485 发送数据
|
||||
* @param ptr 待发送数据指针
|
||||
* @param len 待发送字节数
|
||||
* @note 先切换为发送(DE 高),发送完成后切回接收(DE 低)。使用阻塞方式发送。
|
||||
* @retval 无
|
||||
*/
|
||||
void RS485_SendBuff(uint8_t *ptr, uint32_t len);
|
||||
|
||||
|
||||
#endif
|
||||
#endif /* __RS485_H__ */
|
||||
|
||||
Reference in New Issue
Block a user