目录
前言
趁着国庆这几天想着做个与硬件的控制,于是就需要交互,LCD屏幕可以用来显示数据,而输入我想到了以前用过的矩阵键盘,但矩阵键盘需要的io太多了。于是买了TM1638模块,在网上看了很多博文,唉,一言难尽啊,驱动都是一样的,TM1638是一种类似于iic的时序但又不是iic时序,它的好处就是用三个引脚同时控制 8位数码管 8位LED灯以及8个按键 。
LED灯和数码管的动态扫描容易实现,按键按理也简单,第一次用这个本着以跑起来为主的目的在网上看了看别人怎么做的,结果,按键方面的控制硬是没有一个可以跑的,,大多数文章基本类似(因为驱动已经写好了)。无语的是它功能确实厉害(3个引脚控制3种8位的外设),但按键方面确实我没有找到能直接抄过来就能跑的,最终我怀疑是不是我硬件的问题(在某宝买了2块,结果2块或多或少有几个led灯点不亮,led灯的测试电压是2v可以电亮,我用万用表测我的只有1.13v。。。。),于是我找了个esp32的例程成功把按键跑起来了。
附上ESP32的TM1638例程
TM1638 LED数码显示模块ARDUINO驱动代码_悟渔的博客-优快云博客_tm1638按键怎么编码
关于按键控制的困惑及解决方案
第一困惑: 我看博客困在了那个 DIO 这个引脚位,注释写着是输入,但为什么并没有更改GPIO的输出模式呢?在stm32里推挽输出,设置输出状态0/1后再对它进行读无效。于是,我不得不去看使用文档,后续知道DIO写数据是输出模式,读数据是输入模式,于是乎在写读时需要更改GPIO的引脚状态。
/**重新设置引脚输入输出状态**/
void Set_Pin_Mode(GPIO_TypeDef * GPIOx,u16 PIN,u32 Mode){
GPIO_InitTypeDef s ={0};
s.Pin=PIN;
s.Mode=Mode;
s.Speed=GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOx,&s);
}
第二困惑:我第一困惑解决了,还是跑不起来,后面看上面的那个esp32例程里用了延时来适应高主频的MCU,比如我用STM32F103是72MHZ全速运行,所以不加延时也是跑不起来的。调用驱动里的读按键一直都是读出来KEY 为 1。
于是加延时
/***************************************************************************************/
/**
* TM1638读键扫数据函数
* 参数:无
* 返回值:读取的按键号,1~8
*/
unsigned char TM1638_ReadKey(void) //TM1638读键扫数据函数
{
unsigned char c[4],i,key_value=0;
_STB=0; //STB=0,开始写命令
TM1638_WriteData(0x42); //普通模式,地址自动增加,读键扫数据
for(i=0;i<4;i++) c[i]=TM1638_Read(); //读取键值
_STB=1; //STB=1,读键值结束
for(i=0;i<4;i++)
key_value|=c[i]<<i;
for(i=0;i<8;i++)
if((0x01<<i)==key_value)
break;
if(i == 8)return 0;
return i+1;
}
经过我的实践,得出:这个按键读出来则一定是被按下了,而不是受抖动,不足的是通过这个模块我只是知道这个按键被按下,而不知道它到底触发了多少次,在测试中,我按下未松开,我通过串口去打印发现按键被按下,前若干次打印出来是键值,后面则是未按下的值,断断续续地又打印出键值,我通过跑例程也是这样。

不知道是不是时序有问题,欢迎同行赐教。
关于按键控制判断只按下一次
尽管这样我还是想通过写算法知道它到底是被按下了一次还是被按下多次(若是考虑到那种按一次数值单位增减的需求),虽然读出来的按键不稳定,但经过我的实际测试,刚按下读出来的数必然是连续的键值,然后必定是连续的0,若还是按着不动,则有可能又是连续的键值(这种情况下一般是按了有几s之久)。所以我也给出我的算法,经过我测试按下按着不动不超过5s,一般被视为只按下了一次。如果它被按下时通过读的键值是固定那么就百分百判断只按下了一次。
void TM1638_KEY_SCAN(vo

本文介绍如何利用TM1638模块控制数码管、LED灯和按键,并解决按键控制难题,包括消除抖动、判断单次按下等问题。
最低0.47元/天 解锁文章
732

被折叠的 条评论
为什么被折叠?



