中斷是計算機系統(tǒng)最重要的組成機制之一,在ARM架構(gòu)里,通常稱為異常(Exception),在文檔里是這么說的:
An exception can be caused by the execution of an exception generating instruction or triggered as a response to a system behavior such as an interrupt, memory management protection violation, alignment or bus fault, or a debug event.
意思是異常是由某些能夠生成異常的指令(例如:SVC)或者是響應(yīng)外部中斷、內(nèi)存沖突、對齊或總線錯誤、調(diào)試等系統(tǒng)行為導致的。
所以,在ARM架構(gòu)里,中斷指的是外設(shè)產(chǎn)生的需要系統(tǒng)優(yōu)先處理的事件,是異常的一種。異常由NVIC(Nested Vectored Interrupt Controller)模塊統(tǒng)一管理。
關(guān)于中斷和異常的工作原理,在ARM架構(gòu)下的工作方式等這里不做展開,需要復習這些知識點的建議找ARM內(nèi)核架構(gòu)的文檔去看。這里主要以HAL庫中STM32F7的串口中斷響應(yīng)過程為例,來看一下中斷到底是怎么工作的,為什么能夠提高系統(tǒng)運行效率。
1. CubeMX配置串口1工作在中斷模式下
還是之前的點燈例程,按下圖配置串口1,重新生成代碼。
需要說明的是,ARM的中斷優(yōu)先級分為搶占式優(yōu)先級和子優(yōu)先級,STM32采用4個優(yōu)先級位,也即4個優(yōu)先級位都為搶占式優(yōu)先級(FreeRTOS就是這樣處理的)時,總共有16個優(yōu)先級別,數(shù)值越小優(yōu)先級越高。這里默認就行。
2. 生成代碼分析
在生成的工程里Core->Src目錄下,會多一個usart.c的源文件,里邊有下面三個函數(shù),把代碼注釋寫出來:
//串口1初始化函數(shù)
void MX_USART1_UART_Init(void)
{
//設(shè)置串口1工作參數(shù):115200bps,1個起始位,8個數(shù)據(jù)位,1個停止位,無校驗位
//調(diào)用HAL的串口初始化函數(shù)HAL_UART_Init(&huart1)
}
//串口的MSP(MCU Support Package)初始化,這是與硬件相關(guān)的初始化,單獨提出來,方便移植
//這是一個回調(diào)函數(shù),會被HAL的串口初始化函數(shù)調(diào)用
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
//串口1相關(guān)時鐘使能
//串口1相關(guān)GPIO初始化
//設(shè)置NVIC,使能串口1中斷
}
//串口MSP的反初始化,調(diào)用這個函數(shù)會使串口失能,相關(guān)的時鐘、引腳和中斷恢復到復位狀態(tài)
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
//失能串口1時鐘
//失能串口1引腳
//失能串口1中斷
}
在main.c中調(diào)用串口1初始化函數(shù),程序運行時完成串口1的初始化。
另外,在stm32f7xx.c中,增加了下面的函數(shù):
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}
這是串口1 的中斷服務(wù)程序,通過調(diào)用HAL庫的串口中斷處理程序HAL_UART_IRQHandler完成中斷響應(yīng)。這個中斷服務(wù)程序完全可以針對該串口完成的具體功能自己去寫,效率更高。調(diào)用HAL庫完成中斷處理更簡單方便,可移植性更好。
另外要注意的是,調(diào)用HAL庫完成中斷處理的話,還需要自己重寫中斷處理的回調(diào)函數(shù),HAL庫里的回調(diào)函數(shù)是一個弱函數(shù),本身并沒有實現(xiàn)任何功能。這也很好理解,每個應(yīng)用的需求都不同,不可能寫出一個通用的中斷處理函數(shù)。而且有一個回調(diào)用的弱函數(shù)在,就算是用戶程序沒有實現(xiàn),也不會導致程序出錯。
3. 添加代碼實現(xiàn)功能
假設(shè)要實現(xiàn)一個最簡單的情況,串口每接收到一個字節(jié)的數(shù)據(jù),非n則計數(shù)器RxCounter加1,否則計數(shù)器清零。為了方便觀察,我們按下邊這樣實現(xiàn)。
在main.c中定義兩個全局變量,并申明usart.c中定義的串口1的句柄,如下:
uint8_t* Uart1RxBuff = 0;
uint8_t RxCounter = 0;
extern UART_HandleTypeDef huart1;
并在main函數(shù)的while循環(huán)前加如下代碼,實現(xiàn)串口1每接收一個字節(jié)產(chǎn)生中斷,接收的數(shù)據(jù)存放在Uart1RxBuff中。
if (HAL_UART_Receive_IT(&huart1, Uart1RxBuff, 1) != HAL_OK)
{
Error_Handler();
}
在usart.c中,聲明main.c中定義的兩個全局變量:
extern uint8_t* Uart1RxBuff;
extern uint8_t RxCounter;
并重新實現(xiàn)接收中斷的回調(diào)函數(shù)如下:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/*判斷是否是串口1中斷*/
if(huart- >Instance == USART1)
{
/*判斷接收的數(shù)據(jù)是否為n*/
if(*Uart1RxBuff != 'n')
{
RxCounter ++;
}
else
{
RxCounter = 0;
}
/*重新使能串口1接收中斷*/
HAL_UART_Receive_IT(&huart1, Uart1RxBuff, 1);
}
}
而HAL庫中的接收回調(diào)弱函數(shù)的代碼如下:
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_UART_RxCpltCallback can be implemented in the user file.
*/
}
另外, UNUSED是一個宏,定義如下:
#define UNUSED(X) (void)X /* To avoid gcc/g++ warnings */
好了,到此就完成了一個簡單的串口接收中斷處理的任務(wù)。能夠判斷接收的有效字符數(shù)。
4. 中斷響應(yīng)過程分析
串口1接收到一個字節(jié)的數(shù)據(jù)后,USART_ISR寄存器的RXNE位置1,如果對應(yīng)的接收中斷使能的話,則會向NVIC產(chǎn)生一個中斷請求,NVIC根據(jù)中斷源(USART1)去中斷向量表相應(yīng)的地址上找到中斷向量(中斷服務(wù)程序的入口地址),執(zhí)行串口1的中斷服務(wù)程序。
由上圖可以看出,USART1的中斷向量偏移地址為0x000000D4,默認是從零地址開始偏移,所以實際地址也為0x000000D4。中斷向量表這個地址上存儲的中斷向量是中斷服務(wù)程序USART1_IRQHandler的入口地址??催^之前文章關(guān)于啟動代碼的分析就應(yīng)該知道,在啟動代碼里定義好了中斷向量表,中斷向量地址是由鏈接器生成符號地址后裝入中斷向量表的。
那么接下來的調(diào)用過程是這樣的:
5. 小結(jié)
基于HAL庫的串口中斷的基本流程就是這樣,但是并沒有深入去查看相關(guān)庫函數(shù)的實現(xiàn)過程,想全面掌握的話還需要去仔細閱讀庫函數(shù)源碼。
-
FreeRTOS
+關(guān)注
關(guān)注
12文章
492瀏覽量
63925 -
串口中斷
+關(guān)注
關(guān)注
0文章
67瀏覽量
14275 -
STM32F7
+關(guān)注
關(guān)注
1文章
48瀏覽量
9384 -
中斷響應(yīng)
+關(guān)注
關(guān)注
0文章
11瀏覽量
3107 -
HAL庫
+關(guān)注
關(guān)注
1文章
121瀏覽量
6806
發(fā)布評論請先 登錄
STM32f405 HAL庫串口中斷接受上溢錯誤(ORE)問題
STM32 HAL庫多串口中斷通訊【任意長度 不丟幀】精選資料分享
【STM32的HAL庫開發(fā)】CubeMX配置HAL庫,不進串口中斷的問題 精選資料分享
否有用于stm32f7的SPL庫?
STM32 串口使用IDLE中斷+DMA接收(HAL庫函數(shù))

STM32H7 串口 空閑中斷 任意長接收 Hal庫 IDLE

STM32 HAL庫中串口空閑中斷+DMA 實現(xiàn)串口數(shù)據(jù)的不定長接收

STM32 的 USART 串口中斷通訊---輸出 hello windows(實現(xiàn) STM32 與主機的通訊)

STM32使用CubeMAX配置的串口中斷接收方法

評論