9.嵌入式控制器(Embedded Controller,EC)学习 GPIO开发流程

9.嵌入式控制器(Embedded Controller,EC)学习 GPIO开发流程,第1张

文章目录
    • 1.General Control Register (GCR),通用控制寄存器,地址0x160
    • 2.GPDRA—GPDRJ端口数据寄存器组(共10组)
    • 3.Port Control n Registers (GPCRn, n = A0-I7),端口控制寄存器
    • 4.GPIO端口编程指导
      • 编程步骤
      • 端口初始化
      • 使用InitGPIOReg数据结构初始化所有端口默认工作模式
      • 读取输入引脚的值(STATE_ACin()):
      • 输出引脚输出高低电平,以大小写灯为例:

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中各个相关寄存器的作用和配置。

寄存器对应地址:

/* Spec.7.5.3 General Purpose I/O Port (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用于配置端口引脚的下拉,高电平使能

端口控制寄存器配置示例代码

/*-----------------------------------------------------------------------------
 * Parameter Definition
 *---------------------------------------------------------------------------*/
#define PALT            0x00
#define INPUT           0x80
#define OUTPUT          0x40
#define PULL_UP         0x04
#define PULL_DN         0x02
#define Driving4mA      0x00    //4mA
#define Driving8mA      0x10    //8mA
#define Driving12mA     0x18    //12mA
#define MaxDriving      0x38    //16mA
4.GPIO端口编程指导 编程步骤
  1. 配置各个端口相关寄存器的初始值(配置asInitGPIOReg)
  2. 使用各个端口相关寄存器的初始值配置GPIO端口的工作方式(Reset_Initialization()—》Init_GPIO())
  3. 在主循环中 *** 作相关端口
端口初始化

InitGPIOReg数据结构,该数据结构用于保存端口初始化相关寄存器初始值的保存。

/*-----------------------------------------------------------------------------
 * Data Structure
 *---------------------------------------------------------------------------*/
typedef struct InitGPIOReg
{
    XBYTE   *reg;
    BYTE    value;
} sInitGPIOReg;
使用InitGPIOReg数据结构初始化所有端口默认工作模式
//-----------------------------------------------------------------------------
// External ram GPIO Registers
// Parameter: INPUT,OUTPUT,PALT,PULL_UP,PULL_DN
//-----------------------------------------------------------------------------
const sInitGPIOReg code asInitGPIOReg[] =
{
    { &GCR,             0x06            },  //

    { &GPIOA,           0xF7            },  // Port A Data port Init

    { &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            },  // Port B Data port Init

    { &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            },  // Port C Data port Init

    { &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            },  // Port D Data port Init

    { &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            },  // Port E Data port Init

    { &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            },  // Port F Data port Init

    { &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            },  // Port G Data port Init

    { &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            },  // Port H Data port Init

    { &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            },  // Port I Data port Init

    { &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            },  // Port J Data port Init

    { &GPIO_J0_CTRL,    INPUT           },
    { &GPIO_J1_CTRL,    PALT            },
    { &GPIO_J2_CTRL,    PALT            },
    { &GPIO_J3_CTRL,    PALT            },
    { &GPIO_J4_CTRL,    INPUT           },
    { &GPIO_J5_CTRL,    INPUT           }

};
//-----------------------------------------------------------------------------
// The function of GPIO register init.
//-----------------------------------------------------------------------------
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) //RCVV

在主循环中,例如在10ms事件轮询函数中,使用if语句来判断适配器的拔插状态,这里一般会使用上次状态来判断状态变化,当状态发生变化时才执行相应的 *** 作

void Oem_Hook_Timer10ms(void)
{
	new_state = STATE_ACin();
	if(new_state != old_state) //适配器状态改变,插入或者拔出适配器
	{
		if(STATE_ACin()!= 0) //插入适配器
		{
			//1.适配器插入后点亮相应的指示灯
			//2.判断电池电量,进而是否进行充电 *** 作
			//3.通过SCI Event通知 *** 作系统适配器插入了
		}
		else //拔出适配器
		{
			//1.适配器拔出后熄灭相应的指示灯
			//2.通过SCI Event通知 *** 作系统适配器拔出了
		}
		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按钮的 *** 作时,代码中会 *** 作这两个宏来实现相应的 *** 作。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/867858.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-12
下一篇 2022-05-12

发表评论

登录后才能评论

评论列表(0条)

保存