IT8502中各个引脚的描述见下表所示:
在嵌入式控制器EC的IT8502主控芯片中,通过芯片的数据手册可以得知,总共有10组GPIO,其中有7组GPIO中分别包含8个引脚,其他3组引脚分别包含4、7和6个引脚(在GPG[6,2:0]有4个引脚,GPH[6:0]中有7个引脚,在GPJ[5:0]中有6个引脚),引脚总数为73(8*7+7+6)。
接下来介绍GPIO中各个相关寄存器的作用和配置。
寄存器对应地址:
#define GCR (*(XBYTE *)0x1600)
#define GPIOA (*(XBYTE *)0x1601)
#define GPIOB (*(XBYTE *)0x1602)
#define GPIOC (*(XBYTE *)0x1603)
#define GPIOD (*(XBYTE *)0x1604)
#define GPIOE (*(XBYTE *)0x1605)
#define GPIOF (*(XBYTE *)0x1606)
#define GPIOG (*(XBYTE *)0x1607)
#define GPIOH (*(XBYTE *)0x1608)
#define GPIOI (*(XBYTE *)0x1609)
#define GPIOJ (*(XBYTE *)0x160A)
#define GPIOK (*(XBYTE *)0x160B)
#define GPIOL (*(XBYTE *)0x160C)
#define GPIOM (*(XBYTE *)0x160D)
1.General Control Register (GCR),通用控制寄存器,地址0x160
这个寄存器只需要配置GCR[2-1],用于配置LPC复位使能与否,一般默认配置为失能LPC复位,即&GCR=0x06;
2.GPDRA—GPDRJ端口数据寄存器组(共10组)
配置该寄存器可以直接对输出引脚输出对应的高低电平,例如后面的代码中&GPIOA=0xF7,0xF7=0b11110111,意思是在GPIOA这组的8个引脚的第三个引脚输出低电平(如果配置为输出模式),其他七个引脚输出高电平(如果配置为输出模式)。其他几组GPIO原理相同。
3.Port Control n Registers (GPCRn, n = A0-I7),端口控制寄存器
在IT8502芯片中,有73个可用的GPIO,每个GPIO端口都有一个对应的端口控制寄存器用来配置端口的工作方式。
以GPCRAn为例来介绍GPCR的用法,大部分引脚的默认工作方式是GPI模式,也就是输入模式。
Bit7、Bit6用于配置端口引脚的模式,共三种,如下所示:
- 00b,端口配置为复用功能
- 01b,端口配置为输出模式
- 10b,端口配置为输入模式
Bit5,Bit4,Bit3用于配置端口引脚的驱动能力
- 000b,4mA驱动电流
- 001b,8mA驱动电流
- 010b,8mA驱动电流
- 011b,12mA驱动电流
- 110b,16mA驱动电流
- 111b,16mA驱动电流
Bit2用于配置端口引脚的上拉,高电平使能
Bit1用于配置端口引脚的下拉,高电平使能
端口控制寄存器配置示例代码
#define PALT 0x00
#define INPUT 0x80
#define OUTPUT 0x40
#define PULL_UP 0x04
#define PULL_DN 0x02
#define Driving4mA 0x00
#define Driving8mA 0x10
#define Driving12mA 0x18
#define MaxDriving 0x38
4.GPIO端口编程指导
编程步骤
- 配置各个端口相关寄存器的初始值(配置asInitGPIOReg)
- 使用各个端口相关寄存器的初始值配置GPIO端口的工作方式(Reset_Initialization()—》Init_GPIO())
- 在主循环中操作相关端口
端口初始化
InitGPIOReg数据结构,该数据结构用于保存端口初始化相关寄存器初始值的保存。
typedef struct InitGPIOReg
{
XBYTE *reg;
BYTE value;
} sInitGPIOReg;
使用InitGPIOReg数据结构初始化所有端口默认工作模式
const sInitGPIOReg code asInitGPIOReg[] =
{
{ &GCR, 0x06 },
{ &GPIOA, 0xF7 },
{ &GPIO_A0_CTRL, OUTPUT+PULL_UP },
{ &GPIO_A1_CTRL, INPUT },
{ &GPIO_A2_CTRL, OUTPUT+PULL_UP },
{ &GPIO_A3_CTRL, OUTPUT+PULL_UP },
{ &GPIO_A4_CTRL, OUTPUT+PULL_UP },
{ &GPIO_A5_CTRL, OUTPUT+PULL_UP },
{ &GPIO_A6_CTRL, OUTPUT+PULL_UP },
{ &GPIO_A7_CTRL, OUTPUT+PULL_UP },
{ &GPIOB, 0xF8 },
{ &GPIO_B0_CTRL, INPUT },
{ &GPIO_B1_CTRL, INPUT },
{ &GPIO_B2_CTRL, OUTPUT },
{ &GPIO_B3_CTRL, PALT+PULL_UP },
{ &GPIO_B4_CTRL, PALT+PULL_UP },
{ &GPIO_B5_CTRL, OUTPUT+PULL_UP },
{ &GPIO_B6_CTRL, OUTPUT+PULL_UP },
{ &GPIO_B7_CTRL, OUTPUT+PULL_UP },
{ &GPIOC, 0x00 },
{ &GPIO_C0_CTRL, OUTPUT+PULL_UP },
{ &GPIO_C1_CTRL, PALT+PULL_UP },
{ &GPIO_C2_CTRL, PALT+PULL_UP },
{ &GPIO_C3_CTRL, PALT+PULL_UP },
{ &GPIO_C4_CTRL, OUTPUT+PULL_UP },
{ &GPIO_C5_CTRL, OUTPUT },
{ &GPIO_C6_CTRL, INPUT+PULL_UP },
{ &GPIO_C7_CTRL, INPUT+PULL_UP },
{ &GPIOD, 0x5C },
{ &GPIO_D0_CTRL, INPUT },
{ &GPIO_D1_CTRL, INPUT+PULL_UP },
{ &GPIO_D2_CTRL, INPUT+PULL_UP },
{ &GPIO_D3_CTRL, OUTPUT },
{ &GPIO_D4_CTRL, OUTPUT+PULL_UP },
{ &GPIO_D5_CTRL, INPUT+PULL_UP },
{ &GPIO_D6_CTRL, OUTPUT+PULL_UP },
{ &GPIO_D7_CTRL, PALT },
{ &GPIOE, 0x04 },
{ &GPIO_E0_CTRL, OUTPUT+PULL_UP },
{ &GPIO_E1_CTRL, INPUT+PULL_DN },
{ &GPIO_E2_CTRL, OUTPUT+PULL_UP },
{ &GPIO_E3_CTRL, OUTPUT+PULL_UP },
{ &GPIO_E4_CTRL, INPUT+PULL_UP },
{ &GPIO_E5_CTRL, OUTPUT+PULL_UP },
{ &GPIO_E6_CTRL, INPUT+PULL_DN },
{ &GPIO_E7_CTRL, PALT },
{ &GPIOF, 0x40 },
{ &GPIO_F0_CTRL, PALT },
{ &GPIO_F1_CTRL, PALT },
{ &GPIO_F2_CTRL, OUTPUT+PULL_UP },
{ &GPIO_F3_CTRL, INPUT+PULL_UP },
{ &GPIO_F4_CTRL, INPUT },
{ &GPIO_F5_CTRL, OUTPUT+PULL_UP },
{ &GPIO_F6_CTRL, OUTPUT+PULL_UP },
{ &GPIO_F7_CTRL, OUTPUT+PULL_UP },
{ &GPIOG, 0x02 },
{ &GPIO_G0_CTRL, PALT },
{ &GPIO_G1_CTRL, OUTPUT+PULL_UP },
{ &GPIO_G2_CTRL, INPUT },
{ &GPIO_G3_CTRL, PALT },
{ &GPIO_G4_CTRL, PALT },
{ &GPIO_G5_CTRL, PALT },
{ &GPIO_G6_CTRL, INPUT },
{ &GPIO_G7_CTRL, PALT },
{ &GPIOH, 0x01 },
{ &GPIO_H0_CTRL, OUTPUT+PULL_UP },
{ &GPIO_H1_CTRL, INPUT+PULL_DN },
{ &GPIO_H2_CTRL, OUTPUT+PULL_UP },
{ &GPIO_H3_CTRL, OUTPUT+PULL_UP },
{ &GPIO_H4_CTRL, INPUT+PULL_DN },
{ &GPIO_H5_CTRL, INPUT+PULL_DN },
{ &GPIO_H6_CTRL, OUTPUT+PULL_UP },
{ &GPIO_H7_CTRL, PALT },
{ &GPIOI, 0x30 },
{ &GPIO_I0_CTRL, INPUT },
{ &GPIO_I1_CTRL, INPUT },
{ &GPIO_I2_CTRL, INPUT },
{ &GPIO_I3_CTRL, INPUT },
{ &GPIO_I4_CTRL, INPUT },
{ &GPIO_I5_CTRL, INPUT },
{ &GPIO_I6_CTRL, INPUT },
{ &GPIO_I7_CTRL, INPUT },
{ &GPIOJ, 0x00 },
{ &GPIO_J0_CTRL, INPUT },
{ &GPIO_J1_CTRL, PALT },
{ &GPIO_J2_CTRL, PALT },
{ &GPIO_J3_CTRL, PALT },
{ &GPIO_J4_CTRL, INPUT },
{ &GPIO_J5_CTRL, INPUT }
};
void Init_GPIO(void)
{
BYTE iTemp;
iTemp = 0x00;
while( iTemp<(sizeof(asInitGPIOReg)/3) )
{
*asInitGPIOReg[iTemp].reg=asInitGPIOReg[iTemp].value;
iTemp++;
}
}
读取输入引脚的值(STATE_ACin()):
这里以监测适配器是否插入为例,在笔记本电脑中,在插入电源适配器后,电源充放电管理芯片会拉高AC_OK信号,EC接收该信号用于判断适配器的拔插状态,当AC_OK为高时,电源适配器为插入状态,当AC_OK信号为低时,电源适配器为拔除状态。假设充放电芯片的AC_OK与EC芯片的GPD1引脚连接。在前面的引脚初始化配置中已经将该引脚配置为输入模式了。
接下来需要在OEM_GPIO.H中定义宏STATE_ACin(),用读取GPD1引脚的输入值:
#define STATE_ACin() IS_BIT_SET(GPIOD,1)
在主循环中,例如在10ms事件轮询函数中,使用if语句来判断适配器的拔插状态,这里一般会使用上次状态来判断状态变化,当状态发生变化时才执行相应的操作
void Oem_Hook_Timer10ms(void)
{
new_state = STATE_ACin();
if(new_state != old_state)
{
if(STATE_ACin()!= 0)
{
}
else
{
}
old_state = STATE_ACin();
}
}
输出引脚输出高低电平,以大小写灯为例:
在大小写Caps按键按下后,大小写灯的状态会发生变换,大写状态时会点亮Caps灯,小写状态时会熄灭Caps灯。首先需要在宏定义中定义on/off
#define CAPLED_ON() CLR_BIT(GPIOG,1)
#define CAPLED_OFF() SET_BIT(GPIOG,1)
当矩阵键盘或者外接USB键盘有操作Caps按钮的操作时,代码中会操作这两个宏来实现相应的操作。
|