第4章 S5PV210微处理器GPIO编程
1. S5PV210芯片共有584引脚,其中237个输入/输出引脚,分属于多个I/O端口。所有I/O端口均为多功能端口,功能可以编程设置,分别是:
GPA0:8线输入/输出 端口 ,或2×UART 带流控制端口;
GPA1:5线输入/输出端口,或2×UART 不带流控或1×UART带流控端口;
GPB:8线输入/输出端口,或2×SPI端口;
GPC0:5线输入/输出端口,或I2S、PCM、AC97端口;
GPC1:5线输入/输出端口,或I2S、SPDIF、LCD_FRM端口;
GPD0:4线输入/输出端口,或PWM端口;
GPD1:6线输入/输出端口,或3×I2C、PWM、IEM端口;
GPE0,1:13线输入/输出端口,或Camera I/F端口;
GPF0,1,2,3:30线输入/输出端口,或LCD I/F端口;
GPG0,1,2,3:28线输入/输出端口,或4×MMC 通道端口;
GPH0,1,2,3:32线输入/输出端口,或键盘及最大32位睡眠可唤醒接口
GPI:低功率I2S、PCM,或AUDIO_SS PDN寄存器控制PDN 掉电配置端口;
GPJ0,1,2,3,4:35线输入/输出端口,或Modem IF、CAMIF、CFCON、KEYPAD、SROM ADDR[22:16] 端口;
MP0_1,2,3:20线输入/输出端口,或EBI(SROM、NF、OneNAND)控制信号口;
MP0_4,5,6,7:32线输入/输出内存端口,或EBI端口;
MP1_0-8:71线DRAM1 端口;
MP2_0-8:71 线DRAM2 端口;
ETC0, ETC1, ETC2, ETC4:28线输入/输出ETC 端口,或JTAG端口等
2. 每个端口均有3个寄存器用于控制其操作,一个是端口控制寄存器,用于设置其每个引脚的功能;一个是数据寄存器,用于作为普通输入/输出功能时的数据存储器;再一个是上拉控制寄存器,控制该端口的引脚是否需要接上拉电阻。
例如:
GPA0CON:端口控制寄存器,每4位定义一位管脚功能。
0000-输入;0001-输出;1111-GPA0_INT;其余保留。
GPA0DAT:数据寄存器。
当端口设置为输入端口时,相应的位是引脚状态。当端口设置为 输出端口 时,引脚状态与相应的位相同
GPA0UP:端口上拉寄存器。
端口上拉寄存器控制了每个端口组的上拉电阻的允许/禁止。如果某一位为0,相应的上拉电阻被允许;如果某一位为1,相应的上拉电阻被禁止。如果端口的上拉电阻被允许,无论在哪种状态下(输入、输出、DATAn、EINTn等),上拉电阻都起作用
3. 编程实例
通过GPD0_0管脚连接蜂鸣器,并通过GPH2_0/1/2/3管脚连接4只独立按键,通过GPJ2_0/1/2/3管脚连接LED等。对S5PV210的GPIO口进行编程,用查询方式获取按键状态,当按键按下时,对应的LED灯闪亮,蜂鸣器鸣响一声。当按键松开,对应的LED灯熄灭。
为了达到读取按键及控制蜂鸣器的目的,需要通过配置GPD0CON寄存器将GPD0_0管脚配置为输出方式,LED灯控制引脚寄存器GPJ2CON配置为GPJ2_0/1/2/3引脚为输出功能,将按键输入引脚寄存器GPH2CON使GPH2_0/1/2/3引脚为输入功能。
#define GPD0CON (*(volatile unsigned long *)0xE02000A0)
#define GPD0DAT (*(volatile unsigned long *)0xE02000A4)
// 初始化buzzer
void buzzer_init(void)
{
GPD0CON |= 1<<0;
}
void buzzer_on(void)
{
GPD0DAT |= 1<<0;
}
void buzzer_off(void)
{
GPD0DAT &= ~(1<<0);
}
// LED
#define GPJ2CON (*(volatile unsigned long *) 0xE0200280)
#define GPJ2DAT (*(volatile unsigned long *) 0xE0200284)
// KEY
#define GPH2CON (*(volatile unsigned long *) 0xE0200C40)
#define GPH2DAT (*(volatile unsigned long *) 0xE0200C44)
//灯输出与按键输入
#define GPJ2_0_OUTPUT (1<<(0*4))
#define GPJ2_1_OUTPUT (1<<(1*4))
#define GPJ2_2_OUTPUT (1<<(2*4))
#define GPJ2_3_OUTPUT (1<<(3*4))
#define GPH2_0_INTPUT ~(0xf<<(0*4))
#define GPH2_1_INTPUT ~(0xf<<(1*4))
#define GPH2_2_INTPUT ~(0xf<<(2*4))
#define GPH2_3_INTPUT ~(0xf<<(3*4))
void main()
{ unsigned long dat;
// LED:设置寄存器GPJ2CON0使GPJ2_0/1/2/3引脚为输出功能
GPJ2CON = GPJ2_0_OUTPUT|GPJ2_1_OUTPUT|GPJ2_2_OUTPUT|GPJ2_3_OUTPUT;
// KEY:设置寄存器GPH2CON0使GPH2_0/1/2/3引脚为输入功能
GPH2CON =GPH2_0_INTPUT&GPH2_1_INTPUT&GPH2_2_INTPUT&GPH2_3_INTPUT;
buzzer_init();
while(1) {
// 读取KEY相关的引脚值,用于判断KEY是否被按下
dat = GPH2DAT;
// 判断KEY1:GPH2_0
if(dat & (1<<0)) // KEY1被按下,则LED1亮,否则LED1灭
{ GPJ2DAT |= 1<<0; // OFF
buzzer_off();
}
else
{ GPJ2DAT &= ~(1<<0); // ON
buzzer_on();
delay(0x10000);
}
// 判断KEY2:GPH2_1
if(dat & (1<<1)) // KEY2被按下,则LED2亮,否则LED2灭
{ GPJ2DAT |= 1<<1; buzzer_off(); }
else
{ GPJ2DAT &= ~(1<<1); buzzer_on(); delay(0x10000); }
// 判断KEY3:GPH2_2
if(dat & (1<<2)) // KEY3被按下,则LED3亮,否则LED3灭
{ …… }
else
{ …… }
// 判断KEY4:GPH2_3
if(dat & (1<<3)) // KEY4被按下,则LED4亮,否则LED4灭
{ …… }
else
{ …… }
} //End of while(1)
} //End of main()