將上一節搭建的工程複製一份,命名爲「6.key interrupt」。這一節主要講如何使用SAM4N的GPIO中斷功能,實現按鍵的中斷輸入。函數
這個程序主要是在上一個程序中進行改進,實現按鍵的中斷輸入。this
上圖能夠看出按鍵一邊鏈接在PA30上面,一邊鏈接到GND,當按下按鍵時,PA30管腳的電平會被拉低,將按鍵管腳設置成上拉電阻方式,這樣鬆開按鍵時PA30會被拉高。blog
因此要實現按鍵的輸入中斷能夠捕獲PA30的上升沿或是降低沿。ip
#define USER_BUTTON (0x01UL<<30)get
/************************************************************it
*函數名: Key_GPIO_Config()io
*參 數 :voidtest
*返回值:voidcli
*功 能 :按鍵GPIO的初始化函數,使用按鍵前必須先調用此函數進行初始化配置
*************************************************************/
void Key_GPIO_Config(void)
{
/*禁止外設管理控制寄存器(PMC)寫保護*/
PMC->PMC_WPMR = 0x504D4300;
/*使能PIOA時鐘*/
PMC->PMC_PCER0 = (1UL << ID_PIOA);
/*使能外設管理控制寄存器(PMC)寫保護*/
PMC->PMC_WPMR = 0x504D4301;
/*使能USER_BUTTON管腳,對應爲PA30*/
PIOA->PIO_PER=(USER_BUTTON);
/*禁止USER_BUTTON管腳*/
PIOA->PIO_ODR=(USER_BUTTON);
/*使能USER_BUTTON管腳的上拉電阻,設置爲上拉*/
PIOA->PIO_PUER=(USER_BUTTON);
/*使能USER_BUTTON管腳濾波功能*/
PIOA->PIO_IFER=USER_BUTTON;
/*使能USER_BUTTON管腳中斷功能*/
PIOA->PIO_IER=USER_BUTTON;
/*使能USER_BUTTON管腳中斷爲其餘中斷觸發*/
PIOA->PIO_AIMER=USER_BUTTON;
/*使能USER_BUTTON管腳中斷爲邊沿觸發*/
PIOA->PIO_ESR=USER_BUTTON;
/*使能USER_BUTTON管腳中斷爲上降沿觸發*/
PIOA->PIO_REHLSR=USER_BUTTON;
PIOA->PIO_ISR;
/*配置PIOA的先佔優先級爲1,從優先級爲1*/
NVIC_SetPriority(PIOA_IRQn, ((0x01<<3)|0x01));
/*使能PIOA的中斷通道*/
NVIC_EnableIRQ(PIOA_IRQn);
}
第一步,打開PIOA的時鐘,接着使能PIOA30的GPIO功能,而後禁止PIOA30的輸出,只做爲輸入功能,接着使能PIOA30的上拉電阻。第二步,打開PIOA30管腳的濾波功能,這樣能夠起到一個硬件消抖的做用,而後經過PIO_IER寄存器使能PIOA30的中斷功能。默認狀況下中斷會被設置成邊沿觸發,這明顯不是咱們要的,咱們須要的是降低沿觸發或上升沿觸發。SAM4N的GPIO中斷提供邊沿觸發、降低沿觸發、上升沿觸發、低電平觸發、高電平觸發五種類型。除了邊沿觸發爲默認方式外,其餘方式類型須要經過配置。首先配置PIO_AIMER寄存器,使能其餘中斷模式,接着配置PIO_ESR寄存器,使能上升/降低沿觸發方式,最後配置PIO_REHLSR寄存器,配置成上升沿觸發方式,下面是結構圖:
接着須要設置PIOA向量中斷優先級,最後使能PIOA的向量中斷。在PIOA的中斷函數中寫中斷處理程序:
/***************************************************************
* 函數名:PIOA_Handler()
* 參數 :void
* 返回值:void
* 描述 :PIOA管腳中斷服務函數
*************************************************************/
void PIOA_Handler(void)
{
/*檢測是否爲USER_BUTTON引起的中斷*/
if((PIOA->PIO_ISR&USER_BUTTON)!=0)
{
printf("USER_BUTTON按鍵被按下\r\n");
}
}
這裏咱們須要讀取PIOA的PIO_ISR寄存器,判斷是否是PIOA30中斷,讀取中斷寄存器之後,中斷標誌位會自動清除,若是在這裏不讀去這個PIO_ISR,中斷不清楚將會連續觸發,這點須要注意。
在PIOA30中斷後,也是打印按鍵被按下的信息到串口。
在main函數中只要去初始化按鍵便可:
int main(void)
{
systick_hw_init();
led_hw_init();
UART0_Init(115200);
Key_GPIO_Config();
UART0_SendString("this is a key test demo!\r\n");
while(1){
PIOB->PIO_CODR=(0x01<<LED0_PIN);
delay_ms(200);
PIOB->PIO_SODR=(0x01<<LED0_PIN);
delay_ms(200);
}
}
和上一個程序同樣,下載運行,按下按鍵串口會打印出以下信息: