日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

串口IDLE空闲中断+DMA实现接收不定长数据基于stm32cubemx

發布時間:2025/3/21 编程问答 71 豆豆
生活随笔 收集整理的這篇文章主要介紹了 串口IDLE空闲中断+DMA实现接收不定长数据基于stm32cubemx 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言:對于串口接收一些不定長的數據,必須面對一個問題:怎么判斷一幀數據接收是否完成?通常使用RXNE非空中斷配合簡單的數據協議,在數據中加入幀頭、幀尾,在程序中判斷是否接收到幀尾來確定數據接收完畢,因此對每個字節都要觸發中斷進行判斷,比較消耗系統資源,尤其是在一些實時性要求較高的場合,而串口空閑中斷可以大大簡化數據接收過程的判斷。本文章介紹基于stm32cubemx使用DMA+IDLE串口空閑中斷實現接收不定長數據。

STM32的IDLE空閑中斷產生機制

IDLE空閑中斷是在監測到數據接收后(即串口的RXNE位被置位)開始檢測,當總線上在一個字節對應的周期內未再有新的數據接收時,控制觸發空閑中斷的IDLE位被硬件置1 便會激發一個空閑中斷,在中斷處理函數中,我們可以解析接收到的不定長數據。

?使用工具

軟件:stm32cubemx ,keil uVision5,串口收發軟件(vofa+,

硬件:stm32f103rct6,ST-link下載器,數據線.

STM32CUBEMX初始化配置

打開stm32cubemx,點擊紅色方框處,開始新建工程

查找芯片型號,選擇對應芯片型號處雙擊

sys進行如下配置,便于進行st-link下載

設置rcc,選擇高速時鐘(HSE)為外部晶振

配置時鐘樹,本文使用的是f103系列,HCLK最大為72MHz

配置串口:

1.設置MODE為異步通信(Asynchronous)

2.使用默認配置(波特率為115200 Bits/s,傳輸數據長度為8 Bit,奇偶檢驗無,停止位為1 Bit 接收和發送都使能)

3.使能串口中斷

?

設置DMA:

  • 點擊add,添加通道
  • 通道配置均為默認(modenormal,內存地址每次遞增1個byte)
  • 工程命名,選擇保存位置,選擇使用的編譯器及版本

    ?

    如下配置,點擊GENERATE CODE生成代碼

    代碼編寫

    注釋部分為使用雙緩沖區接收數據,可有效防止接收中斷間隔時間非常短(即發送數據幀的速率很快),MCU來不及處理此次接收到的數據,又產生中斷,導致數據會被覆蓋的情況

    main.h中添加

    #define BUFFER_SIZE 100 void USAR_UART_IDLECallback(UART_HandleTypeDef *huart,uint8_t rxlen );

    main.c

    /* USER CODE BEGIN PV */ uint8_t rxbuffer1[BUFFER_SIZE]={0}; //接收數據緩存數組1 //uint8_t rxbuffer2[BUFFER_SIZE]={0}; //接收數據緩存數組2 //uint8_t flag=0;雙緩沖區切換標志 /* USER CODE END PV */

    ?main函數中注意確保DMA初始化函數放在串口初始化之前,

    并在串口初始化之后使能IDLE中斷、開啟串口DMA接收

    /* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();//放在串口初始化之前MX_USART1_UART_Init();/* USER CODE BEGIN 2 */__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能IDLE中斷HAL_UART_Receive_DMA(&huart1,rxbuffer1,BUFFER_SIZE);//開啟串口DMA接收/* USER CODE END 2 */

    在/* USER CODE BEGIN 4 */下添加用戶自定義IDLE空閑中斷回調函數(注釋部分為雙緩沖接收)

    void USAR_UART_IDLECallback(UART_HandleTypeDef *huart,uint8_t rxlen ){if(huart == &huart1) //判斷是否為串口1產生中斷{/* switch(flag){case 0: flag=1;memset(rxbuffer2,0,BUFFER_SIZE);//清空接收緩存,調用需包含string.h,本例程刪去也基本無影響HAL_UART_Receive_DMA(&huart1,rxbuffer2,BUFFER_SIZE);//重新打開DMA接收HAL_UART_Transmit_DMA(&huart1, rxbuffer1,rxlen);//將接收到的不定長數據發送到上位機 rxlen = 0;//清除數據長度計數break;case 1:flag=0;memset(rxbuffer1,0,BUFFER_SIZE);//清空接收緩存,調用需包含string.h,本例程刪去也基本無影響HAL_UART_Receive_DMA(&huart1,rxbuffer1,BUFFER_SIZE);//重新打開DMA接收HAL_UART_Transmit_DMA(&huart1, rxbuffer2,rxlen);//將接收到的不定長數據發送到上位機 rxlen = 0;//清除數據長度計數break;}*/HAL_UART_Transmit_DMA(&huart1, rxbuffer1,rxlen);//將接收到的不定長數據發送到上位機rxlen = 0;//清除數據長度計數HAL_UART_Receive_DMA(&huart1,rxbuffer1,BUFFER_SIZE);//重新打開DMA接收}}

    由于hal庫中沒有定義IDLE空閑中斷的中斷處理函數,需要用戶自行定義

    打開stm32f1xx_it.c,找到void USART1_IRQHandler(void)函數,并添加如下代碼:

    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 */uint8_t rxlen ; //接收一幀數據的長度if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) //判斷idle標志被置位{ __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除標志位HAL_UART_DMAStop(&huart1); // 停止DMA傳輸rxlen = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); //總計數減去未傳輸的數據個數,得到已經接收的數據個數USAR_UART_IDLECallback(&huart1,rxlen); // 調用用戶定義空閑中斷回調函數}/* USER CODE END USART1_IRQn 1 */ }

    下載程序測試

    藍色為上位機發送數據,綠色為上位機接收數據

    測試正常

    總結

    以上是生活随笔為你收集整理的串口IDLE空闲中断+DMA实现接收不定长数据基于stm32cubemx的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。