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