
AVR学习笔记十九、4X4矩阵键盘实验.pdf
6页AVR 学习笔记十九、4X4 矩阵键盘实验19.1 实例功能在前面的实例中我们已经学习了在单片机系统中检测独立式按键的接口电路和程序设计,独立式按键的每个按键占用1 位 I/O口线,其状态是独立的,相互之间没有影响,只要单独测试链接案件的I/O 口线电平的高低就能判断键的状态独立式按键电路简单、配置灵活, 软件结构也相对简单此种接口方式适用于系统需要按键数目较少的场合在按键数量较多的情况下, 如系统需要8 个以上按键的键盘时,采用独立式接口方式就会占用太多的I/O 口,这对于I/O 口资源不太丰富的单片机系统来说显得相当浪费,那么当按键数目相对较多的时候, 为了减少I/O 口资源的占用, 应该采取什么样的方式才能够既满足多按键识别,又减少 I/O 口的占用呢?当然我们可以采用端口扩展器件比如串并转换芯片实现单片机I/O 口的扩展,但是这种方式既增加了电路的复杂性,又增加了系统的成本开销有没有比较经济实惠的方法呢?事实上,在实际引用中我们经常采用矩阵式键盘的方式来节约I/O 口资源和系统成本在这个实验中,我们采用4X4 矩阵键盘来实现使用8 个 I/O 口识别 16 个按键的实验,本实例分为三个功能模块,分别描述如下: 单片机系统:利用ATmega16 单片机与矩阵键盘电路实现多按键识别。
外围电路: 4X4 矩阵键盘电路、LED 数码管显示电路 软件程序:编写软件,实现4X4 矩阵键盘识别16 个按键的程序通过本实例的学习,掌握以下内容: 4X4 矩阵键盘的电路设计和程序实现19.2 器件和原理19.2.1 矩阵键盘的工作原理和扫描确认方式当键盘中按键数量较多时,为了减少对I/O 口的占用, 通常将按键排列成矩阵形式,也称为行列键盘, 这是一种常见的连接方式矩阵式键盘接口见图1 所示, 它由行线和列线组成,按键位于行、列的交叉点上当键被按下时,其交点的行线和列线接通,相应的行线或列线上的电平发生变化,MCU 通过检测行或列线上的电平变化可以确定哪个按键被按下图 1 为一个 4 x 4的行列结构,可以构成16 个键的键盘很明显,在按键数量多的场合,矩阵键盘与独立式按键键盘相比可以节省很多的I/O 口线图 1 4X4 键盘扫描电路矩阵键盘不仅在连接上比单独式按键复杂,它的按键识别方法也比单独式按键复杂在矩阵键盘的软件接口程序中,常使用的按键识别方法有行扫描法和线反转法这两种方法的基本思路是采用循环查循的方法,反复查询按键的状态,因此会大量占用MCU 的时间, 所以较好的方式也是采用中断的方法来设计,尽量减少键盘查询过程对MCU 的占用时间。
在本实例中只是简单演示矩阵键盘的按键识别技术,所以仍然采用查询方法19.2.2采用行扫描法对矩阵键盘进行判别的思路下面以图2为例,介绍采用行扫描法对矩阵键盘进行判别的思路图2 中, PA0 、PA1、PA2 、PA3为 4 根列线,这4 根列线通过电阻接正电源,即上拉(当然AVR单片机 I/O 口有内部上拉电阻, 可以设置内部上拉电阻使能,从而不用连接4 个外部上拉电阻) ,PA4 、PA5 、PA6 、PA7为 4 根行线将行线所接的I/O 口作为输出端,列线所接的I/O 口作为输入端这样,当没有按键按下时,所有的输入端都是高电平,设置行线输出低电平,一旦有键按下,则输入线会被拉低,这样通过读取输入线的状态就可以得知是否有按键按下行扫描法按键识别的过程如下图 2 ATmega16 与 4X4 键盘的连接1) 、判断键盘中是否有按键按下将全部行线PA4PA7置低电平输出,然后读PA0 PA3四根输入列线的状态只要有低电平出现,则说明有键按下(实际编程时,还要考虑按键的消抖) 如读到的都是高电平,则表示无键按下2) 、判断闭合键所在位置在确认有键按下后,即可进入确定具体哪个键按下的过程其思路是: 依次将 4 根行线分别置为低电平,即在某根行线置为低电平时,其余行线为高电平, 在确定某根行线置为低电平后,再逐列检查各列线的电平状态,若某列为低电平,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。
矩阵按键的识别仅仅是确认和定位了行和列的交叉点上的按键,接下来还要考虑键盘的编码,即对各个按键进行编号在软件中常通过计算的方法或查表的方法对按键进行具体的定义和编号在单片机嵌入式系统中,键盘扫描只是MCU 的工作内容之一MCU 除了要检测键盘和处理键盘操作之外,还要进行其他事物的处理,因此,MCU 如何响应键盘的输入需要在实际系统程序设计时认真考虑通常,完成键盘扫描和处理的程序是系统程序中的一个专用子程序,MCU 调用该键盘扫描子程序对键盘进行扫描和处理的方式有三种:程序控制扫描、定时扫描和中断扫描程序控制扫描方式在主控程序中的适当位置调用键盘扫描程序,对键盘进行读取和处理定时扫描方式在该方式中,要使用MCU 的一个定时器,使其产生一个10ms 的定时中断, MCU 响应定时中断,执行键盘扫描,当在连续两次中断中都读到相同的按键按下(间隔10ms作为消抖处理) ,MCU 才执行相应的键处理程序中断方式 使用中断方式时,键盘的硬件电路要做一定的改动,增加一个按键产生中断信号的输入线, 当键盘有按键按下时, 键盘硬件电路产生一个外部的中断信号,MCU 响应外部中断,进行键盘处理在本实例中我们介绍基于程序控制扫描方式的键盘处理系统的设计方法。
19.3 电路和连接本实验主要有两部分电路模块组成:数码管显示电路,4X4 键盘电路 数码管显示电路电路在前面的实例中我们已经做过介绍,在此不再重复这里我们重点介绍一下4X4 键盘电路 4X4 键盘电路如图3 所示图 3 4X4 键盘电路18.4 程序设计1、程序功能在本实例中,我们利用数码管将4X4 键盘中按下的按键的键码值显示出来2、函数说明本实例主要有数码管显示程序和4X4 键盘识别程序, 数码管显示程序我们前面例子中已经介绍过,本实例的程序中不再详细说明3、编程说明使用 WINA VR 开发环境,使用的是外部12M 的晶振,所以需要将makefile 文件中的时钟频率修改为12M另外在程序烧录到单片机的时候,熔丝位也要选择为外部12M 晶振(注意是晶振, 不是外部振荡器,一定不要选择错了,否则会导致单片机不能再烧写程序)4、程序代码关于数码管显示程序,在此不再列出,直接打包到程序文件夹中下面列出主程序以及4X4 键盘识别程序/* * AVR 使用范例4*4 矩阵键盘检测* * MCU: ATmega16 * * 作者:maweili * * 编译器: usbisp * * * * 2009.04.03* */ #include /io 端口寄存器配置文件,必须包含#include /GCC 中的延时函数头文件unsigned char Disp_Buff16 = 0 xaf,0 xa0,0 xc7,0 xe6,0 xe8,0 x6e,0 x6f,0 xa2, 0 xef,0 xee,0 xeb,0 x6d,0 x0f,0 xe5,0 x4f,0 x4b; /数码管字型码表显示:0,1,2,3,4,5,6,7,8,9,A,b,C,d,E,F unsigned char KeyNumber; /函数声明void Delayus(unsigned int lus); /us 延时函数void Delayms(unsigned int lms); /ms 延时函数unsigned char Read_Key(void); / 读取键值int main(void) /GCC 中 main 文件必须为返回整形值的函数,没有参数 PORTB = 0X00; /PORTB 口全部输出低电平,使数码管的段位全部为低电平,不亮DDRB = 0XFF; /配置端口PB 全部为输出口PORTC &= (1 PC6); /配置数码管0 的位选通口为低电平,不导通数码管DDRC |= (1 PC6); / KeyNumber = 16; /开始没有按键按下,不显示while(1) Read_Key(); /读取键值PORTB = Disp_BuffKeyNumber; /键值送数码管显示PORTC |= (1 PC6);/ 数码管的位选通端口输出高电平,使数码管显示 /us 级别的延时函数void Delayus(unsigned int lus) while(lus-) _delay_loop_2(3); /_delay_loop_2(1) 是延时 4 个时钟周期,参数为3 则延时12 /个时钟周期,本实验用12M 晶体,则12 个时钟周期为12/12=1us /ms 级别的延时函数void Delayms(unsigned int lms) while(lms-) Delayus(1000); /延时 1ms /4*4 矩阵键盘扫描,PD 高四位为行输出口,低四位为列输入口unsigned char Read_Key(void) unsigned char i,j; DDRD = 0 xf0; /设置 PD 高四位为输出口,低四位为输入口PORTD = 0 x00; / 初始运行输出全为0 if(PIND & 0 x0f) = 0 x0f) return 0; / 判断有无按键动作,没有,返回0 else Delayms(20); /按键消抖if(PIND & 0 x0f) = 0 x0f) return 0; /再次判断是否有按键动作else for(i = 4;i 8;i+) /逐行输出 0 PORTD = (1 i) | 0 x0f; /第 i 行输出 0 for(j = 0;j 4;j+) if(PIND & (1 j) = 0) /逐列检测KeyNumber = (i - 4) * 4 + j; /计算键值 return 0; / 。












