STM32 的 GPIO和中斷

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端口位配置表。

  • 輸入模式(MODE[1:0]=00)

00:模擬輸入模式

01:浮空輸入模式(復位后的狀態)

10:上拉/下拉輸入模式

11:保留

  • 輸出模式(MODE[1:0]>00)

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、USARTADCI2CSPI
  • 內核中斷包含:

中斷向量表

定義: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的的作用:?

  1. 中斷使能/失能控制;
  2. 中斷優先級控制;
  3. 優先級分組控制。

?中斷優先級(搶占、響應和自然優先級)

搶占優先級

響應優先級

(搶占優先級相同)

自然優先級

(搶占和響應優先級相同)

如果一個中斷的搶占優先級高于當前正在執行的中斷,那么它可以打斷當前中斷,優先得到執行。 數值越小,優先級越高
如果兩個中斷同時到達,且它們的搶占優先級相同,那么響應優先級高的中斷將首先得到響應。 數值越小,優先級越高
自然優先級是由硬件固定并預先設定的,用戶無法更改。當搶占優先級和響應優先級都相同時,自然優先級將決定哪個中斷先得到處理。

?優先級的執行順序:

多個中斷同時發生時

  • 執行順序首先由?搶占優先級決定?。如果搶占優先級相同,則進一步由響應優先級決定。如果響應優先級也相同,則最終由自然優先級決定。

中斷嵌套的情況下

  • 高搶占優先級的中斷可以打斷低搶占優先級的中斷;(圖例如下)

  • 但高響應優先級的中斷不能打斷低響應優先級的中斷(當它們具有相同的搶占優先級時)。(圖例如下)

?優先級分組(對搶占和響應優先級分組)

優先級寄存器(IPR):8位。但實際上只用到高4位(由AIRCR寄存器控制)如下面表格所示用于決定搶占優先級、響應優先級的等級。

優先級分組AIRCR[10:8]搶占優先級響應優先級
0111
0 位,取值為 0
4 位,取值為 0~15
1110
1 位,取值為 0~1
3 位,取值為 0~7
2101
2 位,取值為 0~3
2 位,取值為 0~3
3100
3 位,取值為 0~7
1 位,取值為 0~1
4011
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觸發方式
上升沿下降沿雙邊沿軟件觸發

----------

?注意事項:

  • 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);}
}

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

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

相關文章

Server - 優雅的配置服務器 Bash 環境(.bashrc)

歡迎關注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/147335592 免責聲明:本文來源于個人知識與公開資料,僅用于學術交流,歡迎討論,不支持轉載。 登錄服…

使用PyTorch實現圖像增廣與模型訓練實戰

本文通過完整代碼示例演示如何利用PyTorch和torchvision實現常用圖像增廣方法,并在CIFAR-10數據集上訓練ResNet-18模型。我們將從基礎圖像變換到復雜數據增強策略逐步講解,最終實現一個完整的訓練流程。 一、圖像增廣基礎操作 1.1 準備工作 #matplotli…

解決Mac 安裝 PyICU 依賴失敗

失敗日志: 解決辦法 1、使用 homebrew 安裝相關依賴 brew install icu4c 安裝完成后,設置環境變量 echo export PATH"/opt/homebrew/opt/icu4c77/bin:$PATH" >> ~/.zshrcecho export PATH"/opt/homebrew/opt/icu4c77/sbin:$PATH…

Springboot后端查詢參數接收

