一、收发主要逻辑
1、接收:利用DMA和空闲中断一次接收一帧的不定长数据,接收到数据后“暂停”(之后分析为何要暂停而不是停止)DMA,快速利用结构体存储接收到数据的地址和长度,再利用队列能够传递结构体的特点,将所收数据的地址和长度入队,然后打开DMA接收。数据处理任务检测队列状态,只要队列中有有效数据就开始数据处理。
2.发送:先将要发送的数据存入循环数组(伪)中,再利用队列将数据的地址和长度入队,利用一个串口输出的守护任务来保证数据传输的完整性,这个守护任务对地址和长度出队并使用DMA传输。
二、接收代码
接收和发送结构体
typedef struct
{
uint8_t lenth;
uint8_t offset_last;
}Usart3RXTempTypedef;
typedef struct
{
uint8_t lenth;
uint8_t offset_last;
uint8_t *addr;
}Usart3TxTypedef;
1.中断
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
uint32_t tmp_flag = 0;
uint16_t temp;
portBASE_TYPE xHigherPriorityTaskWoken= pdFALSE;
tmp_flag =__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE);
if((tmp_flag != RESET))
{
__HAL_UART_CLEAR_IDLEFLAG(&huart3);
temp = huart3.Instance->SR;
temp = huart3.Instance->DR;
HAL_UART_DMAPause(&huart3);
temp = hdma_usart3_rx.Instance->CNDTR;
if(temp >= (USART3_RxBuffer_Size - Usart3Temp.offset_last))//判断是否到达循环数组终点
Usart3Temp.lenth = 2*USART3_RxBuffer_Size - temp - Usart3Temp.offset_last;
else
Usart3Temp.lenth = USART3_RxBuffer_Size - temp - Usart3Temp.offset_last;
Usart3Temp.offset_last = USART3_RxBuffer_Size - temp;
xQueueSendFromISR(QueueUsart3RevHandle,(void *)&Usart3Temp,&xHigherPriorityTaskWoken);
HAL_UART_DMAResume(&huart3);
}
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3);
/* USER CODE BEGIN USART3_IRQn 1 */
/* USER CODE END USART3_IRQn 1 */
}
这里DMA操作要使用HAL_UART_DMAPause
DMA暂停和HAL_UART_DMAResume
DMA恢复。
如果使用HAL_UART_DMAStop
DMA停止和HAL_UART_Receive_DMA
DMA接收启用,会导致DMA一直从循环数组的开头存放数据。
这里Usart3Temp.offset_last
是本次数据的尾地址偏移量。
当然,DMA参数配置中要把模式设置为循环模式。
2.接收数据任务:数据处理方式为收到数据后原样返回
void usart3RxTask(void const * argument)
{
/* USER CODE BEGIN usart3RxTask */
/* Infinite loop */
for(;;)
{
uint16_t i;
uint8_t RevCnt;
Usart3RxTypedef Usart3TempRev;
Usart3TxTypedef Usart3Tx;
/* Infinite loop */
for(;;)
{
xQueueReceive(QueueUsart3RevHandle,(void*)&Usart3TempRev,portMAX_DELAY);
if(Usart3TempRev.offset_last>=Usart3TempRev.lenth)
{
RevCnt=0;
for(i=(Usart3TempRev.offset_last-Usart3TempRev.lenth);i USART3_TxBuffer_Size)//如果溢出,则从数组的第一个地�?�?始储�?
Usart3Tx.offset_last = 0;
for(i=0;i