1.驱动层(采用空闲中断接收数据,加上之前写的队列方式进行数据解耦)
创建一个接收结构体
static Queue_UART_Para rx_temp = {0};
extern UART_HandleTypeDef huart1;
extern DMA_HandleTypeDef hdma_usart1_rx;
初始化UART_DMA接收
void Driver_UART_Init_Config(void)
{
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, (uint8_t *)&rx_temp.Buffer, QueueUARTRxBufMax);
}
在空闲回调函数修改下
Function_Queue_UART_Rx_Push_aData:是将数据压入队列中
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart->Instance == USART1)
{
rx_temp.Count = QueueUARTRxBufMax - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
Function_Queue_UART_Rx_Push_aData(rx_temp);
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, (uint8_t *)&rx_temp.Buffer, QueueUARTRxBufMax);
}
}
2.任务层(这里借鉴MODBUS的协议进行修改)
HAL_UART_GetState:判断当前的状态,因为要用到rx_temp的数据,所以在发送的时候不能破坏数据
Function_Queue_UART_Rx_Pop_aData:是将数据取出来,我用10ms一次进行轮询
Command_UART_Set_Function:这是进行子命令的函数,下面会解释
void Task_UART(void)
{
uint16_t crc16_temp;
static Queue_UART_Para rx_temp;
extern UART_HandleTypeDef huart1;
if(HAL_UART_GetState(&huart1) != HAL_UART_STATE_BUSY_TX)
{
if(Function_Queue_UART_Rx_Pop_aData(&rx_temp) == Queue_OK)
{
crc16_temp = CRC_16((uint8_t *)&rx_temp.Buffer, rx_temp.Count - 2);
if(crc16_temp == ((rx_temp.Buffer[rx_temp.Count - 1] << 8) | rx_temp.Buffer[rx_temp.Count - 2]))
{
if(rx_temp.Buffer[UART_Address] == 0xFF || rx_temp.Buffer[UART_Address] == Driver_Read_Flash(UART1_Address))
{
if(Command_UART_Set_Function(rx_temp.Buffer[UART_ID], (void *)&rx_temp.Buffer) == Command_ERROR)
{
Debug("It is not this command!\r\n");
}
}
}
else
{
if(Driver_Read_Flash(UART_CDC_USB_TT_Mode) == USB_CDC_Normal)
{
Debug("Modebus CRC16 Cheak is Error!\r\n");
}
else
{
CDC_Transmit_HS((uint8_t *)&rx_temp.Buffer, rx_temp.Count);
}
}
}
}
}
3.命令层
命令层.h文件
/**
* @brief UART数据帧结构定义
*/
typedef enum
{
UART_Address = 0, /*!< UART接收数据帧起始地址 */
UART_Function, /*!< UART接收数据帧功能地址 */
UART_ID, /*!< UART接收数据帧ID地址 */
UART_DataNum, /*!< UART接收数据帧数据个数 */
UART_DataStart /*!< UART接收数据帧数据起始位 */
} UART_Type;
#define Command_UART_Read_ID 0x03 /*!< UART接收帧读功能 */
#define Command_UART_Write_ID 0x10 /*!< UART接收帧写功能 */
typedef void (*Command_UART)(void *Buf); /*!< UART任务命令重定义 */
Command_StatusTypeDef Command_UART_Set_Function(uint8_t ID, void *Buf);
命令层解析.h文件
命令解析需要主要字节对齐,这里在队列的数据中已经做了处理
#include "stdint.h"
#include "stddef.h"
#define Command_UART_DBC_Max_Buf 16
#define Command_UART_DBC_Head_Frame_Buf 4
#define Command_UART_DBC_CRC16 2
#define Command_UART_DBC_Buf Command_UART_DBC_Max_Buf - Command_UART_DBC_Head_Frame_Buf
/**
* @brief 串口DBC帧头数据
*/
typedef struct __Command_UART_DBC_Head_Frame
{
uint8_t Address;
uint8_t Function;
uint8_t ID;
uint8_t DataNum;
} Command_UART_DBC_Head_Frame;
/**
* @brief 设置地址
*/
typedef union
{
uint8_t Buf[Command_UART_DBC_Max_Buf];
struct
{
Command_UART_DBC_Head_Frame Head_Frame;
struct __Data_0
{
uint16_t SetAddr;
} Data;
uint8_t Reserve[Command_UART_DBC_Buf - sizeof(struct __Data_0)];
} bit;
} Command_UART_DBC_Set_OwnAddress;
命令层.c文件
这里需要保证每个数据帧的ID和命令的ID一样
#include "Command_UART.h"
#include "Command_UART_DBC.h"
/*!< UART功能命令函数 */
static void Command_UART_Set_OwnAddress(void *Buf);
static void Command_UART_Read_FreeRTOS_WaterMark(void *Buf);
static void Command_UART_W25Qxx_Test(void *Buf);
static void Command_UART_ST7735_Test(void *Buf);
/*!< UART功能命令列表 */
static const Command_UART CMD_UART[] =
{
Command_UART_Set_OwnAddress,
Command_UART_Read_FreeRTOS_WaterMark,
Command_UART_W25Qxx_Test,
Command_UART_ST7735_Test,
};
/*********************************************************************
* @fn Command_UART_Set_Function
*
* @brief UART功能命令设置函数.
*
* @param ID:功能ID号.
*
* @param Buf:接收数据帧.
*
* @return Command_StatusTypeDef:状态标志位
*/
Command_StatusTypeDef Command_UART_Set_Function(uint8_t ID, void *Buf)
{
if(ID < (sizeof(CMD_UART)/sizeof(CMD_UART[0])))
{
CMD_UART[ID]((void *)Buf);
return Command_OK;
}
return Command_ERROR;
}
/*********************************************************************
* @fn Command_UART_Set_OwnAddress
*
* @brief UART读取设置自身地址.
*
* @param Buf:接收数据帧
*
* @return none
*/
static void Command_UART_Set_OwnAddress(void *Buf)
{
Command_UART_DBC_Set_OwnAddress *temp = (Command_UART_DBC_Set_OwnAddress *)Buf;
if(temp->bit.Head_Frame.Function == Command_UART_Read_ID)
{
Debug("UART Address is %d", Driver_Read_Flash(UART1_Address));
}
else if(temp->bit.Head_Frame.Function == Command_UART_Write_ID)
{
//Driver_Write_Flash(UART1_Address, temp->bit.Data.SetAddr, ENABLE);
if(temp->bit.Data.SetAddr)
{
Debug("UART Set Address is %d succ", temp->bit.Data.SetAddr);
}
}
}