三、微控制器上的矩阵键盘设计
目录
前言
一、矩阵键盘
1、矩阵键盘原理:
2、矩阵键盘原理图
二、单片机原理图绘制
1、所需元件名称
2、绘制原理图
三、编写程序
总结
前言
今天我们来学习如何通过AT89C52上的矩阵按键来控制数码管显示对应字母或者数字,期间我们用到的软件有proteus和keil两个软件,欢迎大家提问已经寻找错误,请大家点个关注和收藏,后续还会更新。
一、矩阵键盘
1、矩阵键盘原理:
矩阵键盘是由8个io口对16个按键进行读取的。咱们最常用的方法是行列扫描,可以减小io口的使用,有效的提高了io口的利用率。其中,4X4矩阵式按键中,4条I/O线作为行线,4条I/O口作为列线,行线和列线每个交叉点上设置一个按键,这样咱们就能得到一个4X4的矩阵键盘了。
2、矩阵键盘原理图
上图为4X4矩阵按键的原理图,咱们画原理图时可以参考此原理图进行绘制。
对矩阵键盘读取的方法有两种,分别是:(1)行列式(2)线翻式。
今天咱们用到的是行列式,其具体检测原理如下:
行列式检测时,先控制I/O口对第一行输出低电平,其余行都为高电平,然后立即通过检测控制列的I/O口是否有低电平。假设单片机控制I/O口对第一行输出低电平,通过检测发现第三列的I/O口发现低电平,这样咱们就知道第一行第三列的按键被按下。
二、单片机原理图绘制
1、所需元件名称
proteus原理图中名称对应:
AT89C52——52单片机芯片;
BUTTON——按钮(复位按键);
CAP——无极性电容;
CAP-ELEC——电解电容;
CAP-POL——极性电容;
CRYSTAL——晶振;
RES——电阻;
RESPACK-8——排阻;
7SEG-MPX1-CA——单个数码管;
以上就是我们这次设计需要用到的所有元器件,接下来我们就需要创建新工程,然后在右面添加元器件进行绘制。
2、绘制原理图
首先咱们按照上面给出的原理图画出4X4矩阵按键原理图。
这里我是通过P1口对矩阵按键进行检测的。
下图是当我按下第三行第三列时的现象。
然后我们就可以将数码管、复位电路和时钟电路加入咱们的原理图中,最终如下图。
至此咱们的4X4矩阵按键原理图就画完了。
三、编写程序
咱们可以根据咱们画的原理图对程序进行编写。
咱们进行行列式扫描,具体代码如下:
对数码管数组变量定义(注意这里我们用的是共阳极数码管,此数组不能运用到共阴极数码管中,还需另寻数组):
u8 gsmg_code[17]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e};//共阳极
按键检测函数:
unsigned char key_rants_scan(void)
{
unsigned char key_value=0;
KEY_CONTROL=0x77;
KEY_CONTROL=0xfe;//将第一行置低电平
if(KEY_CONTROL!=0xfe)
{
delay(1000);
switch(KEY_CONTROL)//检测列是否有低电平
{
case 0xee:key_value=1;break;
case 0xde:key_value=2;break;
case 0xbe:key_value=3;break;
case 0x7e:key_value=4;break;
}
}
while(KEY_CONTROL!=0xfe);
KEY_CONTROL=0xfd;//将第二行置低电平
if(KEY_CONTROL!=0xfd)
{
delay(1000);
switch(KEY_CONTROL)
{
case 0xed:key_value=5;break;
case 0xdd:key_value=6;break;
case 0xbd:key_value=7;break;
case 0x7d:key_value=8;break;
}
}
while(KEY_CONTROL!=0xfd);
KEY_CONTROL=0xfb;//将第三行置低电平
if(KEY_CONTROL!=0xfb)
{
delay(1000);
switch(KEY_CONTROL)
{
case 0xeb:key_value=9;break;
case 0xdb:key_value=10;break;
case 0xbb:key_value=11;break;
case 0x7b:key_value=12;break;
}
}
while(KEY_CONTROL!=0xfb);
KEY_CONTROL=0xf7;//将第四行置低电平
if(KEY_CONTROL!=0xf7)
{
delay(1000);
switch(KEY_CONTROL)
{
case 0xe7:key_value=13;break;
case 0xd7:key_value=14;break;
case 0xb7:key_value=15;break;
case 0x77:key_value=16;break;
}
}
while(KEY_CONTROL!=0xf7);
return key_value;//返回按键检测结果
}
主函数:
void main()
{
unsigned char key=0;
while(1)
{
key=key_rants_scan();
if(key!=0)
SMG_A_DP_PORT=gsmg_code[key-1];
}
}
代码效果:
咱们按下二行第三列的按钮:
根据以上步骤,咱们就可以得到想要的实验效果啦!
总结
以上就是咱们的实验步骤,在进行实验的时候要注意:(1)数码管是共阴极还是共阳极(2)需要对按键进行消抖处理(3)I/O口对应哪一行哪一列(4)矩阵按键按下时对应的数字是多少。
通过porteus和keil对4X4矩阵按键进行了简单的设计。希望对你有帮助,后续我还会持续更新,帮忙点赞收藏,欢迎大家来看。
推荐阅读
-
一种结构设计模式,允许在对象中动态添加新行为。它通过创建一个封装器来实现这一目的,即把对象放入一个装饰器类中,然后把这个装饰器类放入另一个装饰器类中,以此类推,形成一个封装器链。这样,我们就可以在不改变原始对象的情况下动态添加新行为或修改原始行为。 在 Java 中,实现装饰器设计模式的步骤如下: 定义一个接口或抽象类作为被装饰对象的基类。 公共接口 Component { void operation; } } 在本例中,我们定义了一个名为 Component 的接口,该接口包含一个名为 operation 的抽象方法,该方法定义了被装饰对象的基本行为。 定义一个实现基类方法的具体装饰对象。 公共类 ConcreteComponent 实现 Component { public class ConcreteComponent implements Component { @Override public void operation { System.out.println("ConcreteComponent is doing something...") ; } } 定义一个抽象装饰器类,该类继承于基类,并将装饰对象作为一个属性。 公共抽象类装饰器实现组件 { protected Component 组件 public Decorator(Component component) { this.component = component; } } @Override public void operation { component.operation; } } } 在这个示例中,我们定义了一个名为 Decorator 的抽象类,它继承了 Component 接口,并将被装饰对象作为一个属性。在操作方法中,我们调用了被装饰对象上的同名方法。 定义一个具体的装饰器类,继承自抽象装饰器类并实现增强逻辑。 公共类 ConcreteDecoratorA extends Decorator { public ConcreteDecoratorA(Component 组件) { super(component); } } public void operation { super.operation System.out.println("ConcreteDecoratorA 正在添加新行为......") ; } } 在本例中,我们定义了一个名为 ConcreteDecoratorA 的具体装饰器类,它继承自装饰器抽象类,并实现了操作方法的增强逻辑。在操作方法中,我们首先调用被装饰对象上的同名方法,然后添加新行为。 使用装饰器增强被装饰对象。 公共类 Main { public static void main(String args) { Component 组件 = new ConcreteComponent; component = new ConcreteDecoratorA(component); 组件操作 } } 在这个示例中,我们首先创建了一个被装饰对象 ConcreteComponent,然后通过 ConcreteDecoratorA 类创建了一个装饰器,并将被装饰对象作为参数传递。最后,调用装饰器的操作方法,实现对被装饰对象的增强。 使用场景 在 Java 中,装饰器模式被广泛使用,尤其是在 I/O 中。Java 中的 I/O 库使用装饰器模式实现了不同数据流之间的转换和增强。 让我们打开文件 a.txt,从中读取数据。InputStream 是一个抽象类,FileInputStream 是专门用于读取文件流的子类。BufferedInputStream 是一个支持缓存的数据读取类,可以提高数据读取的效率,具体代码如下: @Test public void testIO throws Exception { InputStream inputStream = new FileInputStream("C:/bbb/a.txt"); // 实现包装 inputStream = new BufferedInputStream(inputStream); byte bytes = new byte[1024]; int len; while((len = inputStream.read(bytes)) != -1){ System.out.println(new String(bytes, 0, len)); } } } } 其中 BufferedInputStream 对读取数据进行了增强。 这样看来,装饰器设计模式和代理模式似乎有点相似,接下来让我们讨论一下它们之间的区别。 第三,与代理模式的区别: 代理模式的目的是控制对对象的访问,它在对象外部提供一个代理对象来控制对原对象的访问。代理对象和原始对象通常实现相同的接口或继承相同的类,以确保两者可以相互替换。 装饰器模式的目的是动态增强对象的功能,而这是通过对象内部的包装器来实现的。在装饰器模式中,装饰器类和被装饰对象通常实现相同的接口或继承自相同的类,以确保两者可以相互替代。装饰器模式也被称为封装器模式。 在代理模式中,代理类附加了与原类无关的功能。
-
NeurIPS 2022 | 最强斗地主AI!网易互娱AI Lab提出基于完美信息蒸馏的方法-完美信息蒸馏(PTIE) 在斗地主游戏中,非完美信息的引入主要是由于三位玩家均不能看到别人的手牌,对于任意一位玩家而言,仅可知道其余两位玩家当前手牌的并集,而难于精准判断每位玩家当前手牌。完美信息蒸馏的思路是针对这种非完美问题,构建一个第三方角色,该角色可以看到三位玩家的手牌,该角色在不告知每位玩家完美信息的情况下通过信息蒸馏的方式引导玩家打出当前情况下合理的出牌。 以强化学习常用的 Actor-Critic 算法为例,PTIE 在 Actor-Critic 算法的应用中可以利用 Critic 的 Value 输出作为蒸馏手段来提升 Actor 的表现。具体而言即在训练中 Critic 的输入为完美信息(包含所有玩家的手牌信息),Actor 的输入为非完美信息(仅包含自己手牌信息),此种情况下 Critic 给予的 Value 值包含了完美信息,可以更好地帮助 Actor 学习到更好的策略。 从更新公式上来看,正常的 Actor-Critic 算法 Actor 更新的方式如下: 在 PTIE 模式下,对于每个非完美信息状态 h,我们可以在 Critic 中构建对应的完美信息状态 D(h),并用 Critic 的输出来更新 Actor 的策略梯度,从而达到完美信息蒸馏的效果。 PTIE 框架的整体结构如下图所示: 无论是训练还是执行过程中智能体都不会直接使用完美信息,在训练中通过蒸馏将完美信息用于提升策略,从而帮助智能体达到一个更高的强度。 PTIE 的另一种蒸馏方式是将完美信息奖励引入到奖励值函数的训练中,PerfectDou 提出了基于阵营设计的完美信息奖励 node reward,以引导智能体学习到斗地主游戏中的合作策略,其定义如下: 如上所示,完美信息部分 代表 t 时刻地主手牌最少几步可以出完,在斗地主游戏中可以近似理解为是距游戏获胜的距离, 代表 t 时刻地主阵营和农民阵营距游戏获胜的距离之差, 为调节系数。通过此种奖励设计,在训练时既可以一定程度地引入各玩家的手牌信息(出完的步数需要知道具体手牌才能计算),同时也鼓励农民以阵营的角度做出决策,提升农民的合作性。 特征构建: PerfectDou 针对牌类游戏的特点主要构建了两部分特征:牌局状态特征和动作特征。其中牌局状态特征主要包括当前玩家手牌牌型特征、当前玩家打出的卡牌牌型特征、玩家角色、玩家手牌数目等常用特征,动作特征主要用于刻画当前状态下玩家的所有可能出牌,包括了每种出牌动作的牌型特征、动作的卡牌数目、是否为最大动作等特征。 牌型特征为 12 * 15 的矩阵,如下图所示: 该矩阵前 4 行代表对应每种卡牌的张数,5-12 行代表该种卡牌的种类和对应位置。 网络结构和动作空间设计 针对斗地主游戏出牌组合数较多的问题,PerfectDou 基于 RLCard 的工作上对动作空间进行了简化,对占比最大的两个出牌牌型:飞机带翅膀和四带二进行了动作压缩,将整体动作空间由 27472 种缩减到 621 种。 PerfectDou 策略网络结构如下图所示: 策略网络结构同样分为两部分:状态特征部分和动作特征部分。 在状态特征部分,LSTM 网络用于提取玩家的历史行为特征,当前牌局状态特征和提取后的行为特征会再通过多层的 MLP 网络输出当前的状态信息 embedding。 在动作特征部分,每个可行动作同样会经过多层 MLP 网络进行编码,编码后的动作特征会与其对应的状态信息 embedding 经过一层 MLP 网络计算两者间的相似度,并经由 softmax 函数输出对应的动作概率。 实验结果
-
像首席技术官一样思考:如何高效管理 30 人的研发团队?-管理越多越轻松。好的研发团队,应该是上拨下用,即下级对上级的向上管理;而不是反过来,总是向下管理,甚至是 CTO 做经理的事,经理做工程师的事,工程师最终会被当成实习生。如果是这样,就会越管越累,不仅团队无法成长,而且团队整天很忙还效率低下,问题一大堆。 有这样一个小故事:一位高级经理下班后帮忙倒垃圾,结果被老板训斥了一顿。这就好比首席技术官做了实习生自己该做的事。事情本身没有对错之分,只是从不同的角度有不同的理解。 古人云:"用人不疑,疑人不用"。在面对自己的研发团队时,应该相信他们能做好,授权一线开发人员充分发挥专业特长,不要限制他们的工作。但在相信他们的同时,也要进行二次确认,始终秉持 "我相信,但我要确认 "的原则和严谨的精神。因为每个人都会犯错和疏忽,通过发挥团队的智慧,团队犯错的机会就会大大减少。比如回归测试、代码审查、开发演示、变更审批等等。 如前所述,每个人都难免会犯错。但作为管理者,你所设计和商定的流程不能出错。管理者的每一个决定和沟通都应该经过深思熟虑。就像红绿灯的交通设计,某辆车不小心闯红灯可能会扣分,但红绿灯的设计一定要正确、人性化、统一。再比如,开发人员可能会因为疏忽大意写出 bug,但研发流程的设计和上线流程的发布不能有任何差错。因此,流程体系的设计,一方面要结合当前团队规模、业务特点和需要重点解决的问题来设计,另一方面也要在人员防错、效率提升、发挥团队集体智慧等维度进行综合考量。应该站在更高更抽象的角度去思考,不断思考一个倍受欢迎的园区应该如何设计,思考一个灵动、经典、永恒的建筑应该遵循怎样的模式,思考一个成功、优秀、卓越的研发团队应该需要怎样的流程和制度。 最后,反馈很重要。向上汇报很重要,向下反馈也很重要。能够保持顺畅的双向反馈和闭环管理,对研发团队的协作和沟通有着非常明显的积极作用。在向上汇报方面,要培养团队在正式汇报、会议汇报、私下沟通、书面总结、非正式场合等方面的沟通能力,提醒下属报喜也要报忧。凡事先记录,再跟进,最后反馈。反馈很重要,主动汇报更难得。 另一方面,同时也不要忽视向下反馈。好的爱,是双向的。团队也是如此,没有严格的上下级之分,只是分工和角色不同而已。作为管理者,不必总保持一种 "神秘感",让人 "捉摸不透 "才是牛。当团队做得好或有人做得好时,要记得在公开或私下场合给予肯定和赞许。业务有增长、业绩有提升时,别忘了给团队一些鼓励,或者安排一次下午茶或聚餐。在例会或正式会议上,也可以同步向大家传达一些重要信息和高层指示。"欲速则不达,欲远则同行"。 当向上汇报、向下反馈的沟通闭环形成后,同时结合前面研发过程的管理闭环,双管齐下,就能形成良性循环。如此反复,持之以恒,优秀卓越的研发团队,必将呈现。 能力、产出和效率 接下来,继续重复关于能力、产出和效率的话题。 站在不同的角色,以及一个企业经营、生存和发展所需要的基础上,我把研发生产力分为三个层次,分别是:一线员工关心的研发能力、管理层关心的软件产出和操作人员关心的企业生产效率。简单概括就是:既要把工作做好,又要能出成果,还要能帮企业赚钱。
-
51 微控制器设计 16 键矩阵键盘
-
矩阵键盘的原理和程序设计
-
设计分享 | 微控制器 4*4 矩阵键盘控制 LED 灯
-
[51 微控制器]初学者必学的矩阵键盘基础项目 -(读取 LCD 屏幕上显示的矩阵键盘数字) (7)
-
51 基于微控制器的 4x4 矩阵键盘简易教程
-
三、微控制器上的矩阵键盘设计
-
51 微控制器电子秤分级设计(HX711、LCD 1602、矩阵键盘)