前言
這是第二次學習這部分內容了,第一次是大一上學期,因為大二下忙著其他事一直沒來得及吧STM32學完,所以假期從頭開始再學,比第一次也有了更深的理解,以下內容均是看【STM32入門教程-2023版 細致講解 中文字幕】https://www.bilibili.com/video/BV1th411z7sn?p=11&vd_source=e1593f6552f3a4d79494f109d996e6d3這個系列的視頻學習的,如有任何問題,歡迎指正!
正文
一、理論知識
1.中斷
在主程序運行過程中,出現了特定的中斷觸發條件,使得 CPU 暫停當前正在運行的程序,轉而去處理中斷程序,處理完成后又返回原來被暫停的位置繼續運行。
2.中斷優先級
當有多個中斷源同時申請中斷時, CPU 會根據中斷源的輕重緩急進行裁決,優先響應更加緊急的中斷源。
3.中斷嵌套
當一個中斷程序正在運行時,又有新的更高優先級的中斷源申請中斷, CPU 再次暫停當前中斷程序,轉而去處理新的中斷程序,處理完成后依次進行返回。
4.NVIC
1)定義
嵌套中斷向量控制器(是內核外設——使用前不用使能時鐘)。用來統一分配中斷優先級和管理中斷的。
2)NVIC優先級分組
?
NVIC的中斷優先級由優先級寄存器的4位(0~15)決定,這4位可以進行切分,分為高n位的搶占優先級和低4-n位的響應優先級搶占優先級高的可以中斷嵌套,響應優先級高的可以優先排隊,搶占優先級和響應優先級均相同的按中斷號排隊。
搶占優先級&響應優先級區別
注意:優先級數字越大,優先級越低,反之優先級越高。
高優先級的搶占優先級是可以打斷正在進行的低搶占優先級中斷的。 .搶占優先級相同的中斷,高響應優先級不可以打斷低響應優先級的中斷。 .搶占優先級相同的中斷,當兩個中斷同時發生的情況下,哪個響應優先級高,哪個先執行。 如果兩個中斷的搶占優先級和響應優先級都是一樣的話,則看哪個中斷先發生就先執行。
特別說明:一般情況下,系統代碼執行過程中,只設置一次中斷優先級分組。
5.EXTI
1)簡介
EXTI可以監測指定GPIO口的電平信號,當其指定的GPIO口產生電平變化時,EXTI將立即向NVIC發出中斷申請,經過NVIC裁決后即可中斷CPU主程序,使CPU執行EXTI對應的中斷程序。
支持的觸發方式:上升沿(低電平—>高電平)/下降沿(高電平—>低電平)/雙邊沿(電平變化)/軟件觸發(程序里執行一段代碼后觸發)。
支持的GPIO口:所有GPIO口,但相同的Pin不能同時觸發中斷通道數:16個GPIO_Pin,外加PVD輸出、RTC鬧鐘、USB喚醒、以太網喚醒觸發。
響應方式:中斷響應/事件響應(觸發其他外設的操作)。
2)基本結構
3)AFIO復用IO口
AFIO主要用于引腳復用功能的選擇和重定義在STM32中;
AFIO主要完成兩個任務:復用功能引腳重映射、中斷引腳選擇。
4)EXTI框圖
或門:只要輸入一個1,輸出就是高電平,只有全部輸入0,輸出才是低電平;
與門:只有全部輸入1,輸出才是高電平,反之則輸出低電平;
非門(三角形加個圈):輸入1就輸出0,輸入0就輸出1.
二、實驗
1.庫函數代碼
EXTI
(1)初始化EXTI,使用方法和GPIO一致。
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
?
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);
?
(2)軟件觸發外部中斷。
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);
(3)在主程序里查看和清除標志位
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
void EXTI_ClearFlag(uint32_t EXTI_Line);
(4)在中斷函數里查看和清除標志位。
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
?
NVIC+SysTick
(1)用來中斷分組的,參數是中斷分組的方式。
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
(2)初始化NVIC
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
(3)設置中斷向量表
`void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);`
(4)系統低功耗配置
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
2.代碼?
(1)main.c
#include "stm32f10x.h" // Device header
#include "delay.h"
#include "OLED.h"
#include "CountSensor.h"int main(void)
{OLED_Init();CountSensor_Init();OLED_ShowString(1,1,"count:");while(1){OLED_ShowNum(1,7,CountSensor_Get(),5);}
}
(2) CountSensor.c
#include "stm32f10x.h" // Device header
uint16_t CountSensor_Count;void CountSensor_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//初始化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);//配置APIOGPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);//配置EXTIEXTI_InitTypeDef EXTI_InitStruct;EXTI_InitStruct.EXTI_Line = EXTI_Line14; EXTI_InitStruct.EXTI_LineCmd = ENABLE;EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;EXTI_Init(&EXTI_InitStruct);//配置NVICNVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);
}void EXTI15_10_IRQHandler(void)
{if(EXTI_GetFlagStatus(EXTI_Line14)==SET){CountSensor_Count++;EXTI_ClearITPendingBit(EXTI_Line14);}
}uint16_t CountSensor_Get(void)
{return CountSensor_Count;
}
(3)CountSensor.h
#ifndef __COUNT_SENSOR_H
#define __COUNT_SENSOR_Hvoid CountSensor_Init(void);
uint16_t CountSensor_Get(void);#endif
還會持續更新噠~
?