日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【STM32】外部中断

發布時間:2024/4/24 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【STM32】外部中断 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

00. 目錄

文章目錄

    • 00. 目錄
    • 01. 外部中斷簡介
    • 02. 外部中斷配置
    • 03. 外部中斷步驟
    • 04. 硬件設計
    • 05. 程序示例一
    • 06. 程序示例二
    • 07. 附錄
    • 08. 聲明

01. 外部中斷簡介

外部中斷的代碼主要分布在固件庫的 stm32f4xx_exti.h 和 stm32f4xx_exti.c 文件中。

STM32F4 的每個 IO 都可以作為外部中斷的中斷輸入口,這點也是 STM32F4 的強大之處。STM32F407 的中斷控制器支持 22
個外部中斷/事件請求。每個中斷設有狀態位,每個中斷/事件都有獨立的觸發和屏蔽設置。

STM32F407 的 22 個外部中斷為:

  • EXTI 線 0~15:對應外部 IO 口的輸入中斷。
  • EXTI 線 16:連接到 PVD 輸出。
  • EXTI 線 17:連接到 RTC 鬧鐘事件。
  • EXTI 線 18:連接到 USB OTG FS 喚醒事件。
  • EXTI 線 19:連接到以太網喚醒事件。
  • EXTI 線 20:連接到 USB OTG HS(在 FS 中配置)喚醒事件。
  • EXTI 線 21:連接到 RTC 入侵和時間戳事件。
  • EXTI 線 22:連接到 RTC 喚醒事件。

從上面可以看出,STM32F4 供 IO 口使用的中斷線只有 16 個,但是 STM32F4 的 IO 口卻遠遠不止 16 個,那么 STM32F4 是怎么把 16 個中斷線和 IO 口一一對應起來的呢?于是 STM32就這樣設計,GPIO 的管教 GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G,H,I)分別對應中斷線 0~15。這樣每個中斷線對應了最多 9 個 IO 口,以線 0 為例:它對應了 GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、GPIOF.0、GPIOG.0,GPIOH.0,GPIOI.0。而中斷線每次只能連接到 1 個 IO口上,這樣就需要通過配置來決定對應的中斷線配置到哪個 GPIO 上了。下面我們看看 GPIO跟中斷線的映射關系圖:

02. 外部中斷配置

2.1 使能 IO口時鐘,初始化 IO

我們要使用 IO 口作為中斷輸入,所以我們要使能相應的 IO 口時鐘,以及初始化相應的 IO 口為輸入模式

2.2 開啟 SYSCFG 時鐘,設置 IO 口與中斷線的映射關系

只要我們使用到外部中斷,就必須打開 SYSCFG 時鐘。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能 SYSCFG 時鐘

配置 GPIO 與中斷線的映射關系。在庫函數中,配置 GPIO 與中斷線的映射關系的函數 SYSCFG_EXTILineConfig ()來實現的:

void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex);

該函數將 GPIO 端口與中斷線映射起來,程序示例:

SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);

2.3 初始化線上中斷,設置觸發條件

中斷線上中斷的初始化是通過函數 EXTI_Init()實現的。EXTI_Init()函數的定義是:

void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);

程序示例

EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line= EXTI_Line4; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //初始化外設 EXTI 寄存器

2.4 配置中斷分組(NVIC ),并使能中斷

我們設置好中斷線和 GPIO 映射關系,然后又設置好了中斷的觸發模式等初始化參數。既然是外部中斷,涉及到中斷我們當然還要設置 NVIC 中斷優先級。

NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能按鍵外部中斷通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //搶占優先級 2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //響應優先級 2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中斷通道 NVIC_Init(&NVIC_InitStructure); //中斷優先級分組初始化

2.5 編寫中斷服務函數

我們配置完中斷優先級之后,接著要做的就是編寫中斷服務函數。中斷服務函數的名字是在 MDK 中事先有定義的。這里需要說明一下,STM32F4 的 IO 口外部中斷函數只有 7 個,分別為:

DCD EXTI0_IRQHandler ; EXTI Line0 DCD EXTI1_IRQHandler ; EXTI Line1 DCD EXTI2_IRQHandler ; EXTI Line2 DCD EXTI3_IRQHandler ; EXTI Line3 DCD EXTI4_IRQHandler ; EXTI Line4 DCD EXTI9_5_IRQHandler ; External Line[9:5]s DCD EXTI15_10_IRQHandler ; External Line[15:10]s

中斷線 0-4 每個中斷線對應一個中斷函數,中斷線 5-9 共用中斷函數 EXTI9_5_IRQHandler,中斷線 10-15 共用中斷函數EXTI15_10_IRQHandler。在編寫中斷服務函數的時候會經常使用到兩個函數,第一個函數是判斷某個中斷線上的中斷是否發生(標志位是否置位)

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)

這個函數一般使用在中斷服務函數的開頭判斷中斷是否發生。另一個函數是清除某個中斷線上的中斷標志位:

void EXTI_ClearITPendingBit(uint32_t EXTI_Line)

這個函數一般應用在中斷服務函數結束之前,清除中斷標志位。

03. 外部中斷步驟

使用 IO 口外部中斷的一般步驟:
1)使能 IO 口時鐘,初始化 IO 口為輸入。
2)使能 SYSCFG 時鐘,設置 IO 口與中斷線的映射關系。
3)初始化線上中斷,設置觸發條件等。
4)配置中斷分組(NVIC),并使能中斷。
5)編寫中斷服務函數。

