江協科技STM32課程筆記(二)—外部中斷EXTI

二、外部中斷EXTI

中斷:在主程序運行過程中,出現了特定的中斷觸發條件(中斷源),使得CPU暫停當前正在運行的程序,轉而去處理中斷程序,處理完成后又返回原來被暫停的位置繼續運行。

1、stm32中斷簡介

stm32F103有68個可屏蔽中斷通道,包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多個外設。使用NVIC(嵌套中斷向量控制器)統一管理中斷,每個中斷通道都擁有16個可編程的優先等級,可對優先級進行分組,進一步設置搶占優先級和響應優先級。

EXTI0~EXTI4、EXTI9_5和EXTI15_10:即為外部中斷,其中后面兩個為共用的中斷通道,需要在中斷函數中根據標志位判斷是哪個中斷源;

2、NVIC嵌套中斷向量控制器

CPU中用于控制分配中斷優先級,并根據優先級分配中斷的先后執行順序的模塊。分為搶占優先級?(英文前綴pre先占優先級)和響應優先級(英文前綴sub次占優先級)。

搶占優先級是可以產生中斷嵌套,在低搶占優先級的中斷執行中間先執行搶占優先級高的。

響應優先級是插隊,在低響應優先級中斷執行前插隊,但不能搶占。

NVIC中使用SCB_AIRCR寄存器的四位PRIGRUOP進行分組,分配有多少個搶占優先級,有多少個響應優先級。

然后通過NVIC_IPRx寄存器的7~4位決定每個中斷通道的優先級,高n位為搶占優先級,低4-n位為響應優先級。IPRx在庫函數中均已經直接按字節幫我們定義好了,直接使用NVIC->IP[通道號]即可。

NVIC的其他寄存器主要是控制中斷通道是否使能、是否有中斷掛起、設置和清除掛起位等,可以參考手冊和例程

3、EXTI外部中斷控制器

這部分屬于內核外設部分,對于互聯型產品,外部中斷/事件控制器由20個產生事件/中斷請求的邊沿檢測器組成,對于其它產品,則有19個能產生事件/中斷請求的邊沿檢測器。每個輸入線可以獨立地配置輸入類型(脈沖或掛起)和對應的觸發事件(上升沿或下降沿或者雙邊沿都觸發)。每個輸入線都可以獨立地被屏蔽。掛起寄存器保持著狀態線的中斷請求。

事件是指,引腳電平不發生中斷,信號不進入CPU,而是觸發DAC、DMA等外設,用于外設聯合工作。

GPIOA每個引腳需要通過AFIO選通,然后輸入到EXTI中;所以PA0、PB0。。。中只能有一個選通,并進入EXTI0中斷通道。

EXTI的結構

可見支持上升沿、下降沿、雙邊沿和軟件觸發方式。當一個中斷來了,會在請求掛起寄存器中對應位置1,然后根據中斷屏蔽寄存器來決定是否響應中斷。最上面就是外設接口和APB總線,我們可以通過總線訪問這些寄存器

4、使用

對射式紅外傳感器計次

EXTI庫

void EXTI_DeInit(void);      // 清除EXTI的配置,恢復成上電默認的狀態
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);    // 調用這個函數根據結構體里的參數配置EXTI外設,使用方法和GPIO_Init一樣
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);   // 調用這個函數可以把參數傳遞的結構體變量復制一個默認值
// 前面三個函數,基本所有的外設都有,像是庫函數的模板函數一樣,基本每個外設都需要這些類型的函數
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);  
/*軟件觸發外部中斷的,調用這個函數,參數給一個指定的中斷線,就能軟件觸發一次外部中斷 ,如果程序需要用到這個功能的話,可以使用這個函數,如果
只需要外部引腳出啊發中斷,那就不需要這個函數了*/
/*如果想在主程序里查看和清除標志位,就用下面兩個函數*/
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line); // 獲取指定的標志位是否被置1了
void EXTI_ClearFlag(uint32_t EXTI_Line);  // 對置1的標志位進行清除
/*對于這些標志位,有的比較緊急,在置標志位后會觸發中斷,在中斷函數里,如果想查看標志位和清除標志位,就用下面兩個函數*/
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);  // 獲取中斷標志位是否被置1了
void EXTI_ClearITPendingBit(uint32_t EXTI_Line); // 清除中斷掛起標志位
/*上面4個函數也是庫函數的模板函數,很多模塊都有這四個函數,因為在外設運行過程中,會產生一些狀態標志位,比如外部中斷來了,
會有一個掛起寄存器置了一下標志位,對于其它外設,比如串口收到數據,會置標志位,定時器時間到,也會置標志位,這些標志位都是放在狀態寄存器的
,當程序想要看這些標志位時,就可以用到這四個函數*/

NVIC庫

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);    // 這個函數是用來中斷分組的,參數是中斷分組的方式
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);  // 根據結構體里面的指定參數初始化NVIC
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);    //設置中斷向量表
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);  //系統低功耗配置

代碼


