1+X 傳感網(wǎng)中級備考實例解析:異步串行通信的接收中斷(2)

  • 概要
  • RXNE中斷響應過程方法(2)

(一)概要

中斷響應過程需要實現(xiàn)的關鍵代碼是由兩部分組成:
使能中斷標志位+完善中斷服務入口函數(shù)选调,這就像一個固定的套餐組合理盆,缺一不可逝段;
在上一篇http://www.reibang.com/p/f2d4095c9def介紹RXNE的中斷響應過程膏燃,是用HAL庫函數(shù)
__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);使能中斷滥搭,配合中斷響應服務入口函數(shù)USER_UART_IRQHandler(&huart1);共同實現(xiàn)了接收到一個字符的中斷響應過程;

(二)RXNE中斷響應過程方法(2)

2.1 簡介

第二種方法判导,是我們繼續(xù)沿用HAL庫自定義的回調(diào)函數(shù)來實現(xiàn)中斷服務入口程序嫉父,依然是使能中斷 標志位+補充中斷響應服務函數(shù),方法二提供的套餐組合為HAL_UART_Receive_IT() 和HAL_UART_RxCpltCallback()
使能RXNE中斷標志位的函數(shù)聲明是:

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

中斷響應服務函數(shù)是HAL庫定義的回調(diào)函數(shù)( Callback):

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

回調(diào)函數(shù)是一種弱函數(shù)眼刃,
weak 顧名思義是“弱”的意思绕辖,如果函數(shù)名稱前面加上__weak 修飾符,我們一般稱這個函數(shù)為“弱函數(shù)”擂红。加上了__weak 修飾符的函數(shù)仪际,用戶可以在用戶文件中重新定義一個同名函數(shù)围小,最終編譯器編譯的時候,會選擇用戶定義的函數(shù)树碱,如果用戶沒重新定義這個函數(shù)肯适,那么編譯器就會執(zhí)行__weak 聲明的函數(shù),并且編譯器不會報錯成榜。
具備weak屬性的函數(shù)框舔,就像是穿了一件隱身衣,當用戶沒有在文件中定義時赎婚,它對于編譯器是不可見的隱身狀態(tài)刘绣,只有當被用戶重新定義之后,它作為中斷響應的服務函數(shù)挣输,會按照用戶定義實現(xiàn)其功能纬凤;回調(diào)函數(shù)在HAL庫中非常常見,它既可以被全局結構體變量句柄調(diào)用撩嚼,也可以成為中斷響應的服務函數(shù)停士;用戶需要清晰理解不同外設的回調(diào)函數(shù)實現(xiàn)功能,才能方便高效的應用完丽;

2.2 代碼實現(xiàn)步驟

在USART1串口控制流水燈的實驗中恋技,http://www.reibang.com/p/48817b329231,串口助手發(fā)送“mode_1#”命令字后舰涌,STM32的USART1 pRxBuffPtr連續(xù)接收到9個字符之后猖任,就會進入到中斷服務回調(diào)函數(shù); HAL_UART_RxCpltCallback(huart)瓷耙;我們在main.c中重新定義回調(diào)函數(shù)朱躺,即可實現(xiàn)同樣的效果;接下來分析中斷使能到中斷響應的全過程搁痛;
中斷使能:HAL_UART_Receive_IT
中斷響應:SART1_IRQHandler()——HAL_UART_IRQHandler—— UART_Receive_IT——當RxXferCount計數(shù)器自減到0长搀,調(diào)用回調(diào)函數(shù)HAL_UART_RxCpltCallback();

(1)使能中斷標志位
1.1 調(diào)用函數(shù)HAL_UART_Receive_IT允許RXNE標志位產(chǎn)生中斷,該函數(shù)
在mian.c主函數(shù)USART1初始化操作之后鸡典,調(diào)用此函數(shù)源请,目的是開啟RXNE標志位,因為命令字“mode_1#\r\n”是9個字符彻况,當DR數(shù)據(jù)寄存器接收到來自串口助手發(fā)送的9個字符之后谁尸,就會產(chǎn)生響應中斷服務函數(shù);

HAL_UART_Receive_IT(&huart1,uart1RxBuff,9);

從該函數(shù)定義可以得知:該函數(shù)功能是:

1.使能PE(奇偶校驗錯誤)中斷標志位纽甘,ERR(錯誤數(shù)據(jù))中斷標志位良蛮,RXNE(數(shù)據(jù)寄存器不為空)中斷標志位;
2.給串口句柄huart1的三個全局變量*pRxBuffPtr,RxXferSize和RxXferCount賦初值悍赢;

