0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學(xué)習在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區
會(huì )員中心
創(chuàng )作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內不再提示

STM32 HAL庫串口收發(fā)如何使用

科技綠洲 ? 來(lái)源:矜辰所致 ? 作者:矜辰所致 ? 2023-06-22 10:38 ? 次閱讀
  • 前言
  • 一、 HAL 庫串口收發(fā)
    • 1.1 串口發(fā)送
    • 1.2 串口接收
  • 二、 收發(fā)同時(shí)串口卡死?
    • 2.1 問(wèn)題說(shuō)明
    • 2.2 嘗試的處理方式
  • 結語(yǔ)

前言

對于 STM32 串口的使用,確實(shí)很簡(jiǎn)單使用 STM32CubeMX 做好初始化,就可以直接使用了。

但是最近在某些產(chǎn)品上使用串口同時(shí)收發(fā)的時(shí)候,發(fā)現有時(shí)候串口會(huì )收不到數據了,但是發(fā)送正常,而且這個(gè)問(wèn)題再數據量大的時(shí)候很容易出現,于是乎進(jìn)行了好幾天的問(wèn)題測試……

一、 HAL 庫串口收發(fā)

先簡(jiǎn)單回顧一下 STM32 HAL庫串口收發(fā)是如何使用的。

1.1 串口發(fā)送

對于 STM32 來(lái)說(shuō),串口發(fā)送有3中方式:

  1. 輪詢(xún)發(fā)送;
  2. 中斷發(fā)送;
  3. DMA發(fā)送;

在實(shí)際產(chǎn)品上,大部分項目中都用的是 輪詢(xún) 方式發(fā)送,本次出現接收卡死的問(wèn)題的產(chǎn)品也是采用的輪詢(xún)發(fā)送,所以我簡(jiǎn)單的說(shuō)明一下輪詢(xún)發(fā)送,其他兩種方式為 STM32 學(xué)習的基礎問(wèn)題,這里就不過(guò)多討論。

發(fā)送相對簡(jiǎn)單,在 HAL 庫實(shí)際都是使用HAL_UART_Transmit函數:

圖片

在這里插入圖片描述

不管是哪個(gè)串口發(fā)送,都做了個(gè)簡(jiǎn)單的發(fā)送函數:

圖片

在這里插入圖片描述

發(fā)送沒(méi)什么好說(shuō)的,簡(jiǎn)單易用。

1.2 串口接收

和串口發(fā)送一樣,串口接收有3中方式:

  1. 輪詢(xún)接收;
  2. 中斷接收;
  3. DMA接收;

在我們正常的項目使用中,一般都是 中斷接收 或者 DMA 接收,基本上不會(huì )使用 輪詢(xún)接收的方式。

那么對于本次出問(wèn)題的產(chǎn)品,我采用的是 中斷接收的方式。

但是相比較發(fā)送,在 HAL 庫中 使用中斷接收的方式就有點(diǎn) “五花八門(mén)” 的感覺(jué)。

1.2.1 標準庫接收

在標準庫的時(shí)候,我們經(jīng)常這么用,在串口初始化的時(shí)候使用下面的語(yǔ)句使能中斷:

//在串口初始化代碼之后加上中斷使能
USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);

如果需要自動(dòng)判斷一幀數據,我們再開(kāi)啟一下 IDLE 中斷:

USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);

然后在對應的中斷處理函數中,直接讀取 DR 寄存器(STM32F103 而言為 DR,STM32L051 為RDR),然后當 IDLE 中斷產(chǎn)生,也可以處理一下標志位:

//自己用的,用到了 USART_IT_IDLE 標志位,有時(shí)候不合適
void USART3_IRQHandler(void)                 //串口3中斷服務(wù)程序
{
 u8 clear3=clear3;    //消除編譯器沒(méi)有用到的提醒
 // u8  Res;

 if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  
  {
   USART_Enocean_BUF[Enocean_Data++] = USART3- >DR;
   USART3_RX_BUF[USART3_Data++] = USART_ReceiveData(USART3);
   // Res= USART_ReceiveData(USART3);
   // USART_SendData(USART1,Res);while(!(USART1- >SR&USART_FLAG_TXE)); 
  }

    else if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)    
    {
   clear3=USART3- >SR; //讀SR寄存器 可以清空寄存器
   clear3=USART3- >DR; //讀DR寄存器(先讀SR寄存器,再讀DR,為了清除IDLE中斷)      
   USART3_RX_STA=1;   //標記接收到了一幀數據
   //USART3_Data=0;
    }               //enocean是不是讀不到一幀數據,不用一幀數據測試一下  
}

