基於ARM Cortex-A9四核CPU的exynos4412開發板GPIO程式設計案例
阿新 • • 發佈:2019-01-03
GPIO的英文簡稱為General-Purpose IO port,即通用IO介面。介面至少有兩個暫存器,即“通用IO控制暫存器GPxCON”和“通用IO資料暫存器GPxDAT”。在本次程式設計案例中,我們使用的就是以上兩個暫存器,來控制四個LED燈閃爍,實現跑馬燈的功能。
我們通過檢視LED燈的控制電路和exynos-4412手冊,可以得知每個LED的控制暫存器和資料暫存器,我們通過進行設定控制暫存器和資料暫存器的值來實現LED燈的亮滅。
通過檢視LED控制電路圖得知LED2/3/4/5燈分別是由GPX2_7/GPX1_0/GPF3_4/GPF3_5控制的,通過查詢Exynos4412使用者手冊,找到GPIO 這一章中的GPX2暫存器,可以得知
要想GPX2_7有輸出,則需要將控制暫存器GPX2CON 的第28位和31位之間的值設為0x1,且不能修改其他位的值,我們可以使用這樣的程式碼:
GPX2CON = (GPX2CON &(~(0xf<<28)) ) | (0x1<<28);
另外還要有資料暫存器來實現對LED燈亮滅的控制,如下圖
將GPX2DAT的第7位的值設定為0x1時,LED2亮;則GPX2DAT的第7位的值設定為0x0時,LED2滅,由此我們可以得到如下程式碼:
GPX2DAT = GPX2DAT | 0x1<<7;
GPX2DAT = GPX2DAT & (~(0x1<<7)) ;
由於剩下的3個燈的控制方式和LED2相似,因此不再一一進行詳細說明。綜合程式碼如下:
#include "exynos_4412.h" /* GPF3 */ typedef struct { unsigned int CON; unsigned int DAT; unsigned int PUD; unsigned int DRV; unsigned int CONPDN; unsigned int PUDPDN; }gpf3; #define GPF3 (* (volatile gpf3 *)0x114001E0) /* GPX1 */ typedef struct { unsigned int CON; unsigned int DAT; unsigned int PUD; unsigned int DRV; }gpx1; #define GPX1 (* (volatile gpx1 *)0x11000C20 ) /* GPX2 */ typedef struct { unsigned int CON; unsigned int DAT; unsigned int PUD; unsigned int DRV; }gpx2; #define GPX2 (* (volatile gpx2 *)0x11000C40 ) void led_init() //進行控制暫存器的初始化,使控制暫存器相關值設為輸出狀態 { GPX2.CON = (GPX2.CON &(~(0xf<<28))) | (0x1<<28); //對LED2的通用控制暫存器相關位進行設定位輸出 GPX1.CON = (GPX1.CON &(~(0xf<<0))) | (0x1<<0); //對LED3的通用控制暫存器相關位進行設定位輸出 GPF3.CON = (GPF3.CON & ~(0xf<<16 | 0xf<<20)) | (1<<16 | 1<<20); //對LED4和LED5的通用控制暫存器相關位進行設定位輸出 } void led_on(int ledno)//開啟LED燈 { switch(ledno) { case 1: GPX2.DAT = GPX2.DAT | 0x1<<7;//LED2亮 break; case 2: GPX1.DAT = GPX1.DAT | 0x1<<0;//LED3亮 break; case 3: GPF3.DAT = GPF3.DAT | 0x1<<4;//LED4亮 break; case 4: GPF3.DAT = GPF3.DAT | 0x1<<5;//LED5亮 break; } } void led_off(int ledno)//關閉LED燈 { switch(ledno) { case 1: GPX2.DAT = GPX2.DAT & (~(0x1<<7));//LED2滅 break; case 2: GPX1.DAT = GPX1.DAT & (~(0x1<<0));//LED3滅 break; case 3: GPF3.DAT = GPF3.DAT & (~(0x1<<4));//LED4滅 break; case 4: GPF3.DAT = GPF3.DAT & (~(0x1<<5));//LED5滅 break; } } void delay_ms(int num) //由於這是對開發板進行裸機開發,因此沒有延時函式,要自己寫一個 { int i,j; for(i=num; i>0; i--) { for(j=1000; j>0; j--); } } int main(int argc,char **argv) { int i; int ledno; led_init(); for(i=0;i<1000;i++) { ledno = i%4 + 1; //為了實現ledno的值為1,2,3,4迴圈 led_on(ledno); delay_ms(1000); led_off(ledno); } return 0; }