pRxBuffPtr 指向用戶自定義的接收數(shù)組的首地址决瞳;
RxXferSize; 接收數(shù)據(jù)的長度货徙;
RxXferCount:接收數(shù)據(jù)的計數(shù)器;
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  /* Check that a Rx process is not already ongoing */
  if (huart->RxState == HAL_UART_STATE_READY)
  {
    if ((pData == NULL) || (Size == 0U))
    {
      return HAL_ERROR;
    }

    /* Process Locked */
    __HAL_LOCK(huart);

    huart->pRxBuffPtr = pData;//指向用戶自定義的接收數(shù)組
    huart->RxXferSize = Size;//設定接收到的字符串個數(shù)
    huart->RxXferCount = Size;//設定計數(shù)器的初值

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    huart->RxState = HAL_UART_STATE_BUSY_RX;

    /* Process Unlocked */
    __HAL_UNLOCK(huart);

    /* Enable the UART Parity Error Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_PE);//使能PE標志位

    /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
    __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);//使能ERR標志位

    /* Enable the UART Data Register not empty Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);//使能RXNE標志位

    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

(2)中斷響應的執(zhí)行過程
2.1 中斷入口函數(shù): 在文件stm32f1xx_it.c中皮胡,找到IRQHandler函數(shù)

void USART1_IRQHandler(void)//中斷響應的入口
{
 HAL_UART_IRQHandler(&huart1);
}

2.2 執(zhí)行 HAL_UART_IRQHandler(&huart1);: 從函數(shù)定義可知痴颊,當使能RXNE標志位之后,條件語句成立屡贺,則調(diào)用UART_Receive_IT(huart);

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
  uint32_t isrflags   = READ_REG(huart->Instance->SR);
  uint32_t cr1its     = READ_REG(huart->Instance->CR1);
  uint32_t cr3its     = READ_REG(huart->Instance->CR3);
  uint32_t errorflags = 0x00U;
  uint32_t dmarequest = 0x00U;

  /* If no error occurs */
  errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
  if (errorflags == RESET)
  {
    /* UART in mode Receiver -------------------------------------------------*/
    if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
    {
      UART_Receive_IT(huart);
      return;
    }
  }
圖1HAL_UART_IRQHandler函數(shù)定義

2.3 執(zhí)行函數(shù) UART_Receive_IT(huart);蠢棱。該函數(shù)功能
1.判斷一次接收的有效數(shù)據(jù)位是8個字節(jié)還是9個字節(jié);是否必須包含奇偶校驗位甩栈;
2.從DR數(shù)據(jù)寄存器中讀取有效數(shù)據(jù)位存放到用戶自定義的數(shù)組中裳扯;
3.移動指針pRxBuffPtr;
4判斷uarRxXferCount計數(shù)器自減為0之后谤职,就調(diào)用回調(diào)函數(shù) HAL_UART_RxCpltCallback(huart);
5.條件成立,函數(shù)返回HAL_OK亿鲜;
函數(shù) UART_Receive_IT()的作用是把每次中斷接收到的字符保存在串口句柄的緩存指針 pRxBuffPtr 中允蜈,同時每次接收一個字符,其計數(shù)器 RxXferCount 減 1蒿柳,直到接收完成 RxXferSize 個字符之后 RxXferCount 設置為0饶套,同時調(diào)用接收完成回調(diào)函數(shù) HAL_UART_RxCpltCallback 進行處理;

2.4 用戶在main.c中重寫回調(diào)函數(shù)HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)垒探,在回調(diào)函數(shù)中只需要判斷是否USART1的產(chǎn)生的中斷妓蛮,用戶自定義的全局變量 uart1RxState賦值1,則說明數(shù)據(jù)已經(jīng)接收圾叼;此外蛤克,因為上一步在調(diào)用回調(diào)函數(shù)之前,已經(jīng)關閉了中斷__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE)夷蚊;所以需要重新開啟中斷构挤,調(diào)用函數(shù)HAL_UART_Receive_IT(&huart1,uart1RxBuff,9);

 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//當RXcounter自減到0 惕鼓,才進入回調(diào)函數(shù)
 { 
     if(huart->Instance==USART1)
     {
       uart1RxState =1; 
     }
    
    HAL_UART_Receive_IT(&huart1,uart1RxBuff,9);//重新開啟中斷

 }   

總結:

串口中斷是我們總結了第二種方法筋现。與第一種方法不同,我們采用了HAL自定義的中斷服務函數(shù)箱歧,且通過重新定義回調(diào)函數(shù)的方法矾飞。實現(xiàn)了與方法一相同的功能;無論是采取之前庫函數(shù)的思想呀邢,重寫中斷服務響應函數(shù)洒沦;還是采取HAL的邏輯,運用HAL幫我們自定義好的函數(shù)驼鹅;我們都需要充分理解中斷執(zhí)行過程微谓;通過單步運行反復調(diào)試代碼森篷,閱讀參考手冊和英文文檔注釋,幫助我們更好的理解串口異步通信豺型;

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仲智,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子姻氨,更是在濱河造成了極大的恐慌钓辆,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肴焊,死亡現(xiàn)場離奇詭異前联,居然都是意外死亡,警方通過查閱死者的電腦和手機娶眷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門似嗤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人届宠,你說我怎么就攤上這事烁落。” “怎么了豌注?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵伤塌,是天一觀的道長。 經(jīng)常有香客問我轧铁,道長每聪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任齿风,我火速辦了婚禮药薯,結果婚禮上,老公的妹妹穿的比我還像新娘救斑。我一直安慰自己果善,他們只是感情好,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布系谐。 她就那樣靜靜地躺著巾陕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪纪他。 梳的紋絲不亂的頭發(fā)上鄙煤,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音茶袒,去河邊找鬼梯刚。 笑死,一個胖子當著我的面吹牛薪寓,可吹牛的內(nèi)容都是我干的亡资。 我是一名探鬼主播澜共,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼锥腻!你這毒婦竟也來了嗦董?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤瘦黑,失蹤者是張志新(化名)和其女友劉穎京革,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體幸斥,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡匹摇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了甲葬。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片廊勃。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖经窖,靈堂內(nèi)的尸體忽然破棺而出供搀,到底是詐尸還是另有隱情,我是刑警寧澤钠至,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站胎源,受9級特大地震影響棉钧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜涕蚤,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一宪卿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧万栅,春花似錦佑钾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扰她,卻和暖如春兽掰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背徒役。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工孽尽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人忧勿。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓杉女,卻偏偏與公主長得像瞻讽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子熏挎,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容