1.2.1 HAL庫接收

HAL庫接收方式一

在 HAL 庫函數接收的時(shí)候,其實(shí)也可以使用標準庫上一樣的中斷標志使能:

MX_LPUART1_UART_Init();
__HAL_UART_ENABLE_IT(&hlpuart1,UART_IT_RXNE);

IDLE 中斷使能:

__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);

這種方式的處理方式,可以和標準庫差不多。

在 HAL 庫中,外設的中斷的入口函數都放在stm32l0xx_it.c 這個(gè)文件夾中( 以STM32L051 為例),在這個(gè)文件中可以找到和標準庫一樣的 中斷入口函數,我們可以進(jìn)行如下處理:

void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */
  if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE) == SET){
      //  USART_Enocean_BUF[Enocean_Data++] = huart2.Instance- >RDR    
      //  RXNE 數據處理,直接讀取數據      
  }
  if((__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE) != RESET))
  {
     __HAL_UART_CLEAR_IT(&huart2,UART_CLEAR_IDLEF); //??3y?D??  
     // ReceiveState = 1;
     // IDLE 數據處理,一幀數據接收標志位置位
  }
}
HAL庫接收方式二

但是在于 HAL 中,還有一種比較常用的開(kāi)啟中斷方法,不是直接使能中斷,而是通過(guò)調用 HAL 庫函數 HAL_UART_Receive_IT

圖片

在這里插入圖片描述

一般的使用方式步驟:

圖片

在這里插入圖片描述

對于本次需要說(shuō)明的問(wèn)題,就是使用了 HAL_UART_Receive_IT 函數導致的,下文我們會(huì )說(shuō)明,這里列出了基本的使用步驟。

二、 收發(fā)同時(shí)串口卡死?

2.1 問(wèn)題說(shuō)明

最近測試部反饋,產(chǎn)品有些時(shí)候的下行沒(méi)反應,這里所說(shuō)的下行,其實(shí)就是串口接收。

霹靂扒拉一大堆多余的省略 ... ... 只說(shuō)幾個(gè)重點(diǎn):

出問(wèn)題的最后現象就是串口發(fā)送正常,但是永遠接收不到數據了,其他程序正常運行。

出問(wèn)題只存在于串口又有接收,又有發(fā)送的產(chǎn)品上。

產(chǎn)品發(fā)送一般是周期性的,但是接收是隨機的,無(wú)線(xiàn)信號串口接收,所以產(chǎn)品的出問(wèn)題的情況也是隨機的,但是數據量大起來(lái)肯定就會(huì )出現永遠接收不到的問(wèn)題。

2.2 嘗試的處理方式

因為所有的一些都是按照正常流程設計的,按理來(lái)說(shuō)實(shí)在是不知道為什么會(huì )這樣,所以網(wǎng)上查詢(xún)測試了好久,現在我把嘗試的處理方式以及步驟記錄說(shuō)明一下:

2.2.1 清除錯誤標志位

在使用 HAL 庫的時(shí)候,有4個(gè)錯誤 flag,如下圖:

圖片

在這里插入圖片描述

期初還以為是某些異常錯誤導致的,經(jīng)過(guò)網(wǎng)上的的一些查詢(xún),剛開(kāi)始是添加了清除錯誤標志位:

__HAL_UART_CLEAR_FLAG(&hlpuart1, UART_FLAG_PE);//清標志
 __HAL_UART_CLEAR_FLAG(&hlpuart1, UART_FLAG_FE);
 __HAL_UART_CLEAR_FLAG(&hlpuart1, UART_FLAG_NE);
 __HAL_UART_CLEAR_FLAG(&hlpuart1, UART_FLAG_ORE);

