GPIO的簡單介紹
內部結構
- 施密特觸發器(TTL肖特基觸發器) 的工作原理:
????????施密特觸發電路(簡稱)是一種波形整形電路,當任何波形的信號進入電路時,輸出在正、負飽和之間跳動,產生方波或脈波輸出。
????????不同于比較器,施密特觸發電路有兩個臨界電壓且形成一個滯后區,可以防止在滯后范圍內之噪聲干擾電路的正常工作。**如遙控接收線路,傳感器輸入電路都會用到它整形。
GPIO的工作模式?(八種)
(十分重要,面試會考!!!)
模式 | 類型 | 模式介紹 |
浮空輸入 | 數字輸入 | 浮空輸入狀態下, IO 的電平狀態是不確定的,完全由外部輸入決定,如果在該引腳懸空的情況下,讀取該端口的電平是不確定的 |
上拉輸入 | 數字輸入 | IO 口在無輸入的情況下,保持高電平 |
下拉輸入 | 數字輸入 | IO 口在無輸入的情況下,保持低電平 |
模擬輸入 | 模擬輸入 | 輸入信號不經施密特觸發器直接接入,輸入信號為模擬量而非數字量,其余輸入方式輸入數字量 |
開漏輸出 | 數字輸出 | 只能輸出低電平 |
推挽輸出 | 數字輸出 | 可以輸出高、低電平 |
復用開漏輸出 | 數字輸出 | 參考復用推挽 |
復用推挽輸出 | 數字輸出 | 此時 IO 受內部外設控制,比如定時器的 PWM ,比如 SPI 的 MOSI , MISO 等。 而普通的推挽輸出,則 IO 受 ODR 控制 |
- ?上拉/下拉/浮空輸入
- ?推挽/開漏/復用推挽/復用開漏輸出
推挽輸出 | 開漏輸出 |
既能輸出高電平,又能輸出低電平。 | 只能輸出低電平,若要輸出高電平則外接上拉電阻。 |
- 復用功能的配置:
?GPIO的寄存器
?常用的是前五種寄存器:
- GPIOx_CRL:
CNFy[1:0] | 位: 31:30 27:26 23:22 19:18 15:14 11:10 7:6 3:2 | CNFy[1:0]:端口x配置位(y = 0…7) (Port x configuration bits) 軟件通過這些位配置相應的I/O端口,請參考表17端口位配置表。
00:模擬輸入模式 01:浮空輸入模式(復位后的狀態) 10:上拉/下拉輸入模式 11:保留
00:通用推挽輸出模式 01:通用開漏輸出模式 10:復用功能推挽輸出模式 11:復用功能開漏輸出模式 |
MODEy[1:0] | 位: 29:28 25:24 21:20 17:16 13:12 9:8, 5:4 1:0 | MODEy[1:0]:(輸出的頻率)端口x的模式位(y = 0…7) (Port x mode bits)軟件通過這些位配置相應的I/O端口,請參考表17端口位配置表。 00:輸入模式(復位后的狀態) 01:輸出模式,最大速度10MHz 10:輸出模式,最大速度20MHz 11:輸出模式,最大速度50MHz |
?說明:這個寄存器有32位,其中一個GPIOA口,例如:GPIOA1需要 4位進行控制,因此,這個寄存器可以控制 8 個 GPIOA的口。但是一個單片機中GPIOA外設最多可以有16個口,因此還需要一個寄存器:GPIOx_CRH。
- GPIOx_CRH:(與GPIOx_CRL同理)
- GPIOx_IDR:
?說明:表示的是GPIO的16的端口,寫1輸入高電平,寫0輸入低電平。
- GPIOx_ODR:
??說明:表示的是GPIO的16的端口,寫1輸出高電平,寫0輸出低電平。
?GPIOx_BSRR(位設置/清除寄存器):
?說明:置1清除位置0,設置位置1。置0保留。
?GPIO口的庫函數
模塊:LED燈?
LED的介紹
定義:LED是發光二極體(Light Emitting Diode, LED)的簡稱,也被稱作發光二極管,正向通電點亮,反向通電不亮。
分類:引腳二極管 和 貼邊二極管
| |
判斷正負級:
引腳二極管 | 貼片二極管 |
方式1:引腳長為正極,短引腳為負極 | 有記號的是負極 |
方式2:燈里面寬的是負極,窄的是正極 | “T”字形:一橫的一邊是正極,另一邊是負極;三角形符號:“邊”靠近的是正極,“角”靠近的是負極。 |
接線方式:
?在上官二號開發板上的LED的原理圖:
接到上官二號芯片上的端口:
小實驗1:點亮一顆LED燈
- led.c文件中代碼
#include "led.h"
#include "stm32f1xx.h" // 外設的驅動函數//初始化GPIO口void led_init(void){//打開時鐘__HAL_RCC_GPIOB_CLK_ENABLE();//調用GPIO的初始化函數GPIO_InitTypeDef GPIO_Initstruct;GPIO_Initstruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_Initstruct.Pin = GPIO_PIN_8;GPIO_Initstruct.Pull = GPIO_PULLUP;GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB, &GPIO_Initstruct);//關閉LEDled1_off();}
//點亮LED1的函數
void led1_on(void){ HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
}//反轉LED1狀態的函數
void led1_toggle(void){HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
}//熄滅LED1狀態的函數
void led1_off(void){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);}
- main.c文件中?
#include "sys.h"
#include "led.h"
#include "delay.h"void led_init(void); /* LED初始化函數聲明 */int main(void)
{HAL_Init(); /* 初始化HAL庫 */stm32_clock_init(RCC_PLL_MUL9); /* 設置時鐘, 72Mhz */led_init(); /* LED初始化 */while(1){ led1_on();delay_ms(500);led1_off();delay_ms(500);}
}
小實驗2:流水燈
- led.c文件中的代碼:
#include "led.h"
#include "stm32f1xx.h" // 外設的驅動函數//初始化GPIO口void led_init(void){//打開時鐘__HAL_RCC_GPIOB_CLK_ENABLE();//調用GPIO的初始化函數GPIO_InitTypeDef GPIO_Initstruct;GPIO_Initstruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_Initstruct.Pin = GPIO_PIN_8|GPIO_PIN_9;GPIO_Initstruct.Pull = GPIO_PULLUP;GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB, &GPIO_Initstruct);//關閉LEDled1_off();led2_off();}
//點亮LED1的函數
void led1_on(void){ HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
}//反轉LED1狀態的函數
void led1_toggle(void){HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
}//熄滅LED1狀態的函數
void led1_off(void){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);}//點亮LED2的函數
void led2_on(void){ HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
}//反轉LED2狀態的函數
void led2_toggle(void){HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
}//熄滅LED2狀態的函數
void led2_off(void){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);}
- mian.c中的文件?
#include "sys.h"
#include "led.h"
#include "delay.h"int main(void)
{HAL_Init(); /* 初始化HAL庫 */stm32_clock_init(RCC_PLL_MUL9); /* 設置時鐘, 72Mhz */led_init(); /* LED初始化 */while(1){ led1_on();led2_off();delay_ms(500);led1_off();led2_on();delay_ms(500);}
}
模塊:蜂鳴器
蜂鳴器的介紹
實物圖:
低電平觸發驅動電路:
- 工作電壓:3.3v
- 電平:將I/O引腳拉低
有源蜂鳴器 | 無源蜂鳴器 |
內部帶有震蕩源,只要給它通電,它就會發出聲音,但是聲音音調是單一的,頻率是固定的。 | ????????內部沒有震蕩源,需要用一定頻率的方波(常見的頻率范圍在2K到5K之間)去驅動它才可以發聲。 由于可以通過不同頻率的方波驅動,其聲音頻率是可控的,可以模擬出多種聲音效果,甚至達到唱歌的 效果。 |
小實驗:讓蜂鳴器響起來
- beep.c文件
#include "stm32f1xx.h"
#include "beep.h"//初始化GPIO口
void GPIO_Init(void){//打開時鐘__HAL_RCC_GPIOB_CLK_ENABLE();//打開GPIO口GPIO_InitTypeDef GPIO_Initstruct;GPIO_Initstruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_Initstruct.Pin = GPIO_PIN_8;GPIO_Initstruct.Pull = GPIO_NOPULL;GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB,&GPIO_Initstruct);//關閉蜂鳴器beep_off();
}
//打開蜂鳴器函數
void beep_on(void){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
}
//關閉蜂鳴器
void beep_off(void){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
}
//反轉蜂鳴器
void beep_toggle(void){HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
}
- mian.c文件
#include "sys.h"
#include "delay.h"
#include "beep.h"int main(void)
{HAL_Init(); /* 初始化HAL庫 */stm32_clock_init(RCC_PLL_MUL9); /* 設置時鐘, 72Mhz */GPIO_Init(); /*GPIO口初始化 */while(1){ beep_on();delay_ms(500);beep_off();delay_ms(500);}
}
模塊:按鍵
按鍵的介紹
實物圖:
按鍵抖動:
定義:按鍵抖動是指在按鍵開關被按下或釋放的瞬間,由于機械觸點的彈性作用或電信號的短暫波動,導致開關狀態不穩定,出現短暫的抖動現象。這種抖動現象會影響按鍵的識別和處理,可能導致按一次鍵而輸入多次,影響設備的正常運行和用戶的使用體驗。?
軟件消除:通過延時跳過抖動的時間段,再判斷IO輸入電平。
上官二號按鍵的電路圖:
接到上官二號板的PA0和PA1口上:
小實驗:按鍵控制LED燈
- led.文件和點亮led的代碼相同。
- key.c文件
#include "key.h"
#include "stm32f1xx.h"
#include "Delay.h"//初始化GPIO口
void key_init(void){//打開時鐘__HAL_RCC_GPIOA_CLK_ENABLE();//調用GPIO初始化函數GPIO_InitTypeDef GPIO_Initstruct;GPIO_Initstruct.Mode = GPIO_MODE_INPUT;GPIO_Initstruct.Pin = GPIO_PIN_0|GPIO_PIN_1;GPIO_Initstruct.Pull = GPIO_PULLUP;GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA,&GPIO_Initstruct);
}//按鍵檢測函數
uint8_t key_scan(void){//檢測按鍵是否按下,消除抖動if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET){delay_ms(15);//消除抖動//再次判斷按鍵是否按下if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET){//如果按鍵按下,等待按鍵松開while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET);//返回按鍵的值return 1;}}//檢測按鍵是否按下,消除抖動if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET){delay_ms(15);//消除抖動//再次判斷按鍵是否按下if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET){//如果按鍵按下,等待按鍵松開while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET);//返回按鍵的值return 2;}}//返回默認值return 0;
}
- main.c文件
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "key.h"int main(void)
{HAL_Init(); /* 初始化HAL庫 */stm32_clock_init(RCC_PLL_MUL9); /* 設置時鐘, 72Mhz */led_init(); /* LED初始化 */key_init(); /* KEY初始化 */uint8_t key_num = 0;while(1){ key_num = key_scan();if(key_num == 1){led1_toggle();}if(key_num == 2){led2_toggle();}}
}
中斷
中斷的相關概念
什么是中斷?
答:中斷是單片機正在執行程序時,由于內部或外部事件的觸發,打斷當前程序,轉而去處理這一事件,當處理完成后再回到原來被打斷的地方繼續執行原程序的過程。
產生中斷的來源:
????????在ARM體系結構中,中斷通常由外設或外部輸入產生,有時也可以由軟件觸發。中斷是單片機系統處理緊急或突發事件的重要方式,如定時器溢出、按鍵輸入、串口數據到達等
中斷的意義:
????????中斷的主要意義在于提高CPU的效率,而不會一直占用CPU,實現對突發事件的實時處理,以及實現程序的并行化和嵌入式系統進程之間的切換。相較于輪詢方式(即按照一定的頻率和周期不斷地檢測某些事件的發生),中斷在處理一些偶然發生的事情時效率更高。
中斷嵌套:
????????如果一個高優先級的中斷發生,它會立即打斷當前正在處理的中斷(如果其優先級較低),并首先處理這個高優先級的中斷,這就是所謂的中斷嵌套。
?中斷的執行流程:
????????當中斷發生時,STM32的執行流程如下:首先,由外設發出中斷請求;然后,處理器暫停當前執行的任務,保護現場(如將當前位置的PC地址壓棧);接著,程序跳轉到對應的中斷服務程序(ISR)并執行;中斷服務程序執行完畢后,恢復現場(如將棧頂的值送回PC);最后,處理器返回到被中斷的位置,繼續執行下一個指令。
STM32中斷?
STM32F103C8T6中斷數量
- STM32F103C8T6 支持的中斷共有 70 個,其中包括 10 個內核中斷和 60 個外部中斷。
- 外部中斷包含?:EXTI、TIM、USART、ADC、I2C、SPI
- 內核中斷包含:
中斷向量表
定義:STM32的中斷向量表是一個存儲中斷處理函數地址的數組,位于Flash區的起始位置。每個數組元素對應一個中斷源,其地址指向相應的中斷服務程序。當中斷發生時,處理器會根據中斷號查找向量表,然后跳轉到對應的中斷服務程序執行。
?中斷向量表的作用:是解決中斷函數地址不固定與中斷必須跳轉到固定地方執行程序之間的矛盾。由于編譯器每次編譯都會為中斷函數隨機分配地址,但硬件要求 :中斷必須跳轉到固定的位置,因此,中斷向量表就作為這樣一個固定的地址列表,其中包含了中斷函數的地址以及跳轉到這些地址的程序。當中斷發生時,處理器會跳轉到這個固定的中斷向量表,然后根據其中的信息跳轉到相應的中斷處理函數,從而執行中斷。
STM32中斷框圖
?NVIC
NVIC介紹
- NVIC,即Nested Vectored Interrupt Controller(嵌套向量中斷控制器),是STM32中的中斷控制器。它負責管理和協調處理器的中斷請求,是STM32中處理異步事件的重要機制。
- ?NVIC 支持:256個中斷(16內核+240外部)。每個 ISER 寄存器處理 32 個中斷,如果有 8 個 ISER 寄存器,就能處理 256 個中斷。因此,也支持:256個優先級,允許裁剪。(STM32F103C8T6有10個內核和60個外部中斷)。
NVIC的工作原理
????????NVIC提供了靈活、高效、可擴展的中斷處理機制,支持?多級優先級、多向中斷、嵌套向量中斷?等特性。當一個中斷請求到達時,NVIC會確定其優先級并決定是否應該中斷當前執行的程序,以便及時響應和處理該中斷請求。這種設計有助于提高系統的響應速度和可靠性,特別是在需要處理大量中斷請求的實時應用程序中。
由上面的流程圖可知NVIC的的作用:?
- 中斷使能/失能控制;
- 中斷優先級控制;
- 優先級分組控制。
?中斷優先級(搶占、響應和自然優先級)
搶占優先級 | 響應優先級 (搶占優先級相同) | 自然優先級 (搶占和響應優先級相同) |
如果一個中斷的搶占優先級高于當前正在執行的中斷,那么它可以打斷當前中斷,優先得到執行。 數值越小,優先級越高 。 | 如果兩個中斷同時到達,且它們的搶占優先級相同,那么響應優先級高的中斷將首先得到響應。 數值越小,優先級越高 。 | 自然優先級是由硬件固定并預先設定的,用戶無法更改。當搶占優先級和響應優先級都相同時,自然優先級將決定哪個中斷先得到處理。 |
?優先級的執行順序:
多個中斷同時發生時,
- 執行順序首先由?搶占優先級決定?。如果搶占優先級相同,則進一步由響應優先級決定。如果響應優先級也相同,則最終由自然優先級決定。
中斷嵌套的情況下,
- 高搶占優先級的中斷可以打斷低搶占優先級的中斷;(圖例如下)
- 但高響應優先級的中斷不能打斷低響應優先級的中斷(當它們具有相同的搶占優先級時)。(圖例如下)
?優先級分組(對搶占和響應優先級分組)
優先級寄存器(IPR):8位。但實際上只用到高4位(由AIRCR寄存器控制)如下面表格所示。用于決定搶占優先級、響應優先級的等級。
優先級分組 | AIRCR[10:8] | 搶占優先級 | 響應優先級 |
0 | 111 | 0 位,取值為 0 | 4 位,取值為 0~15 |
1 | 110 | 1 位,取值為 0~1 | 3 位,取值為 0~7 |
2 | 101 | 2 位,取值為 0~3 | 2 位,取值為 0~3 |
3 | 100 | 3 位,取值為 0~7 | 1 位,取值為 0~1 |
4 | 011 | 4 位,取值為 0~15 | 0 位,取值為 0 |
NVIC寄存器?
?NVIC相關函數介紹
- ?void HAL_NVIC_DisableIRQ(IRQn_Type IRQn)
?ICER:外設中斷使能寄存器
- void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
?ISER:外設中斷失能寄存器
- void HAL_NVIC_SetPriority()
?IPR:外設優先級寄存器
SHPR:內核外設優先級寄存器?
- ?void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
AIRCR :優先級分組寄存器
?NVIC配置方法
- 設置中斷分組 → 設置中斷優先級 → 使能中斷
- 設置中斷分組一般在 HAL_Init 函數中進行
EXTI?
EXIT介紹
定義:EXTI 是 External Interrupt 的縮寫,表示外部 中斷?事件控制器。EXTI 可以監測指定 GPIO 口的電平信號變化,并在檢測到指定條件時,向內核的中斷控制器 NVIC 發出中斷申請。NVIC 在裁決后,如果滿足條件,會中斷CPU的主程序,使 CPU 轉而執行 EXTI 對應的中斷服務程序。
上升沿 | 下降沿 | 雙邊沿 | 軟件觸發 |
| | | ---------- |
?注意事項:
- EXTI 支持所有的 GPIO 口,但需要注意的是,相同的 Pin 不能同時觸發中斷。例如,PA0 和 PB0 不能同時被配置為中斷源。
EXTI 提供了 16 個 GPIO_Pin 的中斷線,以及額外的中斷線如 PVD 輸出、 RTC 鬧鐘、 USB 喚醒和以太網喚醒(互聯型芯片才具備)。
中斷/事件?
中斷:上圖中的線路①;?中斷會打斷CPU當前正在執行的程序,轉而去執行中斷服務程序,待中斷服務程序執行完畢后,CPU會返回到原來的程序執行點繼續執行。
事件:上圖中線路③;事件只是簡單地表示某個動作或狀態的變化,而不會打斷CPU當前正在執行的程序。
事件觸發中斷:上圖線路②;當事件發生時,它會根據配置來決定是否觸發相應的中斷。如果開放了對應的中斷屏蔽位,事件就可以觸發相應的中斷,否則事件只會作為一個信號存在,不會被CPU處理。
EXTI基本結構
?EXTI基本框圖
?EXTI寄存器
(參考手冊上)
- 中斷屏蔽寄存器(EXTI_IMR)?
位 31:20 | 保留,必須始終保持為復位狀態(0)。 |
位19:0 | MRx : 線 x 上的中斷屏蔽 (Interrupt Mask on line x) 0 :屏蔽來自線 x 上的中斷請求; 1 :開放來自線 x 上的中斷請求。 注:位 19 只適用于互聯型產品,對于其它產品為保留位。 |
- ?上升沿觸發選擇寄存器(EXTI_RTSR)
- ??下降沿觸發選擇寄存器(EXTI_FTSR)
- ?掛起寄存器(EXTI_PR)
EXTI相關函數介紹
EXTI函數沒有專門的.c文件。包含在stm32f1xx_hal_gpio.c文件中
- ?初始化函數:HAL_GPIO_Init()
- void HAL_GPIO_EXTI_IRQHandler (uint16_t GPIO_Pin)?:中斷服務函數
?函數①:操作PR寄存器
?函數②:回調函數(寫服務代碼)
?AFIO
AFIO的介紹
????????AFIO 是(Alternate Function Input/Output)的縮寫,表示復用功能 IO,主要用于實現 I/O 端口的復用功能以及外部中斷的控制(本章主要介紹這個功能)。
AFIO與IO口的關系
(參考手冊中的示意圖)
簡化圖:?
注意:由上面兩個框可知,EXTI 支持所有的 GPIO 口,但需要注意的是,相同的 Pin 不能同時觸發中斷。例如,PA0 和 PB0 不能同時被配置為中斷源。
AFIO外部中斷配置寄存器
總共由四個外部中斷配置寄存器,如下所示:
每個寄存器控制只有前八位有效,一個控制四個EXTI口,對應四個GPIO口,如下所示,?
AFIO函數
在HAL_GPIO_Init( )函數里:
對AFIO寄存器進行配置:?
EXTI配置流程
?小實驗:按鍵點燈(中斷法)
實驗目的:使用中斷的方法,按下 KEY1 翻轉 LED1 狀態,而 LED2 一直保持 500ms 的頻率閃爍。
注意事項:
- 按鍵驅動一般用輪詢法(即按照一定的頻率和周期不斷地檢測某些事件的發生,主要由CPU直接負責),不需要中斷來控制(因為按鍵要消抖,使用延時函數)。
- 中斷服務函數:不能加延時函數,阻塞性函數,不能操作硬件(簡單的可以,例如GPIO口;OLED顯示屏等復雜的不允許),寫Printf()函數有時也會導致異常,中斷服務函數中一般設置標志位,在主函數中看到標志有變化,做到業務的處理。?
exti.c文件中代碼:
#include "exti.h"
#include "stm32f1xx.h"
#include "delay.h"
#include "led.h"void exti_init(void){//打開時鐘__HAL_RCC_GPIOA_CLK_ENABLE();//初始化GPIO口GPIO_InitTypeDef GPIO_Initstruct;GPIO_Initstruct.Mode =GPIO_MODE_IT_FALLING;GPIO_Initstruct.Pin = GPIO_PIN_0;GPIO_Initstruct.Pull = GPIO_PULLUP;GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA,&GPIO_Initstruct);//在HAL_Init()函數中優先級分組,默認第四種,實際用二種HAL_NVIC_SetPriority(EXTI0_IRQn,2,0);HAL_NVIC_EnableIRQ(EXTI0_IRQn);}//中斷服務函數,
void EXTI0_IRQHandler(void){//調用GPIO的中斷公共函數,不同外設不同HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);}
//回調函數,業務代碼:按鍵;消抖
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){//消抖delay_ms(20);if(GPIO_Pin == GPIO_PIN_0){ //判斷EXTI0是否是GPIO_PIN0if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET){//判斷GPIO口是否是低電平led1_toggle();}}
}
main.c文件中的代碼:
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "exti.h"int main(void)
{HAL_Init(); /* 初始化HAL庫 */stm32_clock_init(RCC_PLL_MUL9); /* 設置時鐘, 72Mhz */led_init(); /* LED初始化 */exti_init();while(1){ led2_on();delay_ms(500);led2_off();delay_ms(500);}
}