本帖最后由 zero949079783 于 2024-11-10 23:39 编辑
FreeRTOS-串口DMA收发不定长数据+队列
#include "Usartapp.c"
#include "main.h"
#define Usart1_RX_TASK_PRIO 3 /* 任务优先级 */
#define Usart1_RX_STK_SIZE 512 /* 任务堆栈大小 */
TaskHandle_t Usart1_RXTask_Handler; /* 任务句柄 */
void Usart1_RX_task(void *pvParameters);
#define Usart1_TX_TASK_PRIO 4 /* 任务优先级 */
#define Usart1_TX_STK_SIZE 512 /* 任务堆栈大小 */
TaskHandle_t Usart1_TX_Task_Handler; /* 任务句柄 */
void Usart1_TX_task(void *pvParameters);
/*队列句柄*/
QueueHandle_t RX_queue; //串口RX队列
QueueHandle_t TX_queue; //串口RX队列
uint16_t bufflen = 0; //接收数据长度
void Usart1_RX_Isr_FunCb(uint8_t *data,uint16_t datalen)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
bufflen = datalen;
xQueueSendFromISR(RX_queue,&data,&xHigherPriorityTaskWoken); //将数据放入消息队列
if(xHigherPriorityTaskWoken == pdTRUE)
{
portYIELD_FROM_ISR(xHigherPriorityTaskWoken); //如果需要就切换任务
}
}
void Usart1_RX_task(void *pvParameters)
{
pvParameters=pvParameters;
Usart1_RX_FunCb(Usart1_RX_Isr_FunCb);
uint8_t res = 0;
uint8_t * rev_data ;
while(1)
{
res=xQueueReceive(RX_queue,&rev_data,portMAX_DELAY); //接收队列的数据
if(res == pdPASS)
{
Usart1_Txdata(rev_data,bufflen);//向队列放入数据
}
}
}
void Usart1_TX_Fun(uint8_t *data,uint16_t datalen)
{
xQueueSend(TX_queue,&data,portMAX_DELAY); //发送队列的数据
}
void Usart1_TX_task(void *pvParameters)
{
pvParameters=pvParameters;
uint8_t res = 0;
uint8_t *tx_buff;
Usart1_TX_FunCb(Usart1_TX_Fun);
while(1)
{
res = xQueueReceive(TX_queue,&tx_buff,portMAX_DELAY); //接收TX队列的数据
if(res == pdPASS)
{
Uart1_DMA_ENABLE(tx_buff,bufflen); //启动DMA
}
}
}
void UsartAPP_Task_Init(void)
{
RX_queue = xQueueCreate(10,sizeof(uint8_t *)); //串口RX队列,接收为一桢数据 存放地址就可以
if(RX_queue != NULL)
{
printf("\r\n串口RX队列创建成功\r\n");
}
TX_queue = xQueueCreate(10,sizeof(uint8_t *)); //串口TX队列,接收为一桢数据 存放地址就可以
if(TX_queue != NULL)
{
printf("\r\n串口TX队列创建成功\r\n");
}
/* Usart1_RX 任务 */
xTaskCreate((TaskFunction_t )Usart1_RX_task, /* 任务函数 */
(const char* )"Usart1_RX_task", /* 任务名称 */
(uint16_t )Usart1_RX_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传递给任务函数的参数 */
(UBaseType_t )Usart1_RX_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&Usart1_RX_task); /* 任务句柄 */
xTaskCreate((TaskFunction_t )Usart1_TX_task, /* 任务函数 */
(const char* )"Usart1_TX_task", /* 任务名称 */
(uint16_t )Usart1_TX_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传递给任务函数的参数 */
(UBaseType_t )Usart1_TX_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&Usart1_TX_task); /* 任务句柄 */
}
usart_drv.c#include "usart_drv.h"
UCB uart1; //串口1控制结构体
uint8_t Usart1_RxBuff[U1_RX_SIZE]; //串口1接收缓冲区
uint8_t Usart1_TxBuff[U1_TX_SIZE]; //串口1发送缓冲区
static void(*USART1_TXFun)(uint8_t *data,uint16_t data_len); //函数指针
void Usart1_TX_FunCb(void(*pFunc)(uint8_t *data,uint16_t datalen))
{
USART1_TXFun = pFunc;
}
void Usart1_Txdata(uint8_t *data,uint32_t data_len)
{
if(data_len == 0) //防止发送0个数据
{
uart1.TxState = 0;
uart1.TxCounter = 0;
return ;
}
if((U1_TX_SIZE - uart1.TxCounter) >= data_len)
{
USART1_TXFun(data,data_len);
}
}
void Uart1_DMA_ENABLE(uint8_t *data,uint32_t data_len)
{
HAL_UART_Transmit_DMA(&uart1.uart,data,data_len);
}
/*************************************************************************
* 函 数 名: UART1_Init
* 功能说明: 串口1初始化
* 形 参:无
* 返 回 值: 无
**************************************************************************/
void UART1_Init(uint32_t baudrate)
{
memset(&uart1.uart,0,sizeof(uart1.uart));
uart1.uart.Instance = USART1;
uart1.uart.Init.BaudRate = baudrate;
uart1.uart.Init.WordLength =UART_WORDLENGTH_8B;
uart1.uart.Init.StopBits=UART_STOPBITS_1;
uart1.uart.Init.Parity=UART_PARITY_NONE;
uart1.uart.Init.Mode=UART_MODE_TX_RX;
uart1.uart.Init.HwFlowCtl=UART_HWCONTROL_NONE;
HAL_UART_Init(&uart1.uart);
__HAL_UART_CLEAR_IDLEFLAG(&uart1.uart);
__HAL_UART_ENABLE_IT(&uart1.uart,UART_IT_IDLE);
HAL_UART_Receive_DMA(&uart1.uart,Usart1_RxBuff,U1_RX_MAX);
}
uint8_t tempbuff1[256]={0};
void Usart1_printf(char *fmt,...)
{
uint16_t i;
va_list ap;
va_start(ap,fmt);
vsprintf((char *)tempbuff1,fmt,ap);
va_end(ap);
for(i=0;i<strlen((char *)tempbuff1);i++)
{
while(!__HAL_UART_GET_FLAG(&uart1.uart,UART_FLAG_TXE))
{
}
uart1.uart.Instance->TDR = tempbuff1[i];
}
while(!__HAL_UART_GET_FLAG(&uart1.uart,UART_FLAG_TC))
{
}
}
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef GPIO_InitTypeDefStructur;
if(huart ->Instance == USART1)
{
__HAL_RCC_DMA2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_USART1_CLK_ENABLE();
GPIO_InitTypeDefStructur.Pin =GPIO_PIN_9;
GPIO_InitTypeDefStructur.Mode = GPIO_MODE_AF_PP;
GPIO_InitTypeDefStructur.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitTypeDefStructur.Pull=GPIO_PULLUP;
GPIO_InitTypeDefStructur.Alternate=GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA,&GPIO_InitTypeDefStructur);
GPIO_InitTypeDefStructur.Pin =GPIO_PIN_10;
GPIO_InitTypeDefStructur.Alternate=GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA,&GPIO_InitTypeDefStructur);
HAL_NVIC_SetPriority(USART1_IRQn,7,0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
//TX
uart1.dmatx.Instance = DMA2_Stream7;
uart1.dmatx.Init.Request= DMA_REQUEST_USART1_TX; /* USART1发送DMA */
uart1.dmatx.Init.Direction = DMA_MEMORY_TO_PERIPH; /* 存储器到外设 */
uart1.dmatx.Init.PeriphInc = DMA_PINC_DISABLE; /* 外设非增量模式 */
uart1.dmatx.Init.MemInc = DMA_MINC_ENABLE; /* 存储器增量模式 */
uart1.dmatx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
uart1.dmatx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
uart1.dmatx.Init.Mode = DMA_NORMAL;
uart1.dmatx.Init.Priority=DMA_PRIORITY_MEDIUM;
uart1.dmatx.Init.FIFOThreshold=DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&uart1.dmatx);
__HAL_LINKDMA(huart,hdmatx,uart1.dmatx); //连接DMA通道
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn,7,0);
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
//RX
uart1.dmarx.Instance = DMA2_Stream2; /* 数据流选择 */
uart1.dmarx.Init.Request= DMA_REQUEST_USART1_RX; /* USART1发送DMA */
uart1.dmarx.Init.Direction = DMA_PERIPH_TO_MEMORY;
uart1.dmarx.Init.PeriphInc = DMA_PINC_DISABLE;
uart1.dmarx.Init.MemInc = DMA_MINC_ENABLE;
uart1.dmarx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
uart1.dmarx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
uart1.dmarx.Init.Mode = DMA_NORMAL;
uart1.dmarx.Init.Priority=DMA_PRIORITY_MEDIUM;
uart1.dmarx.Init.FIFOThreshold=DMA_FIFOMODE_DISABLE;
__HAL_LINKDMA(huart,hdmarx,uart1.dmarx); //连接DMA通道
HAL_DMA_Init(&uart1.dmarx);
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn,7,0);
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart ->Instance == USART1)
{
uart1.TxState=0;
}
}
void Usart1_Send_Data(uint8_t *data,uint16_t datalen)
{
uint16_t i;
for(i=0;i<datalen;i++)
{
while(!__HAL_UART_GET_FLAG(&uart1.uart,UART_FLAG_TXE));
uart1.uart.Instance->TDR = data[i];
}
while(!__HAL_UART_GET_FLAG(&uart1.uart,UART_FLAG_TC));
}
static void(*USART1_RXFun)(uint8_t *data,uint16_t datalen); //函数指针
void Usart1_RX_FunCb(void(*pFunc)(uint8_t *data,uint16_t datalen))
{
USART1_RXFun = pFunc;
}
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&uart1.uart);
if(__HAL_UART_GET_FLAG(&uart1.uart,UART_FLAG_IDLE))
{
__HAL_UART_CLEAR_IDLEFLAG(&uart1.uart); //清除空闲中断标志
__HAL_DMA_DISABLE_IT(&uart1.dmarx,DMA_IT_HT);//禁止DMA传输过半中断
uart1.RxCounter = ((U1_RX_MAX) - __HAL_DMA_GET_COUNTER(&uart1.dmarx)); //计算本次的接收数据量
if(USART1_RXFun != NULL)
{
USART1_RXFun(Usart1_RxBuff,uart1.RxCounter);
}
HAL_UART_DMAStop(&uart1.uart); //停止DMA
HAL_UART_Receive_DMA(&uart1.uart,Usart1_RxBuff,U1_RX_MAX);
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart ->Instance == USART1)
{
if(__HAL_DMA_GET_FLAG(&uart1.dmarx, DMA_FLAG_TCIF2_6) == RESET)
{
__HAL_DMA_CLEAR_FLAG(&uart1.dmarx, DMA_FLAG_TCIF2_6); //清除DMA2_Steam2传输完成标志
HAL_UART_DMAStop(&uart1.uart); //停止DMA
HAL_UART_Receive_DMA(&uart1.uart,Usart1_RxBuff,U1_RX_MAX+1);
}
if(__HAL_DMA_GET_FLAG(&uart1.dmarx, DMA_FLAG_TCIF3_7) == RESET)
{
__HAL_DMA_CLEAR_FLAG(&uart1.dmarx, DMA_FLAG_TCIF3_7); //清除DMA2_Steam7传输完成标志
}
}
}
void DMA2_Stream2_IRQHandler(void)
{
HAL_DMA_IRQHandler(&uart1.dmarx);
}
void DMA2_Stream7_IRQHandler(void)
{
HAL_DMA_IRQHandler(&uart1.dmatx);
}
#if 1
#if (__ARMCC_VERSION >= 6010050) /* 使用AC6编译器时 */
__asm(".global __use_no_semihosting\n\t"); /* 声明不使用半主机模式 */
__asm(".global __ARM_use_no_argv \n\t"); /* AC6下需要声明main函数为无参数格式,否则部分例程可能出现半主机模式 */
#else
/* 使用AC5编译器时, 要在这里定义__FILE 和 不使用半主机模式 */
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
#endif
/* 不使用半主机模式,至少需要重定义_ttywrch\_sys_exit\_sys_command_string函数,以同时兼容AC6和AC5模式 */
int _ttywrch(int ch)
{
ch = ch;
return ch;
}
/* 定义_sys_exit()以避免使用半主机模式 */
void _sys_exit(int x)
{
x = x;
}
char *_sys_command_string(char *cmd, int len)
{
return NULL;
}
/* FILE 在 stdio.h里面定义. */
FILE __stdout;
/* 重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{
while ((uart1.uart.Instance->ISR & 0X40) == 0); /* 等待上一个字符发送完成 */
uart1.uart.Instance->TDR = (uint8_t)ch; /* 将要发送的字符 ch 写入到DR寄存器 */
return ch;
}
#endif
/******************************************************************************************/
usart_drv.h#ifndef __USART_DRV_H
#define __USART_DRV_H
#include "stm32h7xx_hal.h"
#include "string.h"
#include "signal.h"
#include "stdarg.h"
#include "stdio.h"
#define U1_RX_SIZE 257
#define U1_TX_SIZE 256
#define U1_RX_MAX 257
#define U1_TX_MAX 256
typedef struct{
uint8_t *start;
uint8_t *end;
}LCB;
typedef struct{
uint32_t RxCounter;
uint32_t TxCounter;
uint32_t TxState;
UART_HandleTypeDef uart;
DMA_HandleTypeDef dmatx;
DMA_HandleTypeDef dmarx;
}UCB;
void UART1_Init(uint32_t baudrate);
void Usart1_PtrInit(void);
void Usart1_Txdata(uint8_t *data,uint32_t data_len);
void Uart1_DMA_ENABLE(uint8_t *data,uint32_t data_len);
void Usart1_printf(char *fmt,...);
void Usart1_Send_Data(uint8_t *data,uint16_t datalen);
void Usart1_RX_FunCb(void(*pFunc)(uint8_t *data,uint16_t datalen));
void Usart1_TX_FunCb(void(*pFunc)(uint8_t *data,uint16_t datalen));
#endif
|
共1人点赞
|