This commit is contained in:
2026-01-30 17:04:39 +08:00
parent b94a28aacf
commit ef112855bf
30 changed files with 2786 additions and 4505 deletions
-1
View File
@@ -1,5 +1,4 @@
#include "bsp_74HC4067.h"
#include "os_timer.h"
/*两片74HC4067,一片TX 一片RX 每片16通道*/
+9 -9
View File
@@ -1,5 +1,5 @@
#include "bsp_Led.h"
#include "os_timer.h"
#include "app_timer.h"
#define LED1_ON HAL_GPIO_WritePin (LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET)
#define LED1_OFF HAL_GPIO_WritePin (LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET)
@@ -14,25 +14,25 @@
#define LED3_TOGGLE HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin)
static void bsp_Led_Init(void);
static void bsp_Led_Flash(void);
static void bsp_led_init(void);
static void bsp_led_task(void);
bsp_Led_t Led =
bsp_led_t led =
{
.Init = bsp_Led_Init,
.Flash = bsp_Led_Flash,
.init = bsp_led_init,
.task = bsp_led_task,
};
/*其他外设初始化后快速闪烁,提示初始化完成*/
static void bsp_Led_Init(void)
static void bsp_led_init(void)
{
for(u8 i = 0;i < 20;i++)
{
Delay_ms(50);
delay_ms(50);
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
}
}
static void bsp_Led_Flash(void)
static void bsp_led_task(void)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
}
+4 -4
View File
@@ -6,10 +6,10 @@
typedef struct
{
void (*Init)(void);
void (*Flash)(void);
}bsp_Led_t;
void (*init)(void);
void (*task)(void);
}bsp_led_t;
extern bsp_Led_t Led;
extern bsp_led_t led;
#endif
-396
View File
@@ -1,396 +0,0 @@
#include "bsp_Uart.h"
#include "string.h"
//#define RS485_RX HAL_GPIO_WritePin(RS485_EN_GPIO_Port, RS485_EN_Pin, GPIO_PIN_RESET)
#define RS485_RX HAL_GPIO_WritePin(RS485_EN_GPIO_Port, RS485_EN_Pin, GPIO_PIN_SET)
#define RS485_TX HAL_GPIO_WritePin(RS485_EN_GPIO_Port, RS485_EN_Pin, GPIO_PIN_SET)
/*缓冲收发区*/
#define RX_TEMP_BUFF_NUM (3000U)
u8 Rx_Temp_Buff[RX_TEMP_BUFF_NUM];
#define UART1_TX_LEN (3000U)
#define UART1_RX_LEN (3000U)
#define UART2_TX_LEN (3000U)
#define UART2_RX_LEN (3000U)
#define UART4_TX_LEN (3000U)
#define UART4_RX_LEN (3000U)
u8 Uart1_TX_Buff[UART1_TX_LEN];
u8 Uart1_Rx_Buff[UART1_RX_LEN];
u8 Uart2_TX_Buff[UART2_TX_LEN];
u8 Uart2_Rx_Buff[UART2_RX_LEN];
u8 Uart4_TX_Buff[UART4_TX_LEN];
u8 Uart4_Rx_Buff[UART4_RX_LEN];
static void bsp_Uart_Init(bsp_Uart_t *p_Uart);
static void bsp_Uart_Send(bsp_Uart_t *p_Uart,u8 *pData, u16 Len);
static void bsp_Uart_Rx_IdleInt(bsp_Uart_t *p_Uart);
static void bsp_Uart_Rx_TimeIncrement(bsp_Uart_t *p_Uart,u16 Time);
static void bsp_Uart_Rx_Task(bsp_Uart_t *p_Uart);
static void bsp_Uart_Rx_TimeStart(bsp_Uart_t *p_Uart);
static void bsp_Uart_Tx_DMA_TCInt(bsp_Uart_t *p_Uart);
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart4;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart2_tx;
extern DMA_HandleTypeDef hdma_uart4_rx;
extern DMA_HandleTypeDef hdma_uart4_tx;
bsp_Uart_t COM_Uart1 =
{
.RxQueue = queue(u8,UART1_RX_LEN),
.Uart =&huart1,
.Tx_DMA = &hdma_usart1_tx,
.Rx_DMA = &hdma_usart1_rx,
.Tx_DMA_Len = UART1_TX_LEN,
.Rx_DMA_Len = UART1_RX_LEN,
.Tx_Addr = &Uart1_TX_Buff[0],
.Rx_Addr = &Uart1_Rx_Buff[0],
.Tx_DMA_CompleteFlag = 1,
.Rx_TimeOver = 0,
.relay.uart = NULL,
.Init = bsp_Uart_Init,
.Send = bsp_Uart_Send,
.Tx_DMA_TCInt = bsp_Uart_Tx_DMA_TCInt,
.Rx_IdleInt = bsp_Uart_Rx_IdleInt,
.Rx_TimeIncrementInt = bsp_Uart_Rx_TimeIncrement,
.Rx_DataAnalysis = NULL,
.Rx_Task = bsp_Uart_Rx_Task,
};
bsp_Uart_t COM_Uart2 =
{
.RxQueue = queue(u8,UART2_RX_LEN),
.Uart =&huart2,
.Tx_DMA = &hdma_usart2_tx,
.Rx_DMA = &hdma_usart2_rx,
.Tx_DMA_Len = UART2_TX_LEN,
.Rx_DMA_Len = UART2_RX_LEN,
.Tx_Addr = &Uart2_TX_Buff[0],
.Rx_Addr = &Uart2_Rx_Buff[0],
.Tx_DMA_CompleteFlag = 1,
.Rx_TimeOver = 0,
.relay.uart = &COM_Uart4,
.Init = bsp_Uart_Init,
.Send = bsp_Uart_Send,
.Tx_DMA_TCInt = bsp_Uart_Tx_DMA_TCInt,
.Rx_IdleInt = bsp_Uart_Rx_IdleInt,
.Rx_TimeIncrementInt = bsp_Uart_Rx_TimeIncrement,
.Rx_DataAnalysis = NULL,
.Rx_Task = bsp_Uart_Rx_Task,
};
bsp_Uart_t COM_Uart4 =
{
.RxQueue = queue(u8,UART4_RX_LEN),
.Uart =&huart4,
.Tx_DMA = &hdma_uart4_tx,
.Rx_DMA = &hdma_uart4_rx,
.Tx_DMA_Len = UART4_TX_LEN,
.Rx_DMA_Len = UART4_RX_LEN,
.Tx_Addr = &Uart4_TX_Buff[0],
.Rx_Addr = &Uart4_Rx_Buff[0],
.Tx_DMA_CompleteFlag = 1,
.Rx_TimeOver = 0,
.relay.uart = NULL,
.Init = bsp_Uart_Init,
.Send = bsp_Uart_Send,
.Tx_DMA_TCInt = bsp_Uart_Tx_DMA_TCInt,
.Rx_IdleInt = bsp_Uart_Rx_IdleInt,
.Rx_TimeIncrementInt = bsp_Uart_Rx_TimeIncrement,
.Rx_DataAnalysis = NULL,
.Rx_Task = bsp_Uart_Rx_Task,
};
/* 初始化函数 */
static void bsp_Uart_Init(bsp_Uart_t *p_Uart)
{
/*配置数据解析函数*/
//p_Uart->Rx_DataAnalysis = NULL;
/* 启用空闲中断 */
__HAL_UART_ENABLE_IT(p_Uart->Uart, UART_IT_IDLE);
/* 启动DMA接收 */
//HAL_UART_Receive_DMA(p_Uart->Uart, p_Uart->Rx_Addr, p_Uart->Rx_DMA_Len);
/* 重新启动接收 */
HAL_UARTEx_ReceiveToIdle_DMA(p_Uart->Uart, p_Uart->Rx_Addr, p_Uart->Rx_DMA_Len);
}
static void bsp_Uart_DMASend(bsp_Uart_t *p_Uart,u8 *pData, u16 Len)
{
u32 tickstart,tick;
p_Uart->Tx_DMA_CompleteFlag = 0;
if(p_Uart->Tx_DMA_Len < Len)
Len = p_Uart->Tx_DMA_Len;
memcpy(p_Uart->Tx_Addr, pData, Len); /*拷贝数据到发送缓冲*/
// /*阻塞式发送,非阻塞式发送,会导致收发数据时正好切换通道的情况*/
// HAL_UART_Transmit(p_Uart->Uart,p_Uart->Tx_Addr,Len,500);
HAL_UART_Transmit_DMA(p_Uart->Uart,p_Uart->Tx_Addr,Len);
tickstart = HAL_GetTick();
while( !p_Uart->Tx_DMA_CompleteFlag)
{
tick = HAL_GetTick();
if((tick - tickstart) > 200) // 1000ms 超时
{
p_Uart->Tx_DMA_CompleteFlag = 1;
break;
}
}
}
/*大数据量发送*/
static void bsp_Uart_Send(bsp_Uart_t *p_Uart,u8 *pData, u16 Len)
{
u16 i,SendNum;
if(p_Uart == &COM_Uart4)
RS485_TX;
SendNum = Len / p_Uart->Tx_DMA_Len;
for(i=0;i<SendNum;i++)
{
bsp_Uart_DMASend(p_Uart,&pData[p_Uart->Tx_DMA_Len * i], p_Uart->Tx_DMA_Len);
}
/*发送剩余数据*/
Len -= p_Uart->Tx_DMA_Len * i;
if(0 == Len)
{
return ;
}
else
{
bsp_Uart_DMASend(p_Uart,&pData[p_Uart->Tx_DMA_Len * i],Len);
}
}
static void bsp_Uart_Tx_DMA_TCInt(bsp_Uart_t *p_Uart)
{
p_Uart->Tx_DMA_CompleteFlag = 1;
}
/*空闲接收中断*/
static void bsp_Uart_Rx_IdleInt(bsp_Uart_t *p_Uart)
{
u16 Rx_Length, i;
/*停止接收*/
HAL_UART_DMAStop(p_Uart->Uart);
/* 计算接收到的数据长度 */
Rx_Length = p_Uart->Rx_DMA_Len - __HAL_DMA_GET_COUNTER(p_Uart->Rx_DMA);
/* 如果长度为0,直接返回 */
if (Rx_Length == 0) {
return;
}
/* 入队 */
for (i = 0; i < Rx_Length; i++)
{
queue_push_back(p_Uart->RxQueue, (void *)&p_Uart->Rx_Addr[i]);
}
/* 开始计数 */
bsp_Uart_Rx_TimeStart(p_Uart);
// HAL_UART_Receive_DMA(p_Uart->Uart, p_Uart->Rx_Addr, p_Uart->Rx_DMA_Len);
HAL_UARTEx_ReceiveToIdle_DMA(p_Uart->Uart, p_Uart->Rx_Addr, p_Uart->Rx_DMA_Len);
}
/*中断计数*/
static void bsp_Uart_Rx_TimeIncrement(bsp_Uart_t *p_Uart,u16 Time)
{
/*开始计数*/
if(1 == p_Uart->Rx_StartFlag)
{
p_Uart->Rx_TimeCount += Time;
}
}
/*开始计数*/
static void bsp_Uart_Rx_TimeStart(bsp_Uart_t *p_Uart)
{
p_Uart->Rx_StartFlag = 1;
p_Uart->Rx_TimeCount = 0;
}
/*停止计数*/
static void bsp_Uart_Rx_TimeStop(bsp_Uart_t *p_Uart)
{
p_Uart->Rx_StartFlag = 0;
p_Uart->Rx_TimeCount = 0;
}
static void bsp_Uart_Rx_Task(bsp_Uart_t *p_Uart)
{
/*超时计数完成,接收到一帧数据*/
if(p_Uart->Rx_TimeOver < p_Uart->Rx_TimeCount)
{
p_Uart->Rx_Len = queue_size(p_Uart->RxQueue);
/*停止计数*/
bsp_Uart_Rx_TimeStop(p_Uart);
if(p_Uart->Rx_Len <= p_Uart->Rx_DMA_Len && (0 != p_Uart->Rx_Len))
{
if(RX_TEMP_BUFF_NUM < p_Uart->Rx_Len)
{
queue_clear(p_Uart->RxQueue);
}
else
{
for(u16 i = 0;i < p_Uart->Rx_Len;i++)
{
queue_pop(p_Uart->RxQueue,&Rx_Temp_Buff[i]);
}
if(NULL != p_Uart->Rx_DataAnalysis)
{
p_Uart->Rx_DataAnalysis(Rx_Temp_Buff,p_Uart->Rx_Len,p_Uart); /*解析数据*/
}
// p_Uart->Send(p_Uart,Rx_Temp_Buff,p_Uart->Rx_Len);
}
}
}
}
// 错误回调函数中处理ORE
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
bsp_Uart_t *p_Uart = NULL;
if (huart->Instance == USART1)
{
p_Uart = &COM_Uart1;
}
else if (huart->Instance == USART2)
{
p_Uart = &COM_Uart2;
}
else if (huart->Instance == UART4)
{
p_Uart = &COM_Uart4;
}
// 检查具体错误类型
if(huart->ErrorCode & HAL_UART_ERROR_NE)
{
// 处理噪声错误
__HAL_UART_CLEAR_NEFLAG(huart);
}
if(huart->ErrorCode & HAL_UART_ERROR_FE)
{
// 处理帧错误
__HAL_UART_CLEAR_FEFLAG(huart);
}
// 其他错误处理...
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET)
{
__HAL_UART_CLEAR_OREFLAG(huart); // 清除ORE标志
}
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_FE) != RESET)
{
__HAL_UART_CLEAR_FEFLAG(huart); // 清除ORE标志
}
//
if(p_Uart != NULL)
{
// HAL_UART_DeInit(huart);
// HAL_UART_Init(huart);
// HAL_UART_DMAStop(p_Uart->Uart);
HAL_UARTEx_ReceiveToIdle_DMA(p_Uart->Uart, p_Uart->Rx_Addr, p_Uart->Rx_DMA_Len);
}
}
// 实现空闲中断回调
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if (huart->Instance == USART1)
{
bsp_Uart_Rx_IdleInt(&COM_Uart1);
}
else if (huart->Instance == USART2)
{
bsp_Uart_Rx_IdleInt(&COM_Uart2);
}
else if (huart->Instance == UART4)
{
bsp_Uart_Rx_IdleInt(&COM_Uart4);
}
}
/* 串口接收完成回调函数 - 处理空闲中断 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
// {
// __HAL_UART_CLEAR_IDLEFLAG(huart);
// if (huart->Instance == USART1)
// {
// bsp_Uart_Rx_IdleInt(&COM_Uart1);
// }
// else if (huart->Instance == USART2)
// {
// bsp_Uart_Rx_IdleInt(&COM_Uart2);
// }
// else if (huart->Instance == UART4)
// {
// bsp_Uart_Rx_IdleInt(&COM_Uart4);
// }
// }
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
COM_Uart1.Tx_DMA_TCInt(&COM_Uart1);
}
else if (huart->Instance == USART2)
{
COM_Uart2.Tx_DMA_TCInt(&COM_Uart2);
}
else if (huart->Instance == UART4)
{
RS485_RX;
COM_Uart4.Tx_DMA_TCInt(&COM_Uart4);
}
}
-59
View File
@@ -1,59 +0,0 @@
#ifndef _BSP_UART_H_
#define _BSP_UART_H_
#include "main.h"
#include "algo_Queue.h"
typedef struct bsp_Uart_t bsp_Uart_t;
#define usart_type UART_HandleTypeDef
#define dma_type DMA_HandleTypeDef
/*串口转发*/
typedef struct
{
u8 flag; /*串口转发标志位*/
bsp_Uart_t *uart; /*转发出去的串口*/
u16 time_out; /*转发超时时间*/
}bsp_uart_relay_t;
struct bsp_Uart_t
{
queue RxQueue; /*数据接收队列*/
usart_type *Uart; /*串口*/
dma_type *Tx_DMA; /*DMA*/
dma_type *Rx_DMA;
u8 Tx_DMA_CH;
u8 Rx_DMA_CH;
vu8 Tx_DMA_CompleteFlag; /*DMA接受完成标志位*/
u8 *Tx_Addr; /*DMA搬运缓冲*/
u8 *Rx_Addr;
u16 Tx_DMA_Len;
u16 Rx_DMA_Len;
u16 Rx_Len; /*接收到的数据长度*/
u16 Rx_TimeCount; /*超时计数*/
u16 Rx_TimeOver; /*超时时间*/
u8 Rx_StartFlag; /*开始超时计数标志位*/
bsp_uart_relay_t relay; /*串口转发*/
void (*Init)(bsp_Uart_t *); /*初始化*/
void (*Send)(bsp_Uart_t *,u8 *,u16); /*串口发送函数*/
void (*Tx_DMA_TCInt)(bsp_Uart_t *); /*DMA发送完成中断*/
void (*Rx_IdleInt)(bsp_Uart_t *); /*空闲中断*/
void (*Rx_TimeIncrementInt)(bsp_Uart_t *,u16); /*中断计数计数*/
void (*Rx_DataAnalysis)(u8 *,u16,void *); /*数据解析*/
void (*Rx_Task)(bsp_Uart_t *); /*串口接收任务*/
};
extern bsp_Uart_t COM_Uart1;
extern bsp_Uart_t COM_Uart2;
extern bsp_Uart_t COM_Uart4;
#endif
+489
View File
@@ -0,0 +1,489 @@
#include "bsp_uart.h"
#include "string.h"
/* RS485控制宏定义 */
#define RS485_RX HAL_GPIO_WritePin(RS485_EN_GPIO_Port, RS485_EN_Pin, GPIO_PIN_SET)
#define RS485_TX HAL_GPIO_WritePin(RS485_EN_GPIO_Port, RS485_EN_Pin, GPIO_PIN_SET)
/* 缓冲收发区大小 */
#define RX_TEMP_BUFF_NUM (3000U)
/* UART缓冲区大小定义 */
#define UART1_TX_LEN (3000U)
#define UART1_RX_LEN (3000U)
#define UART2_TX_LEN (3000U)
#define UART2_RX_LEN (3000U)
#define UART4_TX_LEN (3000U)
#define UART4_RX_LEN (3000U)
/* 全局缓冲区变量 */
u8 uart1_tx_buff[UART1_TX_LEN];
u8 uart1_rx_buff[UART1_RX_LEN];
u8 uart2_tx_buff[UART2_TX_LEN];
u8 uart2_rx_buff[UART2_RX_LEN];
u8 uart4_tx_buff[UART4_TX_LEN];
u8 uart4_rx_buff[UART4_RX_LEN];
u8 rx_temp_buff[RX_TEMP_BUFF_NUM];
/* 函数声明 */
static void bsp_uart_init(bsp_uart_t *p_uart);
static void bsp_uart_send(bsp_uart_t *p_uart, u8 *p_data, u16 len);
static void bsp_uart_rx_idle_int(bsp_uart_t *p_uart);
static void bsp_uart_rx_time_increment(bsp_uart_t *p_uart, u16 time);
static void bsp_uart_rx_task(bsp_uart_t *p_uart);
static void bsp_uart_rx_time_start(bsp_uart_t *p_uart);
static void bsp_uart_tx_dma_tc_int(bsp_uart_t *p_uart);
static void bsp_uart_dma_send(bsp_uart_t *p_uart, u8 *p_data, u16 len);
/* 外部HAL句柄声明 */
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart4;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart2_tx;
extern DMA_HandleTypeDef hdma_uart4_rx;
extern DMA_HandleTypeDef hdma_uart4_tx;
/******************************************
* 结构体: com_uart1
* 功能: UART1控制实例
* 描述: 定义UART1的硬件参数和回调函数
*******************************************/
bsp_uart_t com_uart1 =
{
.rx_queue = queue(u8, UART1_RX_LEN),
.uart = &huart1,
.tx_dma = &hdma_usart1_tx,
.rx_dma = &hdma_usart1_rx,
.tx_dma_len = UART1_TX_LEN,
.rx_dma_len = UART1_RX_LEN,
.tx_addr = &uart1_tx_buff[0],
.rx_addr = &uart1_rx_buff[0],
.tx_dma_complete_flag = 1,
.rx_time_over = 0,
.relay.uart = NULL,
.init = bsp_uart_init,
.send = bsp_uart_send,
.tx_dma_tc_int = bsp_uart_tx_dma_tc_int,
.rx_idle_int = bsp_uart_rx_idle_int,
.rx_time_increment_int = bsp_uart_rx_time_increment,
.rx_data_analysis = NULL,
.rx_task = bsp_uart_rx_task,
};
/******************************************
* 结构体: com_uart2
* 功能: UART2控制实例
* 描述: 定义UART2的硬件参数和回调函数
*******************************************/
bsp_uart_t com_uart2 =
{
.rx_queue = queue(u8, UART2_RX_LEN),
.uart = &huart2,
.tx_dma = &hdma_usart2_tx,
.rx_dma = &hdma_usart2_rx,
.tx_dma_len = UART2_TX_LEN,
.rx_dma_len = UART2_RX_LEN,
.tx_addr = &uart2_tx_buff[0],
.rx_addr = &uart2_rx_buff[0],
.tx_dma_complete_flag = 1,
.rx_time_over = 0,
.relay.uart = &com_uart4,
.init = bsp_uart_init,
.send = bsp_uart_send,
.tx_dma_tc_int = bsp_uart_tx_dma_tc_int,
.rx_idle_int = bsp_uart_rx_idle_int,
.rx_time_increment_int = bsp_uart_rx_time_increment,
.rx_data_analysis = NULL,
.rx_task = bsp_uart_rx_task,
};
/******************************************
* 结构体: com_uart4
* 功能: UART4控制实例
* 描述: 定义UART4的硬件参数和回调函数
*******************************************/
bsp_uart_t com_uart4 =
{
.rx_queue = queue(u8, UART4_RX_LEN),
.uart = &huart4,
.tx_dma = &hdma_uart4_tx,
.rx_dma = &hdma_uart4_rx,
.tx_dma_len = UART4_TX_LEN,
.rx_dma_len = UART4_RX_LEN,
.tx_addr = &uart4_tx_buff[0],
.rx_addr = &uart4_rx_buff[0],
.tx_dma_complete_flag = 1,
.rx_time_over = 0,
.relay.uart = NULL,
.init = bsp_uart_init,
.send = bsp_uart_send,
.tx_dma_tc_int = bsp_uart_tx_dma_tc_int,
.rx_idle_int = bsp_uart_rx_idle_int,
.rx_time_increment_int = bsp_uart_rx_time_increment,
.rx_data_analysis = NULL,
.rx_task = bsp_uart_rx_task,
};
/******************************************
* 函数: bsp_uart_init
* 功能: UART初始化
* 参数: p_uart - 指向UART结构体的指针
* 返回: 无
* 描述: 初始化UART,使能空闲中断和DMA接收
*******************************************/
static void bsp_uart_init(bsp_uart_t *p_uart)
{
/* 启用空闲中断 */
__HAL_UART_ENABLE_IT(p_uart->uart, UART_IT_IDLE);
/* 重新启动接收,使用空闲中断模式 */
HAL_UARTEx_ReceiveToIdle_DMA(p_uart->uart, p_uart->rx_addr, p_uart->rx_dma_len);
}
/******************************************
* 函数: bsp_uart_dma_send
* 功能: DMA发送函数
* 参数: p_uart - 指向UART结构体的指针
* p_data - 要发送的数据指针
* len - 要发送的数据长度
* 返回: 无
* 描述: 使用DMA发送数据,带有超时检测
*******************************************/
static void bsp_uart_dma_send(bsp_uart_t *p_uart, u8 *p_data, u16 len)
{
u32 tick_start, tick;
p_uart->tx_dma_complete_flag = 0;
/* 如果请求发送的长度大于缓冲区长度,则截断 */
if(p_uart->tx_dma_len < len)
len = p_uart->tx_dma_len;
/* 拷贝数据到发送缓冲区 */
memcpy(p_uart->tx_addr, p_data, len);
/* 启动DMA发送 */
HAL_UART_Transmit_DMA(p_uart->uart, p_uart->tx_addr, len);
/* 等待发送完成,带超时检测 */
tick_start = HAL_GetTick();
while(!p_uart->tx_dma_complete_flag)
{
tick = HAL_GetTick();
if((tick - tick_start) > 200) /* 200ms超时 */
{
p_uart->tx_dma_complete_flag = 1;
break;
}
}
}
/******************************************
* 函数: bsp_uart_send
* 功能: UART发送函数
* 参数: p_uart - 指向UART结构体的指针
* p_data - 要发送的数据指针
* len - 要发送的数据长度
* 返回: 无
* 描述: 大数据量发送函数,支持分块发送
*******************************************/
static void bsp_uart_send(bsp_uart_t *p_uart, u8 *p_data, u16 len)
{
u16 i, send_num;
/* RS485切换到发送模式 */
if(p_uart == &com_uart4)
RS485_TX;
/* 计算需要发送的次数 */
send_num = len / p_uart->tx_dma_len;
/* 分块发送数据 */
for(i = 0; i < send_num; i++)
{
bsp_uart_dma_send(p_uart, &p_data[p_uart->tx_dma_len * i], p_uart->tx_dma_len);
}
/* 发送剩余数据 */
len -= p_uart->tx_dma_len * i;
if(0 == len)
{
return;
}
else
{
bsp_uart_dma_send(p_uart, &p_data[p_uart->tx_dma_len * i], len);
}
}
/******************************************
* 函数: bsp_uart_tx_dma_tc_int
* 功能: DMA发送完成中断处理
* 参数: p_uart - 指向UART结构体的指针
* 返回: 无
* 描述: 在DMA发送完成中断中调用,设置发送完成标志
*******************************************/
static void bsp_uart_tx_dma_tc_int(bsp_uart_t *p_uart)
{
p_uart->tx_dma_complete_flag = 1;
}
/******************************************
* 函数: bsp_uart_rx_idle_int
* 功能: 空闲中断处理
* 参数: p_uart - 指向UART结构体的指针
* 返回: 无
* 描述: 处理UART空闲中断,将接收到的数据存入队列
*******************************************/
static void bsp_uart_rx_idle_int(bsp_uart_t *p_uart)
{
u16 rx_length, i;
/* 停止接收 */
HAL_UART_DMAStop(p_uart->uart);
/* 计算接收到的数据长度 */
rx_length = p_uart->rx_dma_len - __HAL_DMA_GET_COUNTER(p_uart->rx_dma);
/* 如果长度为0,直接返回 */
if (rx_length == 0)
{
return;
}
/* 将接收到的数据存入队列 */
for (i = 0; i < rx_length; i++)
{
queue_push_back(p_uart->rx_queue, (void *)&p_uart->rx_addr[i]);
}
/* 开始接收超时计时 */
bsp_uart_rx_time_start(p_uart);
/* 重新启动接收 */
HAL_UARTEx_ReceiveToIdle_DMA(p_uart->uart, p_uart->rx_addr, p_uart->rx_dma_len);
}
/******************************************
* 函数: bsp_uart_rx_time_increment
* 功能: 接收超时时间递增
* 参数: p_uart - 指向UART结构体的指针
* time - 增加的时间值
* 返回: 无
* 描述: 在中断中调用,递增接收超时计数器
*******************************************/
static void bsp_uart_rx_time_increment(bsp_uart_t *p_uart, u16 time)
{
/* 如果已经开始计数,则增加时间 */
if(1 == p_uart->rx_start_flag)
{
p_uart->rx_time_count += time;
}
}
/******************************************
* 函数: bsp_uart_rx_time_start
* 功能: 启动接收超时计时
* 参数: p_uart - 指向UART结构体的指针
* 返回: 无
* 描述: 开始接收超时计数
*******************************************/
static void bsp_uart_rx_time_start(bsp_uart_t *p_uart)
{
p_uart->rx_start_flag = 1;
p_uart->rx_time_count = 0;
}
/******************************************
* 函数: bsp_uart_rx_time_stop
* 功能: 停止接收超时计时
* 参数: p_uart - 指向UART结构体的指针
* 返回: 无
* 描述: 停止接收超时计数
*******************************************/
static void bsp_uart_rx_time_stop(bsp_uart_t *p_uart)
{
p_uart->rx_start_flag = 0;
p_uart->rx_time_count = 0;
}
/******************************************
* 函数: bsp_uart_rx_task
* 功能: UART接收任务
* 参数: p_uart - 指向UART结构体的指针
* 返回: 无
* 描述: 检查接收超时,处理接收到的数据帧
*******************************************/
static void bsp_uart_rx_task(bsp_uart_t *p_uart)
{
/* 检查是否超时,接收到一帧数据 */
if(p_uart->rx_time_over < p_uart->rx_time_count)
{
/* 获取队列中数据长度 */
p_uart->rx_len = queue_size(p_uart->rx_queue);
/* 停止计时 */
bsp_uart_rx_time_stop(p_uart);
/* 检查数据长度是否有效 */
if(p_uart->rx_len <= p_uart->rx_dma_len && (0 != p_uart->rx_len))
{
/* 如果数据长度超过临时缓冲区大小,则清空队列 */
if(RX_TEMP_BUFF_NUM < p_uart->rx_len)
{
queue_clear(p_uart->rx_queue);
}
else
{
/* 从队列中取出数据到临时缓冲区 */
for(u16 i = 0; i < p_uart->rx_len; i++)
{
queue_pop(p_uart->rx_queue, &rx_temp_buff[i]);
}
/* 如果有数据解析函数,则调用解析函数 */
if(NULL != p_uart->rx_data_analysis)
{
p_uart->rx_data_analysis(rx_temp_buff, p_uart->rx_len, p_uart);
}
}
}
}
}
// 错误回调函数中处理ORE
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
bsp_uart_t *p_uart = NULL;
if (huart->Instance == USART1)
{
p_uart = &com_uart1;
}
else if (huart->Instance == USART2)
{
p_uart = &com_uart2;
}
else if (huart->Instance == UART4)
{
p_uart = &com_uart4;
}
// 检查具体错误类型
if(huart->ErrorCode & HAL_UART_ERROR_NE)
{
// 处理噪声错误
__HAL_UART_CLEAR_NEFLAG(huart);
}
if(huart->ErrorCode & HAL_UART_ERROR_FE)
{
// 处理帧错误
__HAL_UART_CLEAR_FEFLAG(huart);
}
// 其他错误处理...
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET)
{
__HAL_UART_CLEAR_OREFLAG(huart); // 清除ORE标志
}
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_FE) != RESET)
{
__HAL_UART_CLEAR_FEFLAG(huart); // 清除ORE标志
}
//
if(p_uart != NULL)
{
// HAL_UART_DeInit(huart);
// HAL_UART_Init(huart);
// HAL_UART_DMAStop(p_Uart->Uart);
HAL_UARTEx_ReceiveToIdle_DMA(p_uart->uart, p_uart->rx_addr, p_uart->rx_dma_len);
}
}
// 实现空闲中断回调
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if (huart->Instance == USART1)
{
bsp_uart_rx_idle_int(&com_uart1);
}
else if (huart->Instance == USART2)
{
bsp_uart_rx_idle_int(&com_uart2);
}
else if (huart->Instance == UART4)
{
bsp_uart_rx_idle_int(&com_uart4);
}
}
/* 串口接收完成回调函数 - 处理空闲中断 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
// {
// __HAL_UART_CLEAR_IDLEFLAG(huart);
// if (huart->Instance == USART1)
// {
// bsp_Uart_Rx_IdleInt(&COM_Uart1);
// }
// else if (huart->Instance == USART2)
// {
// bsp_Uart_Rx_IdleInt(&COM_Uart2);
// }
// else if (huart->Instance == UART4)
// {
// bsp_Uart_Rx_IdleInt(&COM_Uart4);
// }
// }
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
bsp_uart_tx_dma_tc_int(&com_uart1);
}
else if (huart->Instance == USART2)
{
bsp_uart_tx_dma_tc_int(&com_uart2);
}
else if (huart->Instance == UART4)
{
bsp_uart_tx_dma_tc_int(&com_uart2);
}
}
+70
View File
@@ -0,0 +1,70 @@
#ifndef _BSP_UART_H_
#define _BSP_UART_H_
#include "main.h"
#include "algo_queue.h"
/******************************************
* 结构体: bsp_uart_t
* 功能: UART控制结构体
* 描述: 包含UART的所有配置和状态信息
*******************************************/
typedef struct bsp_uart_t bsp_uart_t;
/* 类型重定义 */
#define usart_type UART_HandleTypeDef
#define dma_type DMA_HandleTypeDef
/******************************************
* 结构体: bsp_uart_relay_t
* 功能: UART转发结构体
* 描述: 用于配置UART数据转发功能
*******************************************/
typedef struct
{
u8 flag; /* 串口转发标志位 */
bsp_uart_t *uart; /* 转发出去的串口指针 */
u16 time_out; /* 转发超时时间 */
} bsp_uart_relay_t;
struct bsp_uart_t
{
queue rx_queue; /* 数据接收队列 */
usart_type *uart; /* 串口句柄指针 */
dma_type *tx_dma; /* 发送DMA句柄 */
dma_type *rx_dma; /* 接收DMA句柄 */
u8 tx_dma_ch; /* 发送DMA通道号 */
u8 rx_dma_ch; /* 接收DMA通道号 */
vu8 tx_dma_complete_flag; /* DMA接收完成标志位 */
u8 *tx_addr; /* DMA发送缓冲区地址 */
u8 *rx_addr; /* DMA接收缓冲区地址 */
u16 tx_dma_len; /* DMA发送缓冲区长度 */
u16 rx_dma_len; /* DMA接收缓冲区长度 */
u16 rx_len; /* 接收到的数据长度 */
u16 rx_time_count; /* 超时计数 */
u16 rx_time_over; /* 超时时间 */
u8 rx_start_flag; /* 开始超时计数标志位 */
bsp_uart_relay_t relay; /* 串口转发配置 */
void (*init)(bsp_uart_t *); /* 初始化函数指针 */
void (*send)(bsp_uart_t *, u8 *, u16); /* 串口发送函数指针 */
void (*tx_dma_tc_int)(bsp_uart_t *); /* DMA发送完成中断处理函数指针 */
void (*rx_idle_int)(bsp_uart_t *); /* 空闲中断处理函数指针 */
void (*rx_time_increment_int)(bsp_uart_t *, u16); /* 中断计数函数指针 */
void (*rx_data_analysis)(u8 *, u16, void *); /* 数据解析函数指针 */
void (*rx_task)(bsp_uart_t *); /* 串口接收任务函数指针 */
};
/* 声明外部变量 */
extern bsp_uart_t com_uart1;
extern bsp_uart_t com_uart2;
extern bsp_uart_t com_uart4;
#endif
File diff suppressed because it is too large Load Diff
-155
View File
@@ -1,155 +0,0 @@
#ifndef __TJCUSARTHMI_H_
#define __TJCUSARTHMI_H_
#include "stm32f4xx.h"
#include "main.h" // 包含 HAL 库头文件
#include "bsp_Uart.h"
#include "bsp_Flash.h" // 添加Flash操作支持
// 定义使用的串口句柄(在main.c中定义的huart2
extern UART_HandleTypeDef huart2;
// 定义串口屏使用的串口
#define TJC_UART huart2
// 环形缓冲区长度
#define RINGBUFF_LEN (500)
// 指令结束符(TJC串口屏协议)
#define TJC_END_BYTES 0xFF
// 最大指令长度
#define MAX_COMMAND_LEN 200 // 增加长度以适应设备信息
// 自定义指令定义
#define CUSTOM_CMD_HEADER_0 0xAA
#define CUSTOM_CMD_HEADER_1 0x55
// 指令类型
#define CMD_DISPLAY_DATA 0x02 // 显示数据
#define CMD_ALARM 0x03 // 报警
#define CMD_DELETE_DEVICE 0x04 // 删除设备
// 显示数据子命令
#define SUB_CMD_SHOW_DEVICES 0x01 // 显示已添加的设备
#define SUB_CMD_REGION_STATS 0x02 // 主界面区域显示
#define SUB_CMD_REGION1_DEVICES 0x03 // 第一个区域设备
#define SUB_CMD_REGION2_DEVICES 0x04 // 第二个区域设备
#define SUB_CMD_REGION3_DEVICES 0x05 // 第三个区域设备
#define SUB_CMD_REGION4_DEVICES 0x06 // 第四个区域设备
// 报警子命令
#define SUB_CMD_HISTORY_ALARM 0x01 // 历史报警
#define SUB_CMD_REALTIME_ALARM 0x02 // 实时报警
// 添加设备指令识别
#define ADD_DEVICE_CMD_BYTE 0x43 // 'C'的ASCII码
// 分隔符
#define DATA_SEPARATOR 0xAA
// 通信状态枚举
typedef enum {
COMM_STATUS_NORMAL = 0, // 正常
COMM_STATUS_ABNORMAL // 异常
} CommStatus;
// 漏液状态枚举
typedef enum {
LEAK_NORMAL = 0, // 正常
LEAK_ABNORMAL // 漏液
} LeakStatus;
// 断带状态枚举
typedef enum {
BREAK_NORMAL = 0, // 正常
BREAK_ABNORMAL // 断带
} BreakStatus;
// 通道状态结构体
typedef struct {
LeakStatus leak_status; // 漏液状态
BreakStatus break_status; // 断带状态
int leak_meter; // 漏液米数(如果漏液状态为漏液,则显示具体米数,否则显示0)
} ChannelStatus;
// 报警类型枚举
typedef enum {
ALARM_LEAK = 0, // 漏液
ALARM_BREAK, // 断带
ALARM_COMM // 通信异常
} AlarmType;
// 设备信息结构体
typedef struct {
uint8_t port; // 端口号
char region[20]; // 区域名(英文)
uint8_t device_id; // 设备ID (1-254)
char device_name[20]; // 设备名(英文)
LeakStatus leak_status; // 漏液状态
BreakStatus break_status; // 断带状态
CommStatus comm_status; // 通信状态
ChannelStatus channels[4]; // 四个通道的状态
} DeviceInfo;
// 报警信息结构体
typedef struct {
char region[20]; // 设备区域
uint8_t device_id; // 设备ID
char device_name[20]; // 设备名称
AlarmType alarm_type; // 报警类型
char start_time[20]; // 开始时间
char end_time[20]; // 结束时间
} AlarmInfo;
// 区域统计结构体
typedef struct {
char region_name[20]; // 区域名
uint8_t total_devices; // 总设备数量
uint8_t leak_devices; // 漏液设备数量
uint8_t break_devices; // 断带设备数量
uint8_t comm_devices; // 通信异常设备数量
} RegionStats;
// 外部可调用函数的声明
void TJC_Init(bsp_Uart_t *pUart);
void TJC_SendData(uint8_t *data, uint16_t len);
void TJCPrintf(const char *cmd, ...);
// 环形缓冲区相关函数
uint16_t TJC_CleanBufferFromInvalidPatterns(void);
void initRingBuffer(void);
void writeRingBuff(uint8_t data);
void deleteRingBuff(uint16_t size);
uint16_t getRingBuffLength(void);
uint8_t read1BFromRingBuff(uint16_t position);
uint8_t isRingBuffOverflow(void);
// 指令处理相关函数
void TJC_ProcessCommand(uint8_t *cmd, uint16_t len);
uint8_t TJC_CheckEndBytes(uint8_t *data, uint16_t len, uint16_t *end_pos);
void TJC_SendResponse(const char *response);
void TJC_ProcessSerialData(u8 *data, u16 len, void *p_arg);
void TJC_DeleteDevices(uint8_t *delete_flags, uint8_t flag_count);
void TJC_ProcessDeleteCommand(uint8_t *cmd, uint16_t len);
/*测试发送历史报警数据*/
void TJC_SendInitCommands(void);
// 新增函数声明
uint16_t CalculateCRC16(uint8_t *data, uint16_t length);
void TJC_ProcessCustomCommand(uint8_t *cmd, uint16_t len);
void TJC_SendAlarmHistory(void);
void TJC_SendRealtimeAlarms(void);
void TJC_SendDeviceList(void);
uint8_t TJC_AddDeviceToFlash(uint8_t *data, uint16_t len);
void TJC_SendRegionStats(void); // 新增:发送区域统计
void TJC_SendRegionDeviceDetails(uint8_t region_index);
// 宏定义简化
#define usize getRingBuffLength()
#define code_c() initRingBuffer()
#define udelete(x) deleteRingBuff(x)
#define u(x) read1BFromRingBuff(x)
#endif