STM32F407串口空閑中斷+DMA 接收,應用于大疆DT7無線遙控
#stm32CubeIDE STM32F4 HAL庫 大疆DT7 串口+DMA ()
1.硬體設計
首先了解大疆接收器發送串口資料的信號型別
如圖可知,需要做一個取反電路…如下圖:

圖片取自網上.這些在網上都可以搜到. 記住要有上拉電阻,如果外部沒有,可使用單片機USART的RX的GPIO配置為上拉
遙控接收后會發送,相當于外部串口的TX,與單片機的RX連接.
接下來就是軟體部分,我使用的是STM32CubeIDE,先配置環境
1.配置RCC時鐘,這個就不多說了,不會的話評論區和我說
2.
配置串口資料
配置串口DMA接收

GPIO模式配置
最后,使能串口接收中斷

我使用了10ms定時器中斷 在定時器中來處理資料,不在中斷中處理.中斷僅用來接收資料.定時器配置我也不多說了

補充一張圖,.
下面上代碼
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); //使能串口空閑中斷
HAL_UART_Receive_DMA(&huart1, receive_buff,18);//開啟串口DMA接收
HAL_TIM_Base_Start_IT(&htim2);//開啟1定時器中斷
/* USER CODE END 2 */
uint8_t receive_buff[18];這是定義的接收陣列
receive_buff為接收陣列,接收到的資料放在這里,18代表一次接收18位元組.
接下來找到stm32f4xx_it.c檔案
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1); //這個可有可無
/* USER CODE BEGIN USART1_IRQn 1 */
if(USART1==huart1.Instance) //判斷是否為串口1的中斷
{
if( __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)!=RESET ) /判斷是否為空閑中斷
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1); // 如果是空閑中斷清除空閑中斷標志
HAL_UART_DMAStop(&huart1); // 關閉串口的DMA接收
DMA2_Stream2->NDTR=(uint16_t)(RC_FRAME_LENGTH); // 這個參考的大疆DT7歷程,重置DMA存盤指標到起始位置
HAL_UART_Receive_DMA(&huart1, (uint8_t*) receive_buff, 18); //再開啟接收
HAL_Delay(25); //為什么加延時呢,見后面
if(__HAL_DMA_GET_COUNTER(&hdma_usart1_rx)==0&&receive_buff[17]==4) // 見后面
{
memcpy(data_Handle, receive_buff, 18); //復制到其他陣列方便處理
}
}
}
/* USER CODE END USART1_IRQn 1 */
}
/**
講解一下, __HAL_DMA_GET_COUNTER(&hdma_usart1_rx)這句話的意思是當前DMA流傳輸中剩余資料單元的數量,也就是說開啟接收后,需要等接收完成才可以去處理資料,即__HAL_DMA_GET_COUNTER(&hdma_usart1_rx)這個等于零,代表18個位元組都接收完成.
可以看一下HAL庫中這個宏定義 #define __HAL_DMA_GET_COUNTER(HANDLE) ((HANDLE)->Instance->NDTR)
再看一下ST檔案NDTR暫存器含義

所以我在HAL_UART_Receive_DMA(&huart1, (uint8_t*) receive_buff, 18); 開啟接收后需要等待20m’接收完成才可以進行這個判斷,否則在除錯時設定斷點會不進入這個if.因為還有剩余,就不會等于0.
關于&&receive_buff[17]==4,是應為我根接收資料的特點,自己增加的一個判斷條件,提高資料正確性.
說白了這句話就是一個接收資料的長度校驗 又加上了一個我自己找的資料的一個特點,才能保證資料的正確性,當發生資料亂的狀況會過濾掉
if(__HAL_DMA_GET_COUNTER(&hdma_usart1_rx)==0&&receive_buff[17]==4)
好的,就這么多了,第一次寫文章,歡迎廣大網友批評指責,看看這個還有什么可提升的地方,互相學習,加油!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/264563.html
標籤:其他
