一、概述
在中,记录了TM1638显示板的显示功能,本文分享该显示板的按键的读取。
二、原理图分析
如上图,16个按键,每个按键的一端连接TM1638的K1、K2,另一端连接SGn,即KSn。再看手册(手册下载数码管显示板驱动芯片TM1638数据手册中关于按键扫描的部分:
与8按键8数码管8LED的显示板不同的是,该显示板可以有组合按键,那在写读按键程序的时候,返回的按键可以不是一个独立的按键,所以可以采用一个两个字节的数据,每一位代表一个按键,正好可以存储16个按键的值。
三、主要代码
1. 按键扫描驱动
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,理解了写出上面的程序就很简单了。
2. 按键应用程序
实现与 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;
}
}