在中,记录了TM1638显示板的显示功能,本文分享该显示板的按键的读取。
如上图,16个按键,每个按键的一端连接TM1638的K1、K2,另一端连接SGn,即KSn。再看手册(手册下载数码管显示板驱动芯片TM1638数据手册中关于按键扫描的部分:
与8按键8数码管8LED的显示板不同的是,该显示板可以有组合按键,那在写读按键程序的时候,返回的按键可以不是一个独立的按键,所以可以采用一个两个字节的数据,每一位代表一个按键,正好可以存储16个按键的值。
typedef union { struct { uint8_t bKey1 :1;//S1 uint8_t bKey2 :1;//S2 uint8_t bKey3 :1;//S3 uint8_t bKey4 :1;//S4 uint8_t bKey5 :1;//S5 uint8_t bKey6 :1;//S6 uint8_t bKey7 :1;//S7 uint8_t bKey8 :1;//S8 uint8_t bKey9 :1;//S9 uint8_t bKey10 :1;//S10 uint8_t bKey11 :1;//S11 uint8_t bKey12 :1;//S12 uint8_t bKey13 :1;//S13 uint8_t bKey14 :1;//S14 uint8_t bKey15 :1;//S15 uint8_t bKey16 :1;//S16 }bt; struct { uint8_t lowb; uint8_t highb; }byte; uint16_t word; }Key_tu;
/******************************************************************************* * 函数名:TM1638_ReadKey * 功 能:TM1638读按键数据 * 参 数:无 * 返回值:读出的数据 * 说 明:返回值为双字节共用体,每一个bit为一个按键; *******************************************************************************/ uint16_t TM1638_ReadKey(void) { uint8_t u8Data[4], i; Key_tu uKey; uKey.word = 0; TM1638_STBReset(); TM1638_WriteData(0x42); delay_us(5); for (i = 0; i < 4; i++) { u8Data[i] = TM1638_ReadData();//读BYTE1~BYTE4的数据 } TM1638_STBSet(); uKey.bt.bKey1 = (((u8Data[0] & 0x04) == 0x04) ? 1 : 0 ); uKey.bt.bKey2 = (((u8Data[0] & 0x40) == 0x40) ? 1 : 0 ); uKey.bt.bKey3 = (((u8Data[1] & 0x04) == 0x04) ? 1 : 0 ); uKey.bt.bKey4 = (((u8Data[1] & 0x40) == 0x40) ? 1 : 0 ); uKey.bt.bKey5 = (((u8Data[2] & 0x04) == 0x04) ? 1 : 0 ); uKey.bt.bKey6 = (((u8Data[2] & 0x40) == 0x40) ? 1 : 0 ); uKey.bt.bKey7 = (((u8Data[3] & 0x04) == 0x04) ? 1 : 0 ); uKey.bt.bKey8 = (((u8Data[3] & 0x40) == 0x40) ? 1 : 0 ); uKey.bt.bKey9 = (((u8Data[0] & 0x02) == 0x02) ? 1 : 0 ); uKey.bt.bKey10 = (((u8Data[0] & 0x20) == 0x20) ? 1 : 0 ); uKey.bt.bKey11 = (((u8Data[1] & 0x02) == 0x02) ? 1 : 0 ); uKey.bt.bKey12 = (((u8Data[1] & 0x20) == 0x20) ? 1 : 0 ); uKey.bt.bKey13 = (((u8Data[2] & 0x02) == 0x02) ? 1 : 0 ); uKey.bt.bKey14 = (((u8Data[2] & 0x20) == 0x20) ? 1 : 0 ); uKey.bt.bKey15 = (((u8Data[3] & 0x02) == 0x02) ? 1 : 0 ); uKey.bt.bKey16 = (((u8Data[3] & 0x20) == 0x20) ? 1 : 0 ); return uKey.word; }
注意下图中红框圈出的部分,是该显示板连接的按键对应的BIT,理解了写出上面的程序就很简单了。
实现与 TM1638驱动显示板(8数码管+8LED+8按键)单片机C语言程序(按键功能)相同的功能,演示效果也相同,因按键读取程序的差异,稍作修改即可:
/******************************************************************************* * 函数名:Key_ScanProcess * 功 能:按键扫描处理 * 参 数:无 * 返回值:无 * 说 明:去抖动,每20ms扫描一次,扫描时按键被释放才会执行案件的操作; 仅支持单键、单击 *******************************************************************************/ void Key_ScanProcess(void) { uint8_t u8KeyNum, i; u8KeyNum = (uint8_t)(TM1638_ReadKey() & 0x0007);//获取键值 if (u8KeyNum != 0)//有键按下 { u8KeyState = KEY_PRESSED; for (i = 0; i < 3; i++) { if (((u8KeyNum >> i) & 0x01) == 1) { u8Key_Name = (i + 1);//保存按键值 break; } } }else { u8KeyState = KEY_RELEASED; } if (u8KeyState == KEY_RELEASED)//按键释放 { switch (u8Key_Name) { case KEY_SET://设置键 { if (uKey_Flag.bt.bSetMode) { uKey_Flag.bt.bSetMode = 0;//退出设置模式 PID_ModifySetTemper(u32Key_SettingTemper);//修改设定温度 }else { uKey_Flag.bt.bSetMode = 1;//进入设置模式 u32Key_SettingTemper = PID_GetSetTemper();//读取设定温度 } }break; case KEY_UP://向上键 { if (uKey_Flag.bt.bSetMode)//设置模式 { if (u32Key_SettingTemper < (80 * 100)) { u32Key_SettingTemper += 10; } } }break; case KEY_DOWN://向下键 { if (uKey_Flag.bt.bSetMode)//设置模式 { if (u32Key_SettingTemper > (30 * 100)) { u32Key_SettingTemper -= 10; } } }break; default:break; } u8Key_Name = KEY_NULL; } }