1 前言
刚开始接触这个芯片时,感觉这个芯片高大上,数据手册就有50多页,寄存器也特别多。目测,应该很难。应用了几个项目,发现也不是很难,而且还挺好用。
手册中的应用示意图如下:
这个芯片对外输出是标准IIC接口,可以使用STM32的标准IIC接口读取。读者可以参考TCA8418.pdf数据手册设计其硬件电路。
该芯片,相比于单片机引脚搭建的矩阵键盘,好处是不用控制逻辑时序,不需要担心占用程序的运行时间等。而且能够可配置为中断检测、锁存输出等功能。简直不能再好用了。
2 实际设计电路
实际用于中,使用了24个按键,采用3行8列方式设计。
3 软件实现
参考数据手册,将COL0~3和ROW0~7设计为矩阵键盘,但有按键按下时,INT引脚输出低电平给单片机,初始化程序如下:
3.1 初始化
void TCA8418_Init(void)
{
static char InitOkCnt = 0;
if(InitOkCnt == 1) return;
unsigned char DataBuff[8];
DataBuff[0]=0xFf;DataBuff[1]=0x07;DataBuff[2]=0x00;
HAL_I2C_Mem_Write(&hi2c2,TCA8418_ADDr,KP_GPIO1,1,DataBuff,3,100);
DataBuff[0]=0x91;
HAL_I2C_Mem_Write(&hi2c2,TCA8418_ADDr,CFG_INT,1,DataBuff,1,100);
DataBuff[0]=0x21;DataBuff[1]=0x01;
HAL_I2C_Mem_Write(&hi2c2,TCA8418_ADDr,UNLOCK1,1,DataBuff,2,100);
DataBuff[0]=0x52;
HAL_I2C_Mem_Write(&hi2c2,TCA8418_ADDr,KP_LCK_TIMER,1,DataBuff,1,100);
{
HAL_I2C_Mem_Read(&hi2c2,TCA8418_ADDr,CFG_INT,1,DataBuff,1,100);
//如果没有复位过,置标志位,并执行一次复位
if(*(unsigned int *)(0x20001FFC) != 0x11223344)
{
*(unsigned int *)(0x20001FFC)=0x11223344;
NVIC_SystemReset();
}
if( DataBuff[0] == 0x91)
{
TCA8418_InitFlag |= 0x01;//初始化成功
InitOkCnt = 1;
}
else
{
NVIC_SystemReset();
}
}
}
3.2 按键读取实现
主程序定时扫描INT引脚是否有发生变化,一旦监测到引脚变为低电平,则立即执行如下按键码读取函数,同时清除按键中断标志位。
unsigned char TCA8418DataBuff[4];
unsigned char bitKeySelect = 0;
void FunTCA8418(void)
{
HAL_I2C_Mem_Read(&hi2c2,TCA8418_ADDr,INT_STAT,1,TCA8418DataBuff,1,100);//读取中断状态情况
if(TCA8418DataBuff[0] )
{
bitKeySelect = 1; HAL_I2C_Mem_Read(&hi2c2,TCA8418_ADDr,KEY_EVENT_A,1,&TCA8418DataBuff[2],1,100);
g_VideoData.KeyNow = TCA8418DataBuff[2];//当前按键值
TCA8418DataBuff[2] &= 0x7F; HAL_I2C_Mem_Read(&hi2c2,TCA8418_ADDr,KEY_EVENT_B,1,&TCA8418DataBuff[3],1,100);
TCA8418_Clear_INT(TCA8418DataBuff[0]);
}
}
清除按键中断标志位。
void TCA8418_Clear_INT(unsigned char ch)
{
unsigned char DataBuff[8];
if(ch)
{
DataBuff[0]=ch;
HAL_I2C_Mem_Write(&hi2c2,TCA8418_ADDr,INT_STAT,1,DataBuff,1,100);
TCA8418DataBuff[0] = 0;
}
}
3.3 调用
在主程序中,调用按键扫描函数如下:
if(KeyIn[IN_EXIT_INT].NowKeyState == 0 && KeyIn[IN_EXIT_INT].PressedTime + 50 < xTaskGetTickCount())//有数据则直接IIC读取
{
KeyIn[IN_EXIT_INT].KeyPressCnt = 1;
FunTCA8418();
}
else if(KeyIn[IN_EXIT_INT].NowKeyState == 1 && KeyIn[IN_EXIT_INT].PressedTime + 500 < xTaskGetTickCount())
{
if(KeyIn[IN_EXIT_INT].KeyPressCnt == 0)
{
KeyIn[IN_EXIT_INT].KeyPressCnt = 1;
FunTCA8418();
TCA8418DataBuff[2] = 0;
}
}