1. 程式人生 > >基於ARM Cortex-A9四核CPU的exynos4412開發板GPIO程式設計案例

基於ARM Cortex-A9四核CPU的exynos4412開發板GPIO程式設計案例



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