在需要的地方加上錯誤標志位清除,我是在清除串口緩存中處理的:

圖片

在這里插入圖片描述

2.2.2 串口溢出錯誤

其實(shí)串口溢出錯誤在上面的已經(jīng)清除過(guò)標志位,因為這個(gè)問(wèn)題著(zhù)實(shí)搞得我頭有點(diǎn)大,所以看到網(wǎng)上前人的處理方式和上面直接清除不一樣,還是試了一把。

這里簡(jiǎn)單說(shuō)明一下,我還特意去看了下自己的 CubeMX 設置,在設置的時(shí)候 有一個(gè) Overrun 錯誤標志位,平時(shí)我們設置都不一定往下拉著(zhù)看 = =?。?/p>

圖片

在這里插入圖片描述

然后確定了開(kāi)啟了串口溢出錯誤檢測以后,我根據網(wǎng)上的方式,加了一個(gè)HAL_UART_ErrorCallback函數,其實(shí)就類(lèi)似于HAL_UART_RxCpltCallback 函數:

圖片

在這里插入圖片描述

自己加了一個(gè) 出錯處理函數,其實(shí)現在看來(lái),當然也是沒(méi)有用的。

2.2.3 HAL庫的半雙工處理?

折騰了好長(cháng)一段時(shí)間,其實(shí)一開(kāi)始就知道問(wèn)題在于 同時(shí)收發(fā)會(huì )出問(wèn)題的情況,那么繼續上網(wǎng)找問(wèn)題。

最終確定了一個(gè)問(wèn)題就是:

我們都知道 STM32 串口是全雙工的, STM32 HAL庫在處理接收的時(shí)候會(huì )鎖一下串口一會(huì ),導致變成某個(gè)短時(shí)間的“半雙工”。

這個(gè)時(shí)候如果同時(shí)收發(fā)就會(huì )出現問(wèn)題,最后解決的辦法在這篇文章中看到了:STM32 F103串口同時(shí)收發(fā)出現死鎖問(wèn)題解決辦法

問(wèn)題在于我們使用的HAL_UART_Receive_IT函數中,有對串口加鎖的操作:

圖片雖然在后面有解鎖:

圖片

在這里插入圖片描述

但是根據后期的解決方式來(lái)說(shuō),確實(shí)就是這個(gè)HAL_UART_Receive_IT函數的問(wèn)題,最后使用的方式為,在產(chǎn)生一次中斷以后開(kāi)啟的時(shí)候手動(dòng)解鎖:

圖片

在這里插入圖片描述

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if(huart- >Instance == LPUART1){
    Enocean_Data++;
    if(Enocean_Data > 98)Enocean_Data = 0;
    while(HAL_UART_Receive_IT(&hlpuart1, (uint8_t *)&USART_Enocean_BUF[Enocean_Data], 1) != HAL_OK){
      hlpuart1.RxState = HAL_UART_STATE_READY;
      __HAL_UNLOCK(&hlpuart1);
    }
  }
  else if(huart- >Instance==USART1)
  {  
  }
}

終于,串口不再卡死 , 成功!

結語(yǔ)

沒(méi)想到和 EEPROM 一樣,一個(gè)簡(jiǎn)單的芯片,一個(gè)熟悉的串口 ,出了這種問(wèn)題 = =!還好最后解決了問(wèn)題。

踩過(guò)的坑都是積累與經(jīng)驗,加油。

聲明:本文內容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權轉載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習之用,如有內容侵權或者其他違規問(wèn)題,請聯(lián)系本站處理。 舉報投訴
  • STM32
    +關(guān)注

    關(guān)注

    2247

    文章

    10693

    瀏覽量

    349920
  • 串口
    +關(guān)注

    關(guān)注

    14

    文章

    1505

    瀏覽量

    74760
  • HAL
    HAL
    +關(guān)注

    關(guān)注

    2

    文章

    69

    瀏覽量

    12492
