一、中斷模式
1.中斷接收。
1.1先看中斷接收的流程(以 USART2 為例)
在啟動(dòng)文件中找到中斷向量
USART2_IRQHandler
找到USART2_IRQHandler的函數(shù)定義
可以看到這里又轉(zhuǎn)到另一個(gè)函數(shù)里去了,再找下去:
該函數(shù)的源碼:
/**
* @brief This function handles UART interrupt request.
* @param huart: pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
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;
}
}
/* If some errors occur */
if((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
{
/* UART parity error interrupt occurred ----------------------------------*/
if(((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_PE;
}
/* UART noise error interrupt occurred -----------------------------------*/
if(((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_NE;
}
/* UART frame error interrupt occurred -----------------------------------*/
if(((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_FE;
}
/* UART Over-Run interrupt occurred --------------------------------------*/
if(((isrflags & USART_SR_ORE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_ORE;
}
/* Call UART Error Call back function if need be --------------------------*/
if(huart->ErrorCode != HAL_UART_ERROR_NONE)
{
/* UART in mode Receiver -----------------------------------------------*/
if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
}
/* If Overrun error occurs, or if any error occurs in DMA mode reception,
consider error as blocking */
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
if(((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest)
{
/* Blocking error : transfer is aborted
Set the UART state ready to be able to start again the process,
Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
UART_EndRxTransfer(huart);
/* Disable the UART DMA Rx request if enabled */
if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
{
CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
/* Abort the UART DMA Rx channel */
if(huart->hdmarx != NULL)
{
/* Set the UART DMA Abort callback :
will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;
if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
{
/* Call Directly XferAbortCallback function in case of error */
huart->hdmarx->XferAbortCallback(huart->hdmarx);
}
}
else
{
/* Call user error callback */
HAL_UART_ErrorCallback(huart);
}
}
else
{
/* Call user error callback */
HAL_UART_ErrorCallback(huart);
}
}
else
{
/* Non Blocking error : transfer could go on.
Error is notified to user through user error callback */
HAL_UART_ErrorCallback(huart);
huart->ErrorCode = HAL_UART_ERROR_NONE;
}
}
return;
} /* End if some error occurs */
/* UART in mode Transmitter ------------------------------------------------*/
if(((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
{
UART_Transmit_IT(huart);
return;
}
/* UART in mode Transmitter end --------------------------------------------*/
if(((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
{
UART_EndTransmit_IT(huart);
return;
}
}
也就是說(shuō),當(dāng)串口中斷觸發(fā)以后,幾經(jīng)周轉(zhuǎn)到了這里,該函數(shù)功能是讀取寄存器的幾個(gè)狀態(tài),判斷無(wú)誤后再轉(zhuǎn)到另一個(gè)函數(shù),就是上圖小矩形框出來(lái)的UART_Receive_IT(huart);
然后我們?cè)偃タ碪ART_Receive_IT(huart)這個(gè)函數(shù)原型:
回調(diào)函數(shù)就在這個(gè)UART_Receive_IT(huart)函數(shù)里:
在回調(diào)函數(shù)上邊有兩行很重要的代碼:
這兩行代碼的作用是關(guān)閉串口接收中斷,也就是說(shuō),在一次串口中斷接收過(guò)程的最后,即串口接收完一組數(shù)據(jù)之后會(huì)關(guān)閉串口接收中斷。(這個(gè)后面還會(huì)再講,先記?。?/p>
總結(jié)一下,串口中斷接收的流程:
USART2_IRQHandler(void) -> HAL_UART_IRQHandler(UART_HandleTypeDef *huart) -> UART_Receive_IT(UART_HandleTypeDef *huart) -> HAL_UART_RxCpltCallback(huart);
Callback函數(shù)就是用戶要重寫在main.c里的回調(diào)函數(shù)。
再說(shuō)明一下一個(gè)很重要的問(wèn)題:STM32的每個(gè)串口中斷有好幾個(gè)(發(fā)送接收等),但是只要是與串口相關(guān)的中斷發(fā)生系統(tǒng)都會(huì)先調(diào)用同一個(gè)函數(shù),也就是中斷向量表中的那個(gè),比如usart2的話就是USART2_IRQHandler(void),然后這個(gè)函數(shù)再調(diào)用HAL_UART_IRQHandler,在HAL_UART_IRQHandler中去讀取寄存器判斷究竟是那幾個(gè)位被置為1,確定好是哪個(gè)中斷之后(接收還是發(fā)送)再調(diào)用不同的回調(diào)函數(shù)。
1.2如何使用接收中斷。
在cube中配置完了之后并沒(méi)有使能串口中斷(有一個(gè)串口初始化函數(shù),但是在這個(gè)函數(shù)中并未使能串口中斷)需要用戶手動(dòng)使能。使能代碼如下:
HAL_UART_Receive_IT(&huart2, (uint8_t *)kRxBuffer, 10);
什么意思呢?
HAL庫(kù)的串口接收思路是這樣的:用戶你可以隨便定義一個(gè)緩存區(qū),大小隨意,然后通過(guò)上邊這個(gè)函數(shù)把這個(gè)緩存區(qū)對(duì)應(yīng)到串口的接收,上面函數(shù)的意思就是把kRxBuffer(這是一個(gè)數(shù)組)作為緩存區(qū),指定大小為10。然后usart2接收數(shù)據(jù)的時(shí)候就防到kRxBuffer這個(gè)數(shù)組中,只有當(dāng)接收到10個(gè)數(shù)據(jù)之后才調(diào)用一次callback函數(shù)(回調(diào)函數(shù))。當(dāng)然不要忘了該函數(shù)的使能串口接收中斷功能, 在:二、中斷模式 的1.1節(jié)中說(shuō)到了串口接收完數(shù)據(jù)后會(huì)關(guān)閉使能,所以,在回調(diào)函數(shù)中一定要再寫一次HAL_UART_Receive_IT(&huart2, (uint8_t *)kRxBuffer, 10),使能接收中斷。
小小的總結(jié)下串口中斷接收怎么用:
(1)指定一個(gè)緩存區(qū)(串口接收到的數(shù)據(jù)會(huì)全部堆到這個(gè)緩存區(qū))
(2)使能串口接收中斷,并把緩存區(qū)對(duì)應(yīng)到串口
(3)在回調(diào)函數(shù)中實(shí)現(xiàn)接收到數(shù)據(jù)之后的操作(比如處理數(shù)據(jù))并再次使能串口接收中斷。
所以更具體一下串口接收的流程就是這樣的:
(1)串口一個(gè)接一個(gè)的接收到數(shù)據(jù)填充到緩存區(qū)
(2)緩存區(qū)滿(大小是用戶定義的)程序幾經(jīng)輾轉(zhuǎn)最后會(huì)調(diào)用到回調(diào)函數(shù)。
(3)執(zhí)行用戶在回調(diào)函數(shù)中實(shí)現(xiàn)的功能。
2.中斷發(fā)送。
2.1發(fā)送中斷的觸發(fā)流程。
由于在STM32中usart2的入口中斷只有一個(gè):
就是上圖的中斷向量表中紅框標(biāo)出來(lái)的。其他的所有中斷其實(shí)都是從這里出發(fā)的,我們?cè)俸娃劢邮找粯愚垡槐榘l(fā)送。
首先是USART2_IRQHandler,找到這個(gè)函數(shù)原型(這一步和接收完全一樣):
再找HAL_UART_IRQHandler(&huart2);原型:
到這里還是和接收完全一樣,注意是完全一樣,源碼也就是上面接收貼出來(lái)的一樣。這次我們主要注意該函數(shù)最后幾行(可以翻上去看源碼):
把中間代碼收起來(lái)以后看最后紅框,這就很明顯了,這里觸發(fā)了發(fā)送中斷(軟件觸發(fā))
接著去找這個(gè)UART_EndTransmit_IT(huart)的函數(shù)原型:
第一個(gè)紅框里清除了發(fā)送中斷使能(同接收一樣,在用完之后就關(guān)掉,但是不同于接收,發(fā)送完成就不用再在回調(diào)函數(shù)中使能了,因?yàn)樵谥袛喟l(fā)送的時(shí)候就會(huì)使能),第二個(gè)紅框調(diào)用回調(diào)函數(shù)。
2.2如何使用發(fā)送中斷。
中斷發(fā)送的意思,非常類似于中斷接收,但其中有一些不同,看下面這個(gè)函數(shù):
HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
一個(gè)非常類似于中斷接收使能的函數(shù)。接收中斷使能函數(shù)的作用是綁定接收緩存區(qū)并使能接收中斷,但是對(duì)于發(fā)送,該函數(shù)的作用是發(fā)送指定長(zhǎng)度的指定數(shù)據(jù)并使能發(fā)送中斷。
比如有一個(gè)unsigned char 數(shù)組a[10],HAL_UART_Transmit_IT(&huart2, a, 10),這一句的意思是用usart2(串口2)發(fā)送a數(shù)組中的10個(gè)數(shù)據(jù),然后使能發(fā)送中斷。
當(dāng)發(fā)送完成之后(或者發(fā)送一半,發(fā)送一半也有個(gè)中斷)就會(huì)執(zhí)行回調(diào)函數(shù)。
總結(jié)一下發(fā)送中斷:
使用HAL_UART_Transmit_IT函數(shù)發(fā)送指定長(zhǎng)度的數(shù)據(jù),并使能發(fā)送中斷,發(fā)送到一半和發(fā)送結(jié)束會(huì)觸發(fā)中斷(相關(guān)的回調(diào)函數(shù)是HAL_UART_TxHalfCpltCallback()和HAL_UART_TxCpltCallback())中斷觸發(fā)后發(fā)送中斷使能會(huì)被清除,然后調(diào)用回調(diào)函數(shù),回調(diào)函數(shù)執(zhí)行完成之后結(jié)束本次發(fā)送。
上一篇:STM32串口環(huán)形緩沖區(qū)
下一篇:STM32F429 DMA串口數(shù)據(jù)發(fā)送
推薦閱讀
史海拾趣
設(shè)計(jì)資源 培訓(xùn) 開(kāi)發(fā)板 精華推薦
- Microchip 升級(jí)數(shù)字信號(hào)控制器(DSC)產(chǎn)品線 推出PWM 分辨率和 ADC 速度業(yè)界領(lǐng)先的新器件
- 意法半導(dǎo)體STM32MP23x:突破成本限制的工業(yè)AI應(yīng)用核心
- 意法半導(dǎo)體推出用于匹配遠(yuǎn)距離無(wú)線微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開(kāi)發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數(shù)
- LGVL配合FreeType為可變字體設(shè)置字重-ESP32篇
- 使用樹(shù)莓派進(jìn)行 ESP32 Jtag 調(diào)試
- ESP32怎么在SPIFFS里面存儲(chǔ)html,css,js文件,以及網(wǎng)頁(yè)和arduino的通訊
- ESP32 freeRTOS使用測(cè)試
- 2025研華智能系統(tǒng)產(chǎn)業(yè)伙伴峰會(huì)成功舉辦
- 意法半導(dǎo)體公布2025年第二季度財(cái)報(bào)和電話會(huì)議時(shí)間安排
- 利用人工智能提升車間生產(chǎn)效率
- 方案分享 | ARXML 規(guī)則下 ECU 總線通訊與 ADTF 測(cè)試方案
- 車載SerDes產(chǎn)業(yè)起飛!國(guó)產(chǎn)新品密集炸場(chǎng)
- 出貨量激增1.34倍! 5G車規(guī)模組成標(biāo)配,三大廠商新品同臺(tái)競(jìng)技
- 6月新能源市場(chǎng):零跑創(chuàng)新高;比亞迪海外突破;理想滑坡
- 基于中科芯車規(guī)MCU的LED矩陣大燈應(yīng)用方案
- 蘋果被判侵犯3G專利,需向西班牙公司TOT賠償1.1億美元
- 從設(shè)計(jì)概念到 FPGA 原型僅需數(shù)分鐘,印度 InCore 完成 SoC Generator 平臺(tái)硅驗(yàn)證
- 防心臟病猝死 智能心電監(jiān)測(cè)衣提前數(shù)天預(yù)警
- 虹膜識(shí)別的原理和五大應(yīng)用領(lǐng)域
- 我國(guó)自主研發(fā)醫(yī)療服務(wù)機(jī)器人 實(shí)現(xiàn)遠(yuǎn)程會(huì)診
- 技術(shù)日漸成熟,激光雷達(dá)廠商押注車規(guī)級(jí)量產(chǎn)產(chǎn)品
- 中國(guó)醫(yī)療器械行業(yè)發(fā)展基礎(chǔ)薄弱,嚴(yán)重依賴進(jìn)口
- AI及IoT加持,錸寶看好PMOLED景氣持續(xù)暢旺
- 合肥高新區(qū)確定“芯屏器合”,積極布局下一代顯示技術(shù)
- 非蘋新機(jī)加持 全球智能手機(jī)看漲 但臺(tái)灣市場(chǎng)仍看淡
- 單片機(jī)定時(shí)計(jì)數(shù)器、中斷和串行口的學(xué)習(xí)
- 單片機(jī)的基本結(jié)構(gòu)解析
- vs2005 c# + wince 如何實(shí)現(xiàn)自動(dòng)撥號(hào)?
- 關(guān)于28035 LIN模塊的問(wèn)題
- st官網(wǎng)上是否可以查到單片機(jī)的化學(xué)物質(zhì)成份表
- 【測(cè)評(píng)SGP40】快速部署實(shí)現(xiàn)的人工智能環(huán)境空氣質(zhì)量跟蹤模型 #1 開(kāi)箱介紹
- 什么是窄帶物聯(lián)網(wǎng)卡
- 求答案。
- 千兆電口的匹配電阻疑問(wèn)???希望各位大俠幫幫小弟!
- 【平頭哥RVB2601創(chuàng)意應(yīng)用開(kāi)發(fā)】第二篇 開(kāi)發(fā)分準(zhǔn)備2(開(kāi)發(fā)環(huán)境搭建和Helloworld例程)
- 景氣太差 國(guó)外網(wǎng)絡(luò)公司開(kāi)始出售不良收購(gòu)資產(chǎn)
- 有關(guān)額定電壓為30伏的電壓互感器 我真的快崩潰了