返回列表 发帖

事无巨细,矩阵键盘

   停笔好几天,今天复工。今天要跟大家分享一下关于用AVR MEGA16扫描矩阵键盘的一些应用心得。拙劣之见,经不起推敲。权当抛砖引玉罢。
     矩阵键盘,顾名思义,一些按键按一个矩阵的形状排列,就成了矩阵键盘。CEPARK AVR学习板的矩阵键盘长成下面这个样子(其实任何开发板的矩阵键盘也都是这个样的):

也许新手们看这个键盘觉得不太眼熟哈,确实也只有开发板的矩阵键盘才长这个样。但是我说几个你绝对眼熟的:电视遥控器上的键盘、银行ATM的输入键盘、计算器上的键盘、还有你手机上的键盘等等。对的,这些全部都是一些典型的矩阵键盘。尽管也许他们的扫描方式各异,但是毕竟还是始于同一种模型,出于同一种原理,从同一个基础成长起来的。(好像这是我第二次说这句话了)此文的目的,就是把这个最初的矩阵键盘展现给读者。
      此需要读者有一点基础,即关于导线两端上的信号是经过“与”的关系再体现到导线上的。这点在此系列的《事无巨细,独立键盘》一文里有详细描述。如果没有任何按键基础的朋友还是建议先看独立键盘一文,学习也是要分步骤次序的。至于为什么呢,这里给大家一句话作为线索去追寻:“当引脚是开漏或集电极开路输出的时候,便具有了“线与”的功能。”(来自马潮的《AVR单片机嵌入式系统原理与应用实践》)。这需要你有一定的模拟电子基础才有办法找出个所以然来。但是如果你没有,就暂时记住结论好了,即:导线两端上的信号是经过“与”的关系再体现到导线上的。短时间内这句话还不会是错的。
      看看CEPARK AVR开发板的矩阵键盘原理图:

上图是一个4X4的矩阵键盘,一共是16个按键。我们照习惯称横为“行”,“竖”为列。那么PA4、PA5、PA6、PA7我们称之为“行线”,则PA0、PA1、PA2、PA3称为“列线”。要正确记住各个行列线各自对应的IO,这里是PA口。注意看,每一个按键的两端,都分别接在某一个列线和行线上,即:“行线和列线是通过某个按键的按下和抬起实现联通和断开的”,和“导线两端上的信号是经过“与”的关系再体现到导线上的。”这两句话便构成了矩阵键盘扫描的全部。要理解好,理解不了就背下来。
      在详细讲述一下矩阵键盘扫描的原理和步骤:
AVR扫描矩阵键盘,即是把某一条(只有一条)行线置为低电平,而列线全部置为输入方向,然后检测列线,如果检测到某一条列线是低电平,那么就表示位于这条列线与输出低电平的行线的交点处的按键被按下了。要扫描16个按键,就依次以这样的方法扫描16次,之后就可以确定哪一个按键被按下了。当然这里也少不了延时消除按键抖动的环节。以下是详细步骤(以此图为例):
① 设置PA口的高四位为输入,最好使能上拉电阻,抗干扰,低四位为输出;
③ 先扫描第一行,则使PA0输出低电平;
②  检测各个列线,是否有低电平的现象?
③ 如果有,则调用延时函数后再次检测列线,如果某列线仍然被检测到低电平,则表示有对应按键按下,进入按键赋值。
④ 如果没有,依次扫描第二行,使PA1输出低电平……
其他几行的扫描都和第一行的一摸一样,我们只需要变化行线的电平就可以了,需要注意的是每次只扫描一行,即只有一根行线输出低电平。
如果读者理解了独立键盘的原理话,那么矩阵键盘也应该是很简单的,但是程序的编写才是关键。有详细注释的源程序附件形式上传,数码管显示函数的功能解释在《事无巨细,数码管闪亮》一文有详细解释:

[hide][/hide]
十分重要的几个地方:
① 在设置行线电平的时候,一定要先设置PORTx再设置DDRx,否则会导致按键扫描的全盘失败。(对此笔者也是十分无解,试验多次都是一样的结果)
② 读取IO的电平之后,要注意把不需要的位全部屏蔽掉。如果不屏蔽会导致按键扫描有高丢失率。

③ 关于消抖的延时时间,一般是20ms,要注意结合自己的晶振频率来编写。MEGA单片机默认为内部1M晶振源,但是外部晶振要比内部晶振来得准确。但是无论如何,要注意单片机的内部熔丝位和GCC的MakeFile文件对应好。
④ 最好把列线设置为带上拉电阻的输入状态,这样会在引脚悬空的时候会由上拉电阻拉成高电平,可以有效减少干扰。
希望能给有需要的人一点帮助。