收藏 人收藏

    評論

    相關(guān)推薦

    淺析STM32HAL串口處理

    STM32HAL串口處理—中斷收發(fā)文章目錄STM32HAL
    發(fā)表于 08-16 06:28

    STM32 HAL串口收發(fā)崩潰的原因

    的校驗碼后字節添加1-8字節隨機數,每種字節長(cháng)度測試10000次。以上測試初串口就會(huì )崩潰,只能發(fā)不能收,調試結果是,串口接收中斷不再響應。源碼中使用HAL_UART_Receive_I...
    發(fā)表于 08-23 08:58

    萌新求助,求STM32HAL中斷模式串口初始化收發(fā)數據的程序

    萌新求助,求STM32HAL中斷模式串口初始化收發(fā)數據的程序
    發(fā)表于 11-16 09:22

    如何解決STM32F4 HAL串口同時(shí)收發(fā)代碼卡死問(wèn)題?

    如何解決STM32F4 HAL串口同時(shí)收發(fā)代碼卡死問(wèn)題?
    發(fā)表于 11-25 08:58

    請問(wèn)STM32CubeIDE如何利用自帶HAL進(jìn)行串口收發(fā)?

    請問(wèn)STM32CubeIDE如何利用自帶HAL進(jìn)行串口收發(fā)?
    發(fā)表于 11-25 07:59

    求大佬分享STM32CubeIDE+HAL+USART+串口收發(fā)的學(xué)習筆記

    求大佬分享STM32CubeIDE+HAL+USART+串口收發(fā)的學(xué)習筆記
    發(fā)表于 12-06 07:55

    分享一個(gè)不錯的stm32使用hal串口收發(fā)送測試

    分享一個(gè)不錯的stm32使用hal串口收發(fā)送測試
    發(fā)表于 12-09 07:59

    如何對STM32F407 HAL串口數據進(jìn)行收發(fā)(輪詢(xún))初始化

    如何對STM32F407 HAL串口數據進(jìn)行收發(fā)(輪詢(xún))初始化?有哪些步驟?
    發(fā)表于 12-09 07:28

    調試HAL中的串口收發(fā)出現無(wú)法break是為什么?

    調試HAL中的串口收發(fā)出現無(wú)法break是為什么?STM32F103庫函數的main函數連續執行任務(wù)怎么辦?
    發(fā)表于 12-14 06:11

    如何解決STM32F103系列HALDMA串口收發(fā)頻繁出現幀錯誤的問(wèn)題?

    如何解決STM32F103系列HALDMA串口收發(fā)頻繁出現幀錯誤的問(wèn)題?
    發(fā)表于 12-14 07:48

    HAL串口數據收發(fā)

    HAL串口數據收發(fā)前言使用cubeMX創(chuàng )建工程文件時(shí),默認使用HAL。作為最新的主流
    發(fā)表于 02-16 06:50

    CubeMX STM32 HAL串口收發(fā)怎么打開(kāi)

    問(wèn)題:在大數據量頻繁收發(fā)時(shí)出現串口接收失效。分析:HAL串口中斷進(jìn)行了封裝,留給用戶(hù)的接口只有一個(gè)回調函數void
    發(fā)表于 02-28 14:13

    STM32L031 HAL 串口收發(fā)例程(中斷配合輪詢(xún))

    STM32L031 HAL 串口收發(fā)例程(中斷配合輪詢(xún))代碼環(huán)境開(kāi)發(fā)工具:STM32CUBEIDE芯片:
    發(fā)表于 11-05 19:35 ?19次下載
    <b class='flag-5'>STM32</b>L031 <b class='flag-5'>HAL</b> <b class='flag-5'>串口</b><b class='flag-5'>收發(fā)</b>例程(中斷配合輪詢(xún))

    STM32 HAL串口收發(fā)是如何使用的?

    STM32 HAL串口收發(fā)是如何使用的? STM32是一款高性能的微控制器,它擁有廣泛的應用領(lǐng)域,其中包括了各種通訊應用,如UART
    的頭像 發(fā)表于 10-26 17:42 ?865次閱讀

    STM32 HAL串口同時(shí)收發(fā),接收卡死?

    STM32 HAL串口同時(shí)收發(fā),接收卡死? 為什么STM32 HAL
    的頭像 發(fā)表于 10-26 17:42 ?2703次閱讀
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看