uint16_t CountSensor_Count;				//全局變量,用于計數/*** 函    數:計數傳感器初始化* 參    數:無* 返 回 值:無*/
void CountSensor_Init(void)
{/*開啟時鐘*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//開啟GPIOB的時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);		//開啟AFIO的時鐘,外部中斷必須開啟AFIO的時鐘/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);						//將PB14引腳初始化為上拉輸入/*AFIO選擇中斷引腳*/GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);//將外部中斷的14號線映射到GPIOB,即選擇PB14為外部中斷引腳/*EXTI初始化*/EXTI_InitTypeDef EXTI_InitStructure;						//定義結構體變量EXTI_InitStructure.EXTI_Line = EXTI_Line14;					//選擇配置外部中斷的14號線EXTI_InitStructure.EXTI_LineCmd = ENABLE;					//指定外部中斷線使能EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;			//指定外部中斷線為中斷模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;		//指定外部中斷線為下降沿觸發EXTI_Init(&EXTI_InitStructure);								//將結構體變量交給EXTI_Init,配置EXTI外設/*NVIC中斷分組*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);				//配置NVIC為分組2//即搶占優先級范圍:0~3,響應優先級范圍:0~3//此分組配置在整個工程中僅需調用一次//若有多個中斷,可以把此代碼放在main函數內,while循環之前//若調用多次配置分組的代碼,則后執行的配置會覆蓋先執行的配置/*NVIC配置*///10~15共用一個中斷通道NVIC_InitTypeDef NVIC_InitStructure;						//定義結構體變量NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;		//選擇配置NVIC的EXTI15_10線NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				//指定NVIC線路使能NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	//指定NVIC線路的搶占優先級為1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;			//指定NVIC線路的響應優先級為1NVIC_Init(&NVIC_InitStructure);								//將結構體變量交給NVIC_Init,配置NVIC外設
}/*** 函    數:獲取計數傳感器的計數值* 參    數:無* 返 回 值:計數值,范圍:0~65535*/
uint16_t CountSensor_Get(void)
{return CountSensor_Count;
}/*** 函    數:EXTI15_10外部中斷函數* 參    數:無* 返 回 值:無* 注意事項:此函數為中斷函數,無需調用,中斷觸發后自動執行*           函數名為預留的指定名稱,可以從啟動文件復制*           請確保函數名正確,不能有任何差異,否則中斷函數將不能進入*/
void EXTI15_10_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line14) == SET)		//判斷是否是外部中斷14號線觸發的中斷{/*如果出現數據亂跳的現象,可再次判斷引腳電平,以避免抖動*/if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0){CountSensor_Count ++;					//計數值自增一次}EXTI_ClearITPendingBit(EXTI_Line14);		//清除外部中斷14號線的中斷標志位//中斷標志位必須清除//否則中斷將連續不斷地觸發,導致主程序卡死}
}int main(void)
{OLED_Init();			//OLED初始化CountSensor_Init();		//計數傳感器初始化/*顯示靜態字符串*/OLED_ShowString(1, 1, "Count:");	//1行1列顯示字符串Count:while (1){OLED_ShowNum(1, 7, CountSensor_Get(), 5);		//OLED不斷刷新顯示CountSensor_Get的返回值}
}

OLED代碼使用GPIO開漏輸出模擬I2C總線,具體代碼見江協科技官網。后續學習I2C時再仔細研讀

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/98178.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/98178.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/98178.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java常見排序算法實現

以下是Java中幾種常見排序算法的實現,包括冒泡排序、選擇排序、插入排序、快速排序和歸并排序。 各排序算法特點說明:冒泡排序: 原理:重復比較相鄰元素,將大的元素逐步"冒泡"到數組末尾特點:穩定…

Python爬蟲實戰:研究Pandas,構建地理信息數據采集和分析系統

1. 引言 1.1 研究背景 地理數據作為描述地球表面空間要素的數據,包含了豐富的空間位置、分布特征和屬性信息,在城市規劃、環境監測、商業分析等眾多領域發揮著不可替代的作用。隨著 "數字地球"、"智慧城市" 等概念的提出和發展,地理數據的重要性日益凸…

nvm安裝node后出現報錯: “npm 不是內部或外部命令,也不是可運行的程序 或批處理文件”

一、問題描述 使用nvm安裝node后,使用npm命令報錯如下 報錯1:npm : 無法將“npm”項識別為 cmdlet、函數、腳本文件或可運行程序的名稱。請檢查名稱的拼寫,如果包括路徑,請確保路徑正確,然后再試一次。報錯2&#xf…

【高等數學】第十二章 無窮級數——第二節 常數項級數的審斂法

上一節:【高等數學】第十二章 無窮級數——第一節 常數項級數的概念和性質 總目錄:【高等數學】 目錄 文章目錄1. 正項級數及其審斂法1. 正項級數及其審斂法 正項級數 各項都是正數或零的級數稱為正項級數正項級數收斂 正項級數 ∑n1∞un\displaystyle\…

圖觀 流渲染場景編輯器

一、 產品簡介圖觀 流渲染場景編輯器,以編輯器插件形式,在Unreal Engine中輕松編輯并發布數字孿生場景。支持 GIS 全球/局部 數字孿生場景構建,并預置 圖觀技術架構工程模板,支持對 場景效果、鏡頭視野,環境時間氣象、…

