開(kāi)發(fā)環(huán)境:
MDK:Keil 5.30
開(kāi)發(fā)板:GD32F207I-EVAL
MCU:GD32F207IK
1 普通方式
1.1 普通方式工作原理
按鍵 GPIO 端口有兩個(gè)方案可以選擇,一是采用上拉輸入模式,因?yàn)榘存I在沒(méi)按下的時(shí)候,是默認(rèn)為高電平的,采且內(nèi)部上拉模式正好符合這個(gè)要求。第二個(gè)方案是直接采用浮空輸入模式,因?yàn)榘凑?a target="_blank">硬件電路圖,在芯片外部接了上拉電阻,其實(shí)就沒(méi)必要再配置成內(nèi)部上拉輸入模式了,因?yàn)樵谕獠可侠c內(nèi)部上拉效果是一樣的。
筆者本文將會(huì)使用KEY1。
1.2 普通方式實(shí)現(xiàn)
主函數(shù)代碼如下:
/*
brief main function
param[in] none
param[out] none
retval none
*/
int main(void)
{
//systick init
sysTick_init();
/* configure LED1 GPIO port */
led_init(LED1);
/* configure LED2 GPIO port */
led_init(LED2);
/* configure LED3 GPIO port */
led_init(LED3);
/* configure LED4 GPIO port */
led_init(LED4);
//key init
key_init(KEY_WAKEUP);
while(1)
{
delay_ms(100);
if(key_scan(KEY_WAKEUP))
{
/* turn toggle LED */
led_toggle(LED1);
led_toggle(LED2);
led_toggle(LED3);
led_toggle(LED4);
}
}
}
- GPIO 初始化配置
/*
brief configure key
param[in] keynum: specify the key to be configured
arg KEY_TAMPER: tamper key
arg KEY_WAKEUP: wakeup key
arg KEY_USER: user key
param[out] none
retval none
*/
void key_init(key_typedef_enum keynum)
{
/* enable the key clock */
rcu_periph_clock_enable(KEY_CLK[keynum]);
rcu_periph_clock_enable(RCU_AF);
/* configure button pin as input */
gpio_init(KEY_PORT[keynum], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, KEY_PIN[keynum]);
}
key_init()與 LED 的 GPIO 初始化函數(shù) led_init()類(lèi)似,區(qū)別只是在這個(gè)函數(shù)中,要開(kāi)啟的 GPIO 的端口時(shí)鐘不一樣,并且把檢測(cè)按鍵用的引腳 Pin 的模式設(shè)置為適合按鍵應(yīng)用的上拉輸入模式(由于接了外部上拉電阻,也可以使用浮空輸入,讀者可自行修改代碼做實(shí)驗(yàn))。
- 按鍵消抖
/*
brief return the key state
param[in] keynum: specify the key to be checked
arg KEY_TAMPER: tamper key
arg KEY_WAKEUP: wakeup key
arg KEY_USER: user key
param[out] none
retval the key's GPIO pin value
*/
key_state_enum key_scan(key_typedef_enum keynum)
{
/* check whether the button is pressed */
if(RESET == gpio_input_bit_get(KEY_PORT[keynum], KEY_PIN[keynum]))
{
delay_ms(100);
/* check whether the button is pressed */
if(RESET == gpio_input_bit_get(KEY_PORT[keynum], KEY_PIN[keynum]))
{
while(RESET == gpio_input_bit_get(KEY_PORT[keynum], KEY_PIN[keynum]))
{
return KEY_ON;
}
}
}
return KEY_OFF;
}
相信延時(shí)消抖的原理大家在學(xué)習(xí)其他單片機(jī)時(shí)就已經(jīng)了解了,本函數(shù)的功能就是掃描輸入參數(shù)中指定的引腳,檢測(cè)其電平變化,并作延時(shí)消抖處理,最終對(duì)按鍵消息進(jìn)行確認(rèn)。
- 利用 gpio_input_bit_get() 讀取輸入數(shù)據(jù),若從相應(yīng)引腳讀取的數(shù)據(jù)等于 0(KEY_ON),低電平,表明可能有按鍵按下,調(diào)用延時(shí)函數(shù)。否則返回 KEY_OFF,表示按鍵沒(méi)有被按下。
- 延時(shí)之后再次利用 gpio_input_bit_get()讀取輸入數(shù)據(jù),若依然為低電平,表明確實(shí)有按鍵被按下了。否則返回 KEY_OFF,表示按鍵沒(méi)有被按下。
- 循環(huán)調(diào)用gpio_input_bit_get() 一直檢測(cè)按鍵的電平,直至按鍵被釋放,被釋放后,返回表示按鍵被按下的標(biāo)志 KEY_ON。以上是按鍵消抖的流程,調(diào)用了一個(gè)庫(kù)函數(shù) gpio_input_bit_get()。輸入?yún)?shù)為要讀取的端口、引腳,返回引腳的輸入電平狀態(tài),高電平為 1,低電平為 0。
2 EXTI方式
2.1 EXTI的工作原理
EXTI(External Interrupt) 就是指外部中斷,通過(guò) GPIO 檢測(cè)輸入脈沖,引起中斷事件,打斷原來(lái)的代碼執(zhí)行流程,進(jìn)入到中斷服務(wù)函數(shù)中進(jìn)行處理,處理完后再返回到中斷之前的代碼中執(zhí)行。
- GD32的中斷和異常
Cortex內(nèi)核具有強(qiáng)大的異常響應(yīng)系統(tǒng),它把能夠打斷當(dāng)前代碼執(zhí)行流程的事件分為異常(exception)和中斷(interrupt),并把它們用一個(gè)表管理起來(lái),編號(hào)為 0 ~ 15 的稱(chēng)為內(nèi)核異常,而 16 以上的則稱(chēng)為外部中斷(外是相對(duì)內(nèi)核而言),這個(gè)表就稱(chēng)為中斷向量表。
而 GD32 對(duì)這個(gè)表重新進(jìn)行了編排,把編號(hào)從-3 至 6 的中斷向量定義為系統(tǒng)異常,編號(hào)為負(fù)的內(nèi)核異常不能被設(shè)置優(yōu)先級(jí),如復(fù)位(Reset)、不可屏蔽中斷 (NMI)、硬錯(cuò)誤(Hardfault)。從編號(hào) 7 開(kāi)始的為外部中斷,這些中斷的優(yōu)先級(jí)都是可以自行設(shè)置的。詳細(xì)的 GD32中斷向量表見(jiàn)下表。
……
完整向量表請(qǐng)參考《GD32F20x_User_Manual_EN_Rev2.4》。
- NVIC 中斷控制器
GD32的中斷如此之多,配置起來(lái)并不容易,因此我們需要一個(gè)強(qiáng)大而方便的中斷控制器 NVIC (Nested Vectored Interrupt Controller)。NVIC 是屬于 Cortex 內(nèi)核的器件,不可屏蔽中斷 (NMI)和外部中斷都由它來(lái)處理,而 SYSTICK 不是由 NVIC 來(lái)控制的。
- NVIC 結(jié)構(gòu)體成員
當(dāng)我們要使用 NVIC 來(lái)配置中斷時(shí),自然想到GD庫(kù)肯定也已經(jīng)把它封裝成庫(kù)函數(shù)了。查找?guī)鞄椭臋n,發(fā)現(xiàn)在 gd32f20x_misc查找到一個(gè)nvic_irq_enable() 函數(shù)。
/*!
\\brief enable NVIC request
\\param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type
\\param[in] nvic_irq_pre_priority: the pre-emption priority needed to set
\\param[in] nvic_irq_sub_priority: the subpriority needed to set
\\param[out] none
\\retval none
*/
void nvic_irq_enable(uint8_t nvic_irq,
uint8_t nvic_irq_pre_priority,
uint8_t nvic_irq_sub_priority)
{
uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U;
/* use the priority group value to get the temp_pre and the temp_sub */
switch((SCB->AIRCR) & (uint32_t)0x700U) {
case NVIC_PRIGROUP_PRE0_SUB4:
temp_pre = 0U;
temp_sub = 0x4U;
break;
case NVIC_PRIGROUP_PRE1_SUB3:
temp_pre = 1U;
temp_sub = 0x3U;
break;
case NVIC_PRIGROUP_PRE2_SUB2:
temp_pre = 2U;
temp_sub = 0x2U;
break;
case NVIC_PRIGROUP_PRE3_SUB1:
temp_pre = 3U;
temp_sub = 0x1U;
break;
case NVIC_PRIGROUP_PRE4_SUB0:
temp_pre = 4U;
temp_sub = 0x0U;
break;
default:
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
temp_pre = 2U;
temp_sub = 0x2U;
break;
}
/* get the temp_priority to fill the NVIC->IP register */
temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre);
temp_priority |= nvic_irq_sub_priority & (0x0FU >> (0x4U - temp_sub));
temp_priority = temp_priority << 0x04U;
NVIC->IP[nvic_irq] = (uint8_t)temp_priority;
/* enable the selected IRQ */
NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU);
}
該函數(shù)有三個(gè)參數(shù),需要配置的中斷向量,中斷向量搶占優(yōu)先級(jí)和中斷向量的響應(yīng)優(yōu)先級(jí)。
前面兩個(gè)結(jié)構(gòu)體成員都很好理解,首先要用 nvic_irq參數(shù)來(lái)選擇將要配置的中斷向量。用nvic_irq_pre_priority參數(shù)要配置中斷向量的搶占優(yōu)先級(jí),用nvic_irq_sub_priority參數(shù)配置中斷向量的響應(yīng)優(yōu)先級(jí)。對(duì)于中斷的配置,最重要的便是配置其優(yōu)先級(jí),但 GD32 的同一個(gè)中斷向量為什么需要設(shè)置兩種優(yōu)先級(jí)?這兩種優(yōu)先級(jí)有什么區(qū)別?
- 搶占優(yōu)先級(jí)和響應(yīng)優(yōu)先級(jí)
GD32的中斷向量具有兩個(gè)屬性,一個(gè)為搶占屬性,另一個(gè)為響應(yīng)屬性,其屬性編號(hào)越小,表明它的優(yōu)先級(jí)別越高。
搶占,是指打斷其他中斷的屬性,即因?yàn)榫哂羞@個(gè)屬性會(huì)出現(xiàn)嵌套中斷(在執(zhí)行中斷服務(wù)函數(shù) A 的過(guò)程中被中斷 B 打斷,執(zhí)行完中斷服務(wù)函數(shù) B 再繼續(xù)執(zhí)行中斷服務(wù)函數(shù)A),搶占屬性由nvic_irq_pre_priority參數(shù)配置。
而響應(yīng)屬性則應(yīng)用在搶占屬性相同的情況下,當(dāng) 兩個(gè)中斷向量的搶占優(yōu)先級(jí)相同時(shí),如 果兩個(gè)中斷同時(shí)到達(dá),則先處理響應(yīng)優(yōu)先級(jí)高的中斷,響應(yīng)屬性 由nvic_irq_sub_priority參數(shù)配置。例如,現(xiàn)在有三個(gè)中斷向量,見(jiàn)下表。
中斷向量 | 搶占優(yōu)先級(jí) | 響應(yīng)優(yōu)先級(jí) |
---|---|---|
A | 0 | 0 |
B | 1 | 0 |
C | 1 | 1 |
若內(nèi)核正在執(zhí)行 C 的中斷服務(wù)函數(shù),則它能被搶占優(yōu)先級(jí)更高的中斷 A 打斷,由于 B和 C 的搶占優(yōu)先級(jí)相同,所以 C 不能被 B 打斷。但如果 B 和 C 中斷是同時(shí)到達(dá)的,內(nèi)核就會(huì)首先響應(yīng)響應(yīng)優(yōu)先級(jí)別更高的 B 中斷。
- NVIC 的優(yōu)先級(jí)組
在配置優(yōu)先級(jí)的時(shí)候,還要注意一個(gè)很重要的問(wèn)題,即中斷種類(lèi)的數(shù)量。NVIC 只可以配置 16 種中斷向量的優(yōu)先級(jí),也就是說(shuō),搶占優(yōu)先級(jí)和響應(yīng)優(yōu)先級(jí)的數(shù)量由一個(gè) 4 位的數(shù)字來(lái)決定,把這個(gè) 4 位數(shù)字的位數(shù)分配成搶占優(yōu)先級(jí)部分和響應(yīng)優(yōu)先級(jí)部分。有 5 組分配方式 :
- 第 0 組:所有 4 位用來(lái)配置響應(yīng)優(yōu)先級(jí)。即 16 種中斷向量具有都不相同的響應(yīng)優(yōu)先級(jí)。
- 第 1 組:最高 1 位用來(lái)配置搶占優(yōu)先級(jí),低 3 位用來(lái)配置響應(yīng)優(yōu)先級(jí)。表示有 21=2 種級(jí)別的搶占優(yōu)先級(jí)(0 級(jí),1 級(jí)),有 23=8 種響應(yīng)優(yōu)先級(jí),即在 16 種中斷向量之中,有8 種中斷,其搶占優(yōu)先級(jí)都為 0 級(jí),而它們的響應(yīng)優(yōu)先級(jí)分別為 0~7,其余 8 種中斷向量的搶占優(yōu)先級(jí)則都為 1 級(jí),響應(yīng)優(yōu)先級(jí)別分別為 0~7。
- 第 2 組:2 位用來(lái)配置搶占優(yōu)先級(jí),2 位用來(lái)配置響應(yīng)優(yōu)先級(jí)。即 22=4 種搶占優(yōu)先級(jí),22=4 種響應(yīng)優(yōu)先級(jí)。
- 第 3 組:高 3 位用來(lái)配置搶占優(yōu)先級(jí),最低 1 位用來(lái)配置響應(yīng)優(yōu)先級(jí)。即有 8 種搶占優(yōu)先級(jí),2 種響應(yīng) 2 優(yōu)先級(jí)。
- 第 4 組:所有 4 位用來(lái)配置搶占優(yōu)先級(jí),即 NVIC 配置的 24 =16 種中斷向量都是只有搶占屬性,沒(méi)有響應(yīng)屬性。
要配置這些優(yōu)先級(jí)組,可以采用庫(kù)函數(shù) nvic_priority_group_set(),可輸入的參數(shù)為NVIC_PRIGROUP_PRE0_SUB4 ~ NVIC_PRIGROUP_PRE4_SUB0,分別為以上介紹的 5 種分配組。
GD32的所有 I/O 端口都可以配置為 EXTI 中斷模式,用來(lái)捕捉外部信號(hào),可以配置為下降沿中斷、上升沿中斷和上升下降沿中斷這三種模式。它們以圖2所示方式連接到外部中斷 / 事件線上。
- EXTI 外部中斷
GD32的所有 GPIO 都引入到 EXTI 外部中斷線上,使得所有的 GPIO 都能作為外部中斷的輸入源。GPIO 與 EXTI 的連接方式見(jiàn)下表。
由下表可知,PA0 ~ PI0 連接到 EXTI0 、PA1~ PI1 連接到 EXTI1、……、PA15 ~ PI15 連接到 EXTI15。這里大家要注意的是 :PAx ~ PIx 端口的中斷事件都連接到了 EXTIx,即同一時(shí)刻 EXTIx 只能響應(yīng)一個(gè)端口的事件觸發(fā),不能夠同一時(shí)間響應(yīng)所有GPIO 端口的事件,但可以分時(shí)復(fù)用。它可以配置為上升沿觸發(fā)、下降沿觸發(fā)或雙邊沿觸發(fā)。EXTI 最普通的應(yīng)用就是接上一個(gè)按鍵,設(shè)置為下降沿觸發(fā),用中斷來(lái)檢測(cè)按鍵。
2.2 2 EXTI的寄存器描述
EXTI 寄存器的寄存器主要有6個(gè),下面分別描述。
- 中斷使能寄存器(EXTI_INTEN)
- 事件使能寄存器(EXTI_EVEN)
- 上升沿觸發(fā)選擇寄存器(EXTI_RTEN)
注意: 外部喚醒線是邊沿觸發(fā)的,這些線上不能出現(xiàn)毛刺信號(hào)。在寫(xiě)EXTI_RTSR寄存器時(shí),在外部中斷線上的上升沿信號(hào)不能被識(shí)別,掛起位也不會(huì)被置位。在同一中斷線上,可以同時(shí)設(shè)置上升沿和下降沿觸發(fā)。即任一邊沿都可觸發(fā)中斷。
- 下降沿觸發(fā)選擇寄存器(EXTI_FTEN)
注意: 外部喚醒線是邊沿觸發(fā)的,這些線上不能出現(xiàn)毛刺信號(hào)。在寫(xiě)EXTI_FTSR寄存器時(shí),在外部中斷線上的下降沿信號(hào)不能被識(shí)別,掛起位不會(huì)被置位。在同一中斷線上,可以同時(shí)設(shè)置上升沿和下降沿觸發(fā)。即任一邊沿都可觸發(fā)中斷。
- 軟件中斷事件寄存器(EXTI_SWIEV)
- 掛起寄存器(EXTI_PD)
2.3 EXTI方式實(shí)現(xiàn)
主函數(shù)代碼如下:
/*
brief main function
param[in] none
param[out] none
retval none
*/
int main(void)
{
//systick init
sysTick_init();
/* configure LED1 GPIO port */
led_init(LED1);
/* configure LED2 GPIO port */
led_init(LED2);
/* configure LED3 GPIO port */
led_init(LED3);
/* configure LED4 GPIO port */
led_init(LED4);
//key init
key_init(KEY_WAKEUP, KEY_MODE_EXTI);
while(1)
{
delay_ms(100);
}
}
- 配置外部中斷
現(xiàn)在我們重點(diǎn)分析 key_init() 這個(gè)函數(shù),它完成了配置一個(gè) I/O 為 EXTI 中斷的一般步驟,主要有以下功能 :
1)使能 EXTIx 線的時(shí)鐘和第二功能 AFIO 時(shí)鐘。
2)配置 EXTIx 線的中斷優(yōu)先級(jí)。
3)配置 EXTI 中斷線 I/O。
4)選定要配置為 EXTI 的 I/O 口線和 I/O 口的工作模式。
5)EXTI 中斷線工作模式配置。
/*
brief configure key
param[in] keynum: specify the key to be configured
arg KEY_TAMPER: tamper key
arg KEY_WAKEUP: wakeup key
arg KEY_USER: user key
param[in] keymode: specify button mode
arg KEY_MODE_GPIO: key will be used as simple IO
arg KEY_MODE_EXTI: key will be connected to EXTI line with interrupt
param[out] none
retval none
*/
void key_init(key_typedef_enum keynum, keymode_typedef_enum keymode)
{
/* enable the key clock */
rcu_periph_clock_enable(KEY_CLK[keynum]);
rcu_periph_clock_enable(RCU_AF);
/* configure button pin as input */
gpio_init(KEY_PORT[keynum], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, KEY_PIN[keynum]);
if (keymode == KEY_MODE_EXTI)
{
/* enable and set key EXTI interrupt to the lowest priority */
nvic_irq_enable(KEY_IRQn[keynum], 2U, 0U);
/* connect key EXTI line to key GPIO pin */
gpio_exti_source_select(KEY_PORT_SOURCE[keynum], KEY_PIN_SOURCE[keynum]);
/* configure key EXTI line */
exti_init(KEY_EXTI_LINE[keynum], EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(KEY_EXTI_LINE[keynum]);
}
}
key_init()代碼中,不僅配置了NVIC ,還對(duì)按鍵的GPIO進(jìn)行了初始化,這部分和按鍵輪詢的設(shè)置類(lèi)似。
接下來(lái),調(diào)用 gpio_exti_source_select () 函數(shù)把 GPIOA、Pin0 與EXTI連接起來(lái)。
最后調(diào)用 exti_init() 把 EXTI 初始化,函數(shù)如下:
/*!
\\brief initialize the EXTI
\\param[in] linex: EXTI line number, refer to exti_line_enum
only one parameter can be selected which is shown as below:
\\arg EXTI_x (x=0..19): EXTI line x
\\param[in] mode: interrupt or event mode, refer to exti_mode_enum
only one parameter can be selected which is shown as below:
\\arg EXTI_INTERRUPT: interrupt mode
\\arg EXTI_EVENT: event mode
\\param[in] trig_type: interrupt trigger type, refer to exti_trig_type_enum
only one parameter can be selected which is shown as below:
\\arg EXTI_TRIG_RISING: rising edge trigger
\\arg EXTI_TRIG_FALLING: falling trigger
\\arg EXTI_TRIG_BOTH: rising and falling trigger
\\arg EXTI_TRIG_NONE: without rising edge or falling edge trigger
\\param[out] none
\\retval none
*/
void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type)
{
/* reset the EXTI line x */
EXTI_INTEN &= ~(uint32_t)linex;
EXTI_EVEN &= ~(uint32_t)linex;
EXTI_RTEN &= ~(uint32_t)linex;
EXTI_FTEN &= ~(uint32_t)linex;
/* set the EXTI mode and enable the interrupts or events from EXTI line x */
switch(mode) {
case EXTI_INTERRUPT:
EXTI_INTEN |= (uint32_t)linex;
break;
case EXTI_EVENT:
EXTI_EVEN |= (uint32_t)linex;
break;
default:
break;
}
/* set the EXTI trigger type */
switch(trig_type) {
case EXTI_TRIG_RISING:
EXTI_RTEN |= (uint32_t)linex;
EXTI_FTEN &= ~(uint32_t)linex;
break;
case EXTI_TRIG_FALLING:
EXTI_RTEN &= ~(uint32_t)linex;
EXTI_FTEN |= (uint32_t)linex;
break;
case EXTI_TRIG_BOTH:
EXTI_RTEN |= (uint32_t)linex;
EXTI_FTEN |= (uint32_t)linex;
break;
case EXTI_TRIG_NONE:
default:
break;
}
}
- AFIO 時(shí)鐘
代碼中調(diào)用rcu_periph_clock_enable(RCU_AF)表示開(kāi)啟 AFIO的時(shí)鐘。
AFIO (alternate-function I/O),指 GPIO 端口的復(fù)用功能,GPIO 除了用作普通的輸入輸出(主功能),還可以作為片上外設(shè)的復(fù)用輸入輸出,如串口、ADC,這些就是復(fù)用功能。大多數(shù) GPIO 都有一個(gè)默認(rèn)復(fù)用功能,有的 GPIO 還有重映射功能。重映射功能是指把原來(lái)屬于 A 引腳的默認(rèn)復(fù)用功能,轉(zhuǎn)移到B引腳進(jìn)行使用,前提是 B 引腳具有這個(gè)重映射功能。
當(dāng)把 GPIO 用作 EXTI 外部中斷或使用重映射功能的時(shí)候,必須開(kāi)啟 AFIO 時(shí)鐘,而在使用默認(rèn)復(fù)用功能的時(shí)候,就不必開(kāi)啟 AFIO 時(shí)鐘了。
- 編寫(xiě)中斷服務(wù)函數(shù)
在這個(gè) EXTI 設(shè)置中我們把 PA0 連接到內(nèi)部的 EXTI0,GPIO 配置為上拉輸入,工作在下降沿中斷。在外圍電路上我們將 PA0 接到了 key上。當(dāng)按鍵沒(méi)有按下時(shí),PA0 始終為高,當(dāng)按鍵按下時(shí) PA0 變?yōu)榈?,從?PA0 上產(chǎn)生一個(gè)下降沿跳變,EXTI0 會(huì)捕捉到這一跳變,并產(chǎn)生相應(yīng)的中斷,中斷服務(wù)程序在 gd32f20x_it.c 中實(shí)現(xiàn)。gd32f20x_it.c 文件是專(zhuān)門(mén)用來(lái)存放中斷服務(wù)函數(shù)的。文件中默認(rèn)只有幾個(gè)關(guān)于系統(tǒng)異常的中斷服務(wù)函數(shù),而且都是空函數(shù),在需要的時(shí)候自行編寫(xiě)。那么中斷服務(wù)函數(shù)名是不是可以自己定義呢?不可以。中斷服務(wù)函數(shù)的名字必須要與啟動(dòng)文件startup_gd32f20x_cl.s 中的中斷向量表定義一致。
EXTI0_IRQHandler 表示為 EXTI0 中斷向量的服務(wù)函數(shù)名。于是,我們就可以在 gd32f20x_it.c文件中加入名為 EXTI0_IRQHandler() 的函數(shù)。
/*!
\\brief this function handles external lines 0 interrupt request
\\param[in] none
\\param[out] none
\\retval none
*/
void EXTI0_IRQHandler(void)
{
if(RESET != exti_interrupt_flag_get(EXTI_0))
{
/* turn toggle LED */
led_toggle(LED1);
led_toggle(LED2);
led_toggle(LED3);
led_toggle(LED4);
exti_interrupt_flag_clear(EXTI_0);
}
}
其內(nèi)容比較容易理解,進(jìn)入中斷后,調(diào)用exti_interrupt_flag_get() 庫(kù)函數(shù)來(lái)重新檢查是否產(chǎn)生了 EXTI_Line 中斷,接下來(lái)把 LED 取反,操作完畢后,調(diào)用 exti_interrupt_flag_clear()清除中斷標(biāo)志位再退出中斷服務(wù)函數(shù)。
3 實(shí)驗(yàn)現(xiàn)象
編譯好程序后,下載到板子上,不管是普通方式還是中斷方式,當(dāng)按在按鍵KEY1時(shí),LED或亮或滅。
-
mcu
+關(guān)注
關(guān)注
146文章
17123瀏覽量
350973 -
按鍵
+關(guān)注
關(guān)注
4文章
223瀏覽量
57595 -
開(kāi)發(fā)板
+關(guān)注
關(guān)注
25文章
5032瀏覽量
97371 -
Cortex-M
+關(guān)注
關(guān)注
2文章
229瀏覽量
29752 -
GD32
+關(guān)注
關(guān)注
7文章
403瀏覽量
24326
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論