串口配置: 異步,波特率:19200,每幀:1位元組;無校驗;1停止位

中斷設定:考慮到后期使用freertos,可控制中斷配置為:4位搶占優先級,15>=中斷優先級級>=5(越低,優先級越高)


DMA設定:以位元組為資料單位,記憶體地址累加

生成工程檔案:

在stm32f1xx_it.h 檔案添加
#define BUFF_MAX 100 #接識訓沖區大小 extern volatile uint8_t rx_len; //接收一幀資料的長度 extern volatile uint8_t recv_end_flag; //一幀資料接收完成標志 extern uint8_t rx_buffer[BUFFER_SIZE]; //接收資料快取陣列
在stm32f1xx_it.c檔案添加
volatile uint8_t rx_len ; //接收一幀資料的長度 volatile uint8_t recv_end_flag; //一幀資料接收完成標志 uint8_t rx_buffer[BUFFER_SIZE]; //接收資料快取陣列
在stm32f1xx_it.c修改中斷串口1中斷函式為
void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ uint32_t tmp_flag = 0; uint32_t temp; tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //獲取IDLE標志位 if((tmp_flag != RESET))//idle標志被置位 { __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除標志位 HAL_UART_DMAStop(&huart1); // temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 獲取DMA中未傳輸的資料個數 //temp = hdma_usart1_rx.Instance->NDTR;//讀取NDTR暫存器 獲取DMA中未傳輸的資料個數, //這句和上面那句等效 rx_len = BUFFER_SIZE - temp; //總計數減去未傳輸的資料個數,得到已經接收的資料個數 recv_end_flag = 1; // 接受完成標志位置1 } /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ /* USER CODE END USART1_IRQn 1 */ }
在main函式添加:
uint8_t Recive_buff[Buff_Max]={0};//轉存緩沖區資料,避免DMA參考的陣列被其他地方操作而發生錯誤
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx_buffer,BUFFER_SIZE);//打開DMA接收
while (1)
{
if(recv_end_flag == 1) //接收完成標志
{
memcpy(Recive_buff,rx_buffer,rx_len);
DMA_Usart_Send(Recive_buff,rx_len);
memset(rx_buffer,0,rx_len);
rx_len = 0;//清除計數
recv_end_flag = 0;//清除接收結束標志位
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重新打開DMA接收
/** HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
* 開串口hartx的DMA接收中斷,回應IDLE中斷,呼叫中斷處理函式UART1_IQRHeahler();
* *huart:呼叫串口x
* *pData:dma轉存資料地址
* BUFFER_SIZE:轉存資料地址大小,此值大于最大傳輸資料+1(停止位),同時為 *hdma_usartx_rx->Instance->CNDTR 賦初始值,即temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx)為該值(初值)-已轉移值
*/
}
HAL_Delay(10); }
void DMA_Usart_Send(uint8_t *buf,uint8_t len)//串口發送封裝 { if(HAL_UART_Transmit_DMA(&huart1, buf,len)!= HAL_OK) //判斷是否發送正常,如果出現例外則進入例外中斷函式 { Error_Handler(); } }
整體流程為:開串口及DMA中斷,等待串口接收資料 -> 有資料傳輸,DMA轉存資料,觸發IDLE中斷 -> 串口中斷處理函式,關閉DMA傳輸,回傳接收標志、資料大小 -> 主程式判斷串口接收資料標志 - > DMA傳輸資料 -> 清除緩沖區 ->開啟串口1 DMA接收中斷
搜索
復制
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/484387.html
標籤:C
