找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 28856|回复: 16
收起左侧

行列扫描法,反转法,状态机法三种矩阵键盘扫描方法详解 带程序

  [复制链接]
ID:140725 发表于 2017-3-13 01:50 | 显示全部楼层 |阅读模式
实现矩阵键盘扫描的三种方法(代码见附件):
1.行列扫描法
2.反转法
3.状态机法(结合定时器中断)
第一种和第二种方法的本质都是进行循环查询,大量占用MCU的时间,效率比较低。初学者一般会学这两种
第三种方法属于状态机方法,它是结合定时器中断的,相比于前两种采用延时函数的方法,大大提高了MCU的效率。
我们设计矩阵键盘的扫描函数时,要保证:既要及时的判断按键是否被按下,又要让MCU有时间去做其他的事。
代码所对应的硬件电路: 0.png
0.png

完整的原理图:
51start单片机开发板V3.0原理图.pdf (805.5 KB, 下载次数: 86)
回复

使用道具 举报

ID:135835 发表于 2017-3-13 16:45 | 显示全部楼层
在刘平老师的《深入浅出玩转51单片机》里学习过状态机法,看得不是太懂。谢楼主分享了。
回复

使用道具 举报

ID:184846 发表于 2017-4-15 17:14 | 显示全部楼层
就是没有金币了
回复

使用道具 举报

ID:184846 发表于 2017-4-19 08:30 | 显示全部楼层
下载看了,觉得上电数码管亮,好像是初始化显示函数Display_init();那里一开始就把位选全打开了,而每10Ms产生一次中断,主函数中一开始readkey=0xff;然后if(flag){flag=0;readkey=Keyscan();Display(readkey);一开始10ms就显示0XFF,觉得这个位选应该在按键松手才打开,修改如下
void Display_init()
{
        P1=0xFF;                 //将所有的位选关闭,所有数码管不亮,
        wela=1;
        wela=0;
        P1=0x00;           //将段选关闭,也就是刚开始的时候数码管都不亮
        dula=1;
        dula=0;
}
void Display(uchar num1)
{
        wela=1;
        P1=0x00;                 //将所有的位选打开,所有数码管同时亮,
        wela=0;
        dula=1;
        P1=smg_duan[num1];
        dula=0;       
}
回复

使用道具 举报

ID:184846 发表于 2017-4-19 08:31 | 显示全部楼层
哦,我看的是状态机那个。
下载看了,觉得上电数码管亮,好像是初始化显示函数Display_init();那里一开始就把位选全打开了,而每10Ms产生一次中断,主函数中一开始readkey=0xff;然后if(flag){flag=0;readkey=Keyscan();Display(readkey);一开始10ms就显示0XFF,觉得这个位选应该在按键松手才打开,修改如下
void Display_init()
{
        P1=0xFF;                 //将所有的位选关闭,所有数码管不亮,
        wela=1;
        wela=0;
        P1=0x00;           //将段选关闭,也就是刚开始的时候数码管都不亮
        dula=1;
        dula=0;
}
void Display(uchar num1)
{
        wela=1;
        P1=0x00;                 //将所有的位选打开,所有数码管同时亮,
        wela=0;
        dula=1;
        P1=smg_duan[num1];
        dula=0;       
}
回复

使用道具 举报

ID:184846 发表于 2017-4-19 09:11 | 显示全部楼层
下载看了状态机,觉得上电数码管亮,好像是初始化显示函数Display_init();那里一开始就把位选全打开了,而每10Ms产生一次中断,主函数中一开始readkey=0xff;然后if(flag){flag=0;readkey=Keyscan();Display(readkey);一开始10ms就显示0XFF,觉得这个位选应该在按键松手才打开,修改如下
void Display_init()
{
        P1=0xFF;                 //将所有的位选关闭,所有数码管不亮,
        wela=1;
        wela=0;
        P1=0x00;           //将段选关闭,也就是刚开始的时候数码管都不亮
        dula=1;
        dula=0;
}
void Display(uchar num1)
{
        wela=1;
        P1=0x00;                 //将所有的位选打开,所有数码管同时亮,
        wela=0;
        dula=1;
        P1=smg_duan[num1];
        dula=0;       
}

评分

参与人数 1黑币 +100 收起 理由
admin + 100 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:213328 发表于 2017-7-24 14:24 | 显示全部楼层
目前用的反转,出了些问题,刚好学习学习
多谢楼主了
回复

使用道具 举报

ID:168002 发表于 2018-3-7 13:33 | 显示全部楼层
之前都是用反转法,现在试试状态机
回复

使用道具 举报

ID:203654 发表于 2018-5-24 10:46 | 显示全部楼层
感谢楼主分享,学习一下
回复

使用道具 举报

ID:286251 发表于 2018-5-26 15:32 | 显示全部楼层
很有用。非常感谢分享
回复

使用道具 举报

ID:430148 发表于 2018-11-20 20:07 | 显示全部楼层
学习一下
回复

使用道具 举报

ID:380988 发表于 2018-12-2 14:45 | 显示全部楼层
感谢楼主分享,学习一下
回复

使用道具 举报

ID:413383 发表于 2019-6-10 00:03 | 显示全部楼层
多谢楼主了
回复

使用道具 举报

ID:558624 发表于 2019-7-13 22:00 | 显示全部楼层
感谢楼主
回复

使用道具 举报

ID:207882 发表于 2019-7-14 17:20 | 显示全部楼层
写得挺好的,点赞,,我下载了你的状态机程序,,为了省点黑币,其他两个我就没下载了,,我看了后自己有些看法,,如果我同一行一个按键压死,,然后我在同一行按下另一个按键呢????还有主函数10Ms检测一次,,为什么数码管显示也放在这个里面???上电数码管亮我觉得不是上面6#说的,                           readkey=Keyscan();
Display(readkey);
上电按键没按的换Keyscan()返回的应该是0吧,,display(0)对应你的数组不就是全亮???,我觉得应该是这样,试试把数组的全灭数据也就是0x00,放在第一个,,剩下的就按你的按键去排显示的数据就好了
回复

使用道具 举报

ID:644656 发表于 2019-11-18 21:52 | 显示全部楼层
哇,感谢楼主的分享,给我们这些小白提供了学习的资料
回复

使用道具 举报

ID:658887 发表于 2019-12-8 15:50 | 显示全部楼层
感谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表