04. 硬件設計

探索者 STM32F4 開發板上載有的 4 個按鈕(KEY_UP、KEY0、KEY1 和 KEY2),來控制板上的 2 個 LED(DS0 和 DS1)和蜂鳴器,其中 KEY_UP 控制蜂鳴器,按一次叫,再按一次停;KEY0 控制 DS0,按一次亮,再按一次滅;KEY1 控制 DS1,
效果同 KEY2;KEY2 則同時控制 DS0 和 DS1,按一次,它們的狀態就翻轉一次。

05. 程序示例一

KEY0控制LED1的翻轉

exti.h文件

#ifndef __EXTI_H__ #define __EXTI_H__#include "sys.h"//中斷初始化函數void EXTIX_Init(void);#endif /*__EXTI_H__*/

exti.c文件

#include "exti.h" #include "key.h" #include "led.h" #include "delay.h" #include "usart.h"//中斷初始化函數void EXTIX_Init(void){EXTI_InitTypeDef EXTI_InitStruct;NVIC_InitTypeDef NVIC_InitStruct;//按鍵初始化KEY_Init();//初始化SYSCFG時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//KEY0 --> PE4SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);//配置中斷EXTI_InitStruct.EXTI_Line = EXTI_Line4;EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;EXTI_InitStruct.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStruct);//配置中斷分組NVIC_InitStruct.NVIC_IRQChannel = EXTI4_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);}//中斷線4處理函數 void EXTI4_IRQHandler(void) {printf("KEY0按下啦....\r\n");//消抖delay_ms(10);if (0 == KEY0){LED1 = !LED1;}//清中斷EXTI_ClearITPendingBit(EXTI_Line4); }

main.c文件

#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "beep.h" #include "key.h" #include "exti.h"int main(void) { BEEP = 0;LED1 = 0;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);BEEP_Init();LED_Init();delay_init(168);uart_init(115200);//外部中斷初始化EXTIX_Init();while(1){printf("程序正在運行.....\r\n");delay_ms(1000);} }

06. 程序示例二

exti.h文件

#ifndef __EXTI_H__ #define __EXTI_H__#include "sys.h"//中斷初始化函數void EXTIX_Init(void);#endif /*__EXTI_H__*/

exti.c文件

#include "exti.h" #include "key.h" #include "led.h" #include "beep.h" #include "delay.h" #include "usart.h"//中斷初始化函數void EXTIX_Init(void){EXTI_InitTypeDef EXTI_InitStruct;NVIC_InitTypeDef NVIC_InitStruct;//按鍵初始化KEY_Init();//初始化SYSCFG時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//KEY0 --> PE4SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);//KEY1 --> PE3SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);//KEY1 --> PE2SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);//KEY_UP --> PA0SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//配置中斷 KEY0 KEY1 KEY2EXTI_InitStruct.EXTI_Line = EXTI_Line4 | EXTI_Line3 | EXTI_Line2;EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;EXTI_InitStruct.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStruct);//配置中斷 KEY_UPEXTI_InitStruct.EXTI_Line = EXTI_Line0;EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;EXTI_InitStruct.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStruct);//配置中斷分組 KEY0NVIC_InitStruct.NVIC_IRQChannel = EXTI4_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);//配置中斷分組 KEY1NVIC_InitStruct.NVIC_IRQChannel = EXTI3_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);//配置中斷分組 KEY2NVIC_InitStruct.NVIC_IRQChannel = EXTI2_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);//配置中斷分組 WK_UPNVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);}//中斷線4處理函數 void EXTI4_IRQHandler(void) {printf("KEY0按下啦....\r\n");//消抖delay_ms(10);if (0 == KEY0){LED1 = !LED1;}//清中斷EXTI_ClearITPendingBit(EXTI_Line4); }//中斷線3處理函數 void EXTI3_IRQHandler(void) {printf("KEY1按下啦....\r\n");//消抖delay_ms(10);if (0 == KEY1){LED2 = !LED2;}//清中斷EXTI_ClearITPendingBit(EXTI_Line3); }//中斷線2處理函數 void EXTI2_IRQHandler(void) {printf("KEY2按下啦....\r\n");//消抖delay_ms(10);if (0 == KEY2){LED1 = !LED1;LED2 = !LED2;}//清中斷EXTI_ClearITPendingBit(EXTI_Line2); }//中斷線0處理函數 void EXTI0_IRQHandler(void) {printf("KEY_UP按下啦....\r\n");//消抖delay_ms(10);if (1 == WK_UP){BEEP = !BEEP;}//清中斷EXTI_ClearITPendingBit(EXTI_Line0); }

main.c文件

#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "beep.h" #include "key.h" #include "exti.h"int main(void) { BEEP = 0;LED1 = 0;LED2 = 0;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);BEEP_Init();LED_Init();delay_init(168);uart_init(115200);//外部中斷初始化EXTIX_Init();while(1){printf("程序正在運行.....\r\n");delay_ms(1000);} }

07. 附錄

7.1 【STM32】STM32系列教程匯總

網址:【STM32】STM32系列教程匯總

08. 聲明

該教程參考了正點原子的《STM32 F4 開發指南》

總結

以上是生活随笔為你收集整理的【STM32】外部中断的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。