基于ARM Cortex-A9四核CPU的exynos4412开发板GPIO编程案例



GPIO的英文简称为General-Purpose IO port通用IO接口。接口至少有两个寄存器,即通用IO控制寄存器GPxCON”通用IO数据寄存器GPxDAT”。在本次编程案例中,我们使用的就是以上两个寄存器,来控制四个LED灯闪烁,实现跑马灯的功能。

我们通过查看LED灯的控制电路和exynos-4412手册,可以得知每个LED的控制寄存器和数据寄存器,我们通过进行设置控制寄存器和数据寄存器的值来实现LED灯的亮灭。

基于ARM Cortex-A9四核CPU的exynos4412开发板GPIO编程案例_第1张图片

通过查看LED控制电路图得知LED2/3/4/5灯分别是由GPX2_7/GPX1_0/GPF3_4/GPF3_5控制的,通过查找Exynos4412用户手册,找到GPIO这一章中的GPX2寄存器,可以得知

基于ARM Cortex-A9四核CPU的exynos4412开发板GPIO编程案例_第2张图片

要想GPX2_7有输出,则需要将控制寄存器GPX2CON 的第28位和31位之间的值设为0x1,且不能修改其他位的值,我们可以使用这样的代码:

GPX2CON  = (GPX2CON &(~(0xf<<28)) )  |  (0x1<<28);

另外还要有数据寄存器来实现对LED灯亮灭的控制,如下图

基于ARM Cortex-A9四核CPU的exynos4412开发板GPIO编程案例_第3张图片

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

 

 

 

 

 

 

 

  

 



你可能感兴趣的:(ARM硬件接口)