1.實現方式 假設前端發送的接口: /users?nameJohn&age30 后端怎么接收里面的name和age呢?以及再發別的參數后端怎么接收呢? 1.比較簡單的方式 當控制器方法的參數類型是簡單類型(如 String、Integer、Long 等&#xff09…

桌面應用中VUE使用新瀏覽器窗口打開頁面

1、瀏覽器應用忽略此方式,可任意方式打開。針對桌面應用設置 newWindowClick(){try {this.fileUrl "";this.params.year ""this.params.date ""axios({method: post,url: /url/pdf/preview,data: this.params,}).then(res> {t…

華為手機怎么進行音頻降噪?音頻降噪技巧分享:提升聽覺體驗

在當今數字化時代,音頻質量對于提升用戶體驗至關重要,無論是在通話、視頻錄制還是音頻文件播放中,清晰的音頻都能帶來更佳的聽覺享受。 而華為手機憑借其強大的音頻處理技術,為用戶提供了多種音頻降噪功能,幫助用戶在…

【數據可視化-22】脫發因素探索的可視化分析

?? 博主簡介:曾任某智慧城市類企業算法總監,目前在美國市場的物流公司從事高級算法工程師一職,深耕人工智能領域,精通python數據挖掘、可視化、機器學習等,發表過AI相關的專利并多次在AI類比賽中獲獎。CSDN人工智能領域的優質創作者,提供AI相關的技術咨詢、項目開發和個…

青少年編程與數學 02-018 C++數據結構與算法 06課題、樹

青少年編程與數學 02-018 C數據結構與算法 06課題、樹 一、樹(Tree)1. 樹的定義2. 樹的基本術語3. 常見的樹類型4. 樹的主要操作5. 樹的應用 二、二叉樹(Binary Tree)1. 二叉樹的定義2. 二叉樹的基本術語3. 二叉樹的常見類型4. 二叉樹的主要操作5. 二叉樹的實現代碼說明輸出示例…

【論文閱讀】Visual Instruction Tuning

文章目錄 導言1、論文簡介2、論文主要方法3、論文針對的問題4、論文創新點總結 導言 本論文介紹了一個新興的多模態模型——LLaVA(Large Language and Vision Assistant),旨在通過指令調優提升大型語言模型(LLM)在視覺…

【學習筆記】Cadence電子設計全流程(三)Capture CIS 原理圖繪制(下)

【學習筆記】Cadence電子設計全流程(三)Capture CIS 原理圖繪制(下) 3.16 原理圖中元件的編輯與更新3.17 原理圖元件跳轉與查找3.18 原理圖常見錯誤設置于編譯檢查3.19 低版本原理圖文件輸出3.20 原理圖文件的鎖定與解鎖3.21 Orca…

js使用IntersectionObserver實現目標元素可見度的交互

文章目錄 1、前言2、代碼實現3、使用場景4、兼容性5、成熟的Hooks推薦 1、前言 IntersectionObserver 是瀏覽器原生提供的一個Api。可以"觀察"我們的元素是否可見,原理是判斷目標元素與可見區域的交叉比例,所以也被稱為"交叉觀察器"…

linux 中斷子系統 層級中斷編程

虛擬中斷控制器代碼&#xff1a; #include<linux/kernel.h> #include<linux/module.h> #include<linux/clk.h> #include<linux/err.h> #include<linux/init.h> #include<linux/interrupt.h> #include<linux/io.h> #include<linu…

蝦皮(Shopee)商品詳情 API 接口概述及 JSON 數據返回參考

前言 一、接口概述 Shopee 商品詳情 API 接口是 Shopee 平臺為開發者提供的&#xff0c;用于獲取商品詳細信息的接口服務。通過該接口&#xff0c;開發者可以獲取商品的標題、價格、庫存、描述、圖片、規格參數、銷量、評價等詳細信息。這些數據為電商數據分析、商品比價工具…

three.js中的instancedMesh類優化渲染多個同網格材質的模型

three.js小白的學習之路。 在上上一篇博客中&#xff0c;簡單驗證了一下three.js中的網格共享。寫的時候就有一些想法&#xff0c;如果說某個場景中有一萬棵樹&#xff0c;這些樹共享一個geometry和material&#xff0c;有沒有好的辦法將其進行一定程度上的渲染優化&#xff0…

MySQL-自定義函數

自定義函數 函數的作用 mysql數據庫中已經提供了內置的函數&#xff0c;比如&#xff1a;sum&#xff0c;avg&#xff0c;concat等等&#xff0c;方便我們日常的使用&#xff0c;當需要時mysql支持定義自定義的函數&#xff0c;方便與我們對于需用復用的功能進行封裝。 基本…

ESP32上C語言實現JSON對象的創建和解析

在ESP32上使用C語言實現JSON對象的創建和解析&#xff0c;同樣可以借助cJSON庫。ESP-IDF&#xff08;Espressif IoT Development Framework&#xff09;本身已經集成了cJSON庫&#xff0c;你可以直接使用。以下是詳細的步驟和示例代碼。 1. 創建一個新的ESP-IDF項目 首先&…

【FAQ】PCoIP 會話后物理工作站本地顯示器黑屏

# 問題 工作人員從家里建立了到辦公室工作站的 PCoIP 連接&#xff0c;該工作站安裝了 HP Anyware Graphics Agent&#xff0c;并且還連接了本地顯示器。然后&#xff0c;遠程用戶決定去辦公室進行本地工作&#xff0c;工作站顯示器顯示黑屏&#xff08;有時沒有信號&#xff…

el-table 目錄樹列表本地實現模糊查詢

table目錄樹結構實現模糊查詢 <el-form :model"queryParams" ref"queryForm" size"small" :inline"true" v-show"showSearch"><el-form-item label"名稱:" prop"Name"><el-input v-mode…

力扣hot100 LeetCode 熱題 100 Java 哈希篇

兩數之和 1. 兩數之和 - 力扣&#xff08;LeetCode&#xff09; 直接暴力 class Solution {public int[] twoSum(int[] nums, int target) {for(int i0;i<nums.length;i){for(int ji1;j<nums.length;j){long ans nums[i]nums[j];if(ans>target)continue;if(anstarg…

前后端部署

#在學習JavaWeb之后&#xff0c;進行了蒼穹外賣的學習。在進行蒼穹外賣的部署的時候&#xff0c;作者遇到了下面的問題# 1.前端工程nginx無法啟動&#xff1a; 當我雙擊已經部署好的nginx工程中nginx.exe文件的時候&#xff0c;在服務中&#xff0c;并沒有找到ngnix成功運行。…