Visual Studio 函數頭顯示引用個數

在visual studio 里面有自帶的顯示引用方案 codeLens

數據結構的哈希表沖突解決方法

哈希表是一種高效的數據結構,通過哈希函數將鍵映射到存儲位置。但由于哈希函數可能將不同鍵映射到相同位置(稱為哈希沖突),需要有效的方法來解決沖突。以下是常見的沖突解決策略,每種方法都有其原理、優缺點和適用場景。我將逐步解釋這些方法,確保內容清晰可靠。 1. 開放…

MySQL 基礎概念與簡單使用

MySQL 基礎概念與簡單使用 一、數據庫基本概念 1、數據庫定義 數據庫(Database)是存儲在計算機內、有組織、可共享的數據集合,用于高效地管理大量數據。 2、數據庫分類 按數據模型分類: 關系型數據庫(如 MySQL、Oracle…

關系模型的數據結構

在關系數據庫這個世界里,所有東西(包括你要記錄的人、物、事,以及它們之間的聯系)都用一種叫做“關系”的結構來表示。而這種“關系”的靈魂,就是“碼”(Key)。1. 核心思想:萬物皆“…

180 課時吃透 Go 語言游戲后端系列0:序言

零基礎能學習 Go 游戲后端開發嗎? 當然能學啦!別擔心,就算你之前對編程一竅不通,也完全沒問題。我特意準備了180課時的開發課程,由淺入深、從理論到實踐帶領大家學會使用GO語言進行游戲后端開發。 編程就像學一門新語…

Android-SerialPort-API-master源碼 串口調試 權限分析 定制

我把界面美化了一下Android-SerialPort-API-master源碼 1.加了發送按鈕 2.加上固定/dev/ttyGS1和GS9串口權限問題已經查清楚了。app與PosServer都是使用google的SerialPort方案。我做的app 都多使用一個函數available(),這個函數是非常有用的。在上位機發送單條指令…

KVM 入門使用手冊

KVM 入門使用手冊 1. 概述 2. 安裝 在 Ubuntu/Debian 上安裝 在 RHEL/CentOS/Fedora 上安裝 3. 網絡配置 查看默認網絡 使用橋接網絡 (推薦用于服務器) 4. 創建虛擬機 方法一:使用圖形界面 (virt-manager) 方法二:使用命令行 (virt-install) 5. 管理虛擬機 使用 `virsh` 命令…

Devise Ruby身份驗證解決方案全攻略

文章目錄 前言Devise到底是什么?為什么選擇Devise?環境準備Devise安裝指南第一步:添加Devise到你的Gemfile第二步:初始化Devise第三步:生成用戶模型第四步:運行數據庫遷移 Devise核心模塊詳解Database Auth…

68-python操作SQLite

1. 了解SQLite SQLite,是一款輕型的數據庫,是遵守ACID的關系型數據庫管理系統,它包含在一個相對小的C庫中。它是D.RichardHipp建立的公有領域項目。它的設計目標是嵌入式的,而且已經在很多嵌入式產品中使用了它,它占用…

在Qt項目中使用QtConcurrent::run,實現異步等待和同步調用

在使用Qt進行開發時,經常需要使用異步方法,不同于C#的async/await,Qt中提供了QtConcurrent::run接口方法可供調用,習慣了C#的await,便想著能不能封裝幾個類似的函數在項目中使用,探索了下,有如下…

視頻分類 pytorchvideo

目錄 1. 速度 vs 精度分析 mvit: r2plus1d_r50 推理代碼: x3d_xs推理代碼: R(21)D X3D(輕量級,速度快) I3D(經典 3D CNN) 替換分類層(適配你的任務) https://gith…

OpenTiny NEXT 內核新生:生成式UI × MCP,重塑前端交互新范式!

近期,我們推出 OpenTiny NEXT —— OpenTiny的下一代企業級前端智能開發解決方案。這不僅是一次技術升級,更是一場用戶交互范式的變革:從傳統的人機交互升級成為人機交互范式和智能體交互范式的融合。我們堅信,每一個企業應用都值…

深度神經網絡1——梯度問題+標簽數不夠問題

要解決一個復雜問題,可能要訓練更深的神經網絡,可能會10層及以上,每層包含數百個神經元,成千上萬個連接。這樣大的神經網絡在訓練的時候可能會遇到以下問題:這樣在進行反向傳播的時候,隨著層數越來越低會遇…

(筆記)內存文件映射mmap

內存文件映射是一種將文件內容映射到進程的虛擬地址空間的技術,使得文件可以被視為內存的一部分,從而允許程序直接對這部分內存進行讀寫操作,而無需傳統的文件 I/O 調用。這種方法不僅簡化了文件操作,還提高了處理效率。 在Linux…

Golang中的NaN(Not a Number)

Golang中的NaN(Not a Number) 在Go語言中,NaN是浮點數(特別是float32和float64)中的一個特殊值,表示未定義或不可表示的數值。 go中,除數為0時并不會返回error或者nil,而是返回無窮大…