附件: 您需要登录才可以下载或查看附件。没有帐号?注册

电子园商城推荐:


看看

TOP

不提倡用这种按键扫描,用状态机扫描是一种很不错的方法,用逐行扫不如用反转法扫描

TOP

不提倡用这种按键扫描,用状态机扫描是一种很不错的方法,用逐行扫不如用反转法扫描 ...
Blueice 发表于 2010-2-3 00:17

嗯,的确如此。但是这个入门性质的文章,还是用最适合入门的方法罢。
进了这个门,理解什么都简单许多了。

TOP

看看     学学

TOP

努力学习, 拼了!!!!!!!!!!!!!

TOP

赞楼主,不错

TOP

楼主同学…
你说的注意事项的第一条,是AVR IO口的物理特性决定的。即在改变PORTx后,需要经过1个半左右的机器周期后,才可以检测到PINx,详见数据手册。
你在改变PORTx后加入的语句对DDRx赋值,其实是没有什么用途的,因为你并不需要改变IO方向,但是它起到了延时的作用。这样就可以正确读取PINx了。反过来写的话,自然读不到正确的PINx。
嘿嘿!

TOP

楼主同学…
你说的注意事项的第一条,是AVR IO口的物理特性决定的。即在改变PORTx后,需要经过1个半左右的 ...
dhjlh 发表于 2010-2-6 01:52

嗯,版主说的有道理,希望能借此讨论下:
1、DDRX的操作不是完全没用的,不知道dhjlh版主注意到没有,论坛的AVR板子,数码管显示和按键扫描的某一个IO口是复用的,所以要在数码管显示的时候设置为输出,在扫描按键的时候设置为输入。其次我并没有在任何地方初始化过另外三个按键IO口,虽然说DDRx默认就是0,但是还是习惯的设置一下。
2、dhjlh版主说的AVR IO的物理特性,我又回去看了看M16 PDF的IO端口一节,找到下面两个图,但是感觉还是不太对。dhjlh版主给指点一下。

您说的“在改变PORTx之后,需要经过一个半左右的时钟周期才能读到正确的PINx”,这句话准确的符合了上面左边的时序图,就是“读取软件赋予的引脚电平的同步”。我认为是在IO为输出方向的情况下的时序。
而上面右边的图,同样也是数据锁存的一个周期之后才能读到PINx的数据,但是这个时序里看不到有体现PORTx的变化。这个图是“读取引脚数据时的同步”。应该是在IO为输入方向的时序吧。
那么我一直以为,在IO做输入脚的时候,外部电平是直接影响PINx寄存器而不必经过PORTx。PORTx的作用仅仅是是否使能上拉电阻。但是没有找到PDF对这一点的说明,还有待验证。
所以希望听听dhjlh版主的看法,扫描按键的时候,假设进入按键扫描程序之前,外部按键已经按下了,即外部低电平。那么进入扫描之后,IO的各个寄存器之间是怎么变化的呢?
附件: 您需要登录才可以下载或查看附件。没有帐号?注册

TOP

这个问题值得讨论一下
一般的说法是:端口由输出转为输入后,要等待一两个时钟周期才能读出正确的IO口电平状态

TOP

嗯,至少某本书是这么写的

TOP

huifu kankan

TOP

膜拜楼主、、、支持。。。。。。。

十分佩服楼主的才华呀。。。特别喜欢你的那个头像,哈哈哈……

正在细细读帖中……

TOP

膜拜楼主、、、支持。。。。。。。

十分佩服楼主的才华呀。。。特别喜欢你的那个头像,哈哈哈…… ...
dandan1990 发表于 2010-2-8 20:01

丹姐怎么有机会出来冒泡了~

TOP

好东西

TOP

很好很强大,楼主厉害

TOP

很好,谢谢

TOP

好的帖子是用来D的!

TOP

你太强了啊你太强了啊你太强了啊你太强了啊

TOP

好,学习下。

TOP

返回列表

站长推荐 关闭


AVR M16单片机助学活动开始了!快来参加吧!!!

家期待已久的Cepark电子园的AVR Atmega16学习板已经正式推出了。 同时,我们的AVR助学活动也正式开始了!!!欢迎大家选购!!! 前期我们经过了样板制作,样 ...


查看