收藏 分享(赏)

第9章 键盘输入接口与状态机编程.doc

上传人:dzzj200808 文档编号:2244651 上传时间:2018-09-07 格式:DOC 页数:26 大小:852.50KB
下载 相关 举报
第9章 键盘输入接口与状态机编程.doc_第1页
第1页 / 共26页
第9章 键盘输入接口与状态机编程.doc_第2页
第2页 / 共26页
第9章 键盘输入接口与状态机编程.doc_第3页
第3页 / 共26页
第9章 键盘输入接口与状态机编程.doc_第4页
第4页 / 共26页
第9章 键盘输入接口与状态机编程.doc_第5页
第5页 / 共26页
点击查看更多>>
资源描述

1、基于 AVR 的单片嵌入式系统原理与实践应用华东师范大学 电子系 马 潮 9-1第 9章 键盘输入接口与状态机编程在前面的章节中,已经详细介绍了 AVR单片机通用数字 I/O口的特性以及应用于输出方式的基本使用方法,并给出了一些与中断、定时计数器相结合的输出控制应用和应用实例。本章将进一步讨论 AVR通用 I/O口用于按键和键盘输入接口,以及基于状态机的软件设计思想和实现。9.1 通用 I/O数字输入接口设计假如把一个单片机嵌入式系统比做一个人的话,那么单片机就相当于人的心脏和大脑,而输入接口就好似人的感官系统,用于获取外部世界的变化、状态等各种信息,并把这些信息输送进人的大脑。嵌入式系统的人

2、机交互通道、前向通道、数据交换和通信通道的各种功能都是由单片机的输入接口及相应的外围接口电路实现的。对于一个电子系统来讲,外部现实世界各种类型和形态的变化和状态都需要一个变换器将其转换成电信号,而且这个电信号有时还需要经过处理,使其成为能被 MCU容易识别和处理的数字逻辑信号,这是因为单片机常用的输入接口通常都是数字接口(A/D 接口,模拟比较器除外,他们属于模拟输入口,而是在芯片内部将模拟信号转换成数字信号的) 。上述的所为“变换器”和“转换处理”从专业的角度讲就是“传感器技术”和“信号调理电路” 。因此,一个单片机嵌入式系统的设计和开发人员要具备这些专业知识和技能,不仅要熟悉一些常用传感器

3、的特性和应用,以及相关的信号调理、转换、接口电路,还要跟踪国际上新技术的发展,将新型传感器器件和新型电路元器件应用于系统设计中。采用新型传感器器件和新型电路元器件,可以大大提高嵌入式系统设计的效率,简化系统的硬件结构和软件设计难度,缩短开发周期,提高系统的性能和可靠型。9.1.1 I/O输入接口硬件设计要点根据系统外围电路输入的电信号形式,可以把输入信号分为以下几种形式:(1) 模拟信号和数字信号。传感器将某个外部参数(如温度、转速)的变化转换成电信号(电压或电流) 。如果传感器输出电信号的幅度变化特征代表了外部参数的变化,如电压的升高下降(电流增大减小)表示温度高低的变化,那么这个传感器就是

4、模拟传感器,它产生是模拟信号。由于MCU是数字化的,因此模拟信号要转换成数字信号才能由 MCU处理。这个转换电路称为摸数转换“A/D” 。A/D 变换是嵌入式系统重要的外围接口电路之一,用途广泛。在系统硬件设计中可以选取专用的 A/D变换芯片作为模拟传感器和单片机之间的接口,也可以选取片内带 A/D转换功能的单片机以简化硬件电路的设计。大多数型号的 AVR单片机在片内都集成有 A/D接口,关于 A/D接口将在以后的章节中进行专门介绍。有些外部参数的变化可以采用数字式传感器器件直接将其变化转换成数字信号。如采用光栅和光电开关器件将位移和转动圈数转换成脉冲信号,用以测量位移或转速。还有一些新型的传

5、感器器件,把模拟传感器、A/D 变换和数字接口集成在一片芯片内,构成了智能数字传感器,如 AD公司和 MAXIM公司的数字温度传感器器件等,这些器件的推出,方便了嵌入式系统的硬件设计。第 9 章 键盘输入接口与状态机编程华东师范大学 电子系 马 潮 9-2(2) 电压信号和电流信号。单片机 I/O接口的逻辑是数字电平逻辑,既以电压的高和低电平作为逻辑“1”和“0” ,因此进入单片机的信号要求是电压信号。一些传感器的输出是电流信号,甚至是微小的电流,那么在进入单片机前还需要将电流信号放大、并把电流转换成电压的信号调理电路。在一些长远距离的应用中,考虑到电压信号的抗干扰能力差,长线衰减等因素,往往

6、在一端把电压信号变成电流信号,在长线中传送电流,而在另一端再把电流信号再转换成电压信号,这样大大提高了信号传输的可靠性,如 RS-485通信等。另外,为了防止外部强电信号对嵌入式系统的冲击而使用的光电隔离技术,也是电流/电压变换的应用(图 9-1) 。图 9-1 长线电流传输和光电隔离(3) 单次信号和连续信号。间隔时间较长单次产生的脉冲信号,以及较长时间保持电平不变化的信号称为单次信号。常见的单次信号一般是由按键、限位开关等人为动作或机械器件产生的信号。而连续信号一般指连续的脉冲信号,如计数脉冲信号,数据通信传输等。单次信号要注意信号的纯净和抗干扰,如消除按键的抖动,外部的干扰等。在图 9-

7、1中,外部状态开关与系统之间采用电流传输方式,在系统入口串接磁阻线圈。当外部开关闭合后,回路中有大电流通过,光电器件导通输出“0” ;而在开关断开后,回路中无电流流通,光电器件不会导通输出“1” 。空间的电磁信号会在传输线上产生高频的干扰信号,磁阻线圈则对高频信号起到阻碍作用,使电流不能突变。另外空间电磁干扰往往能产生较高的干扰电压,但不会产生大的干扰电流(“状态 1”-“状态 2”,最后返回到“状态 0”的。并且在整个过程中,按键的输出信号仅在“状态 1”时给出了唯一的一次确认按键闭合的信号“1” (其它状态均输出“0” ) 。所以上面状态机所表示的按键系统,不仅克服了按键抖动的问题,同时也

8、确保在一次按键整个的过程中,系统只输出一次按键闭合信号(“1” ) 。换句话讲,不管按键被按下的时间保持多长,在这个按键的整个过程中都只给出了一次确认的输出,因此在这个设计中,按键没有“连发”功能,它是一个最简单和基本的按键。一旦有了正确的状态转换图,就可以根据状态转换图编写软件了。在软件中实现状态机的方法和程序结构通常使用多分支结构(IF-ELSEIF-ELSE、CASE 等)实现。下面是根据图 9-4、基于状态机方式编写的简单按键接口函数 read_key()。#define key_input PIND.7 / 按键输入口#define key_state_0 0#define key_

9、state_1 1#define key_state_2 2char read_key(void)static char key_state = 0;char key_press, key_return = 0;key_press = key_input; / 读按键 I/O电平switch (key_state)case key_state_0: / 按键初始态if (!key_press) key_state = key_state_1; / 键被按下,状态转换到键确认态break;case key_state_1: / 按键确认态if (!key_press)key_return = 1

10、; / 按键仍按下,按键确认输出为“1”key_state = key_state_2; / 状态转换到键释放态elsekey_state = key_state_0; / 按键已抬起,转换到按键初始态break;case key_state_2:if (key_press) key_state = key_state_0; /按键已释放,转换到按键初始态break;return key_return;该简单按键接口函数 read_key()在整个系统程序中应每隔 10ms调用执行一次,每次执行时将先读取与按键连接的 I/O的电平到变量 key_press中,然后进入用 switch结构构基于

11、 AVR 的单片嵌入式系统原理与实践应用华东师范大学 电子系 马 潮 9-9成的状态机。switch 结构中的 case语句分别实现了 3个不同状态的处理判别过程,在每个状态中将根据状态的不同,以及 key_press的值(状态机的输入)确定输出值(key_return) ,和确定下一次按键的状态值(key_state) 。函数 read_key()的返回参数提供上层程序使用。返回值为 0时,表示按键无动作;而返回 1表示有一次按键闭合动作,需要进入按键处理程序做相应的键处理。在函数 read_key()中定义了 3个局部变量,其中 key_press和 key_return为一般普通的局部变

12、量,每次函数执行时,key_press 中保存着刚检测的按键值。key_return 为函数的返回值,总是先初始化为 0,只有在状态 1中重新置 1,作为表示按键确认的标志返回。变量 key_state非常重要,它保存着按键的状态值,该变量的值在函数调用结束后不能消失,必须保留原值,因此在程序中定义为“局部静态变量” ,用 static声明。如果使用的语言环境不支持 static类型的局部变量,则应将 key_state定义为全局变量(关于局部静态变量的特点请参考相关介绍 C语言程序设计的书籍) 。例 9.1 单按键的实时时钟秒校时设置设计(一)1) 硬件电路在前面的章节中曾几次给出了简易实时

13、时钟的设计例子,但都没有加入按键,不能实现时钟校时的设置。下面结合上面的按键接口的设计,实现对时钟的校时设置。在该例子中,只是实现了秒单元的校时设置,其重点是让读者体会和实践按键输入接口和处理的实现。时钟系统的硬件电路与图 6-15基本相同,仅在 I/O口 PD7上连接一个按键 K1,该按键的功能为秒加 1,既每按下一次,秒加 1,到 60秒时分加 1,秒回到为 0。图 9-5为电原理图。图 9-5 可实现秒校时的简单时钟电路2) 软件设计以下是采用一个简单按键实现秒单元的校时设置系统的程序。程序中,给出了采用一个简单按键实现时钟校时(仅秒位)设置功能的基本设计,时钟本身的计时显示方法用秒闪烁

14、表示(每秒种 LED数码管的小数点段闪烁一次) 。/*File name : demo_9_1.cChip type : ATmega16Program type : ApplicationClock frequency : 4.000000 MHz第 9 章 键盘输入接口与状态机编程华东师范大学 电子系 马 潮 9-10Memory model : SmallExternal SRAM size : 0Data Stack size : 256*/#include flash char led_710=0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,

15、0x6F; flash char position6=0xfe,0xfd,0xfb,0xf7,0xef,0xdf;char time3; / 时、分、秒计数单元char dis_buff6; / 显示缓冲区,存放要显示的 6个字符的段码值char time_counter,key_stime_counter; / 时间计数单元,char posit;bit point_on, time_1s_ok,key_stime_ok;void display(void) / 6位 LED数码管动态扫描函数PORTC = 0xff;PORTA = led_7dis_buffposit; if (point

16、_on PORTC = positionposit; if (+posit =6 ) posit = 0;/ (3)/ Timer 0 比较匹配中断服务,2ms 定时interrupt TIM0_COMP void timer0_comp_isr(void)display(); / LED扫描显示if (+key_stime_counter =5)key_stime_counter = 0;key_stime_ok = 1; / 10ms到if (+time_counter = 100)time_counter = 0;time_1s_ok = 1; / 1s到void time_to_dis

17、buffer(void) / 时钟时间送显示缓冲区函数char i,j=0;for (i=0;i= 60) / 秒加 1,以下为时间调整time0 = 0;if (+time1 = 60)time1 = 0;if (+time2 = 24) time2 = 0;time_to_disbuffer(); / 新调整好的时间送显示缓冲区;该程序中 LED数码管动态扫描等部分与前面介绍的例子相同,T/C0 的工作于 CTC方式,每 2ms产生中断。在 T/CO中断服务中增加了 10ms到的标志变量 key_stime_ok,作为按键状态机的时间触发序列信号。在主程序中,每隔 10ms调用 read_

18、key()按键接口程序,当函数返回值为 1时,说明产生了一次按键操作过程,秒位加 1,然后进行时间调整。基于 AVR 的单片嵌入式系统原理与实践应用华东师范大学 电子系 马 潮 9-133) 思考与实践 仔细分析 read_key()函数的调用和执行情况,说明为什么该按键接口程序可以正确的处理一次按键的操作过程? 如果将 read_key()中标有(1)的语句 key_return = 1去掉,而将状态 2的处理程序改为:case key_state_2:if (key_press) key_state = key_state_0; /按键已释放,转换到按键初始态else key_return

19、 = 1;break;或:case key_state_2:if (key_press) key_state = key_state_0; /按键已释放,转换到按键初始态key_return = 1;break;时,按键处理会产生什么变化?为什么?三、基于状态机分析的简单按键设计(二)在上面的例子中,对秒的校时设置操作还是不方便,例如,如果将秒从 00 设置为59,需要按键 59 次。如果将按键设计成一个具有“连发”功能的系统,就能很好的解决这个问题。现在考虑这样的一个按键系统:当按键按下后在 1 秒内释放了,此时秒计时加 1,而当按键按下后在 1 秒内没有释放,那么以后每隔 0.5 秒,秒计

20、时就会自动加上 10,直到按键释放为止。这样的按键系统就具备了一种“连发”功能,其中时间也成为系统的一个输入参数了。参考图 9-4,根据状态机的分析方法,可以得到具有上述“连发”功能的按键系统状态转换图(图 9-6) 。图 9-6 具有连发功能按键状态机的状态转换图无按键0有按键1计时 230/0 (消抖)1/01/0 (干扰)0/0 1/10(1s)/20(0.5s)/2第 9 章 键盘输入接口与状态机编程华东师范大学 电子系 马 潮 9-14在图 9-6 所示的图中,按键系统输出 “1”表示按键在 1 秒内释放了,输出“2”表示按键产生一次“连发”的效果。根据图 9-4,下面是基于状态机方

21、式编写的带“连发”功能按键接口函数 read_key_n()。#define key_input PIND.7 / 按键输入口#define key_state_0 0#define key_state_1 1#define key_state_2 2#define key_state_3 3char read_key_n(void)static char key_state = 0, key_time = 0;char key_press, key_return = 0;key_press = key_input; / 读按键 I/O电平switch (key_state)case key_

22、state_0: / 按键初始态if (!key_press) key_state = key_state_1; / 键被按下,状态转换到键确认态break;case key_state_1: / 按键确认态if (!key_press)key_state = key_state_2; / 按键仍按下,状态转换到计时 1key_time = 0; / 清另按键时间计数器else key_state = key_state_0; / 按键已抬起,转换到按键初始态break;case key_state_2:if (key_press)key_state = key_state_0; / 按键已释

23、放,转换到按键初始态key_return = 1; / 输出“1”else if (+key_time = 100) / 按键时间计数key_state = key_state_3; / 按下时间1s,状态转换到计时 2key_time = 0; / 清按键计数器key_return = 2; / 输出“2”break;case key_state_3:if (key_press) key_state = key_state_0; /按键已释放,转换到按键初始态基于 AVR 的单片嵌入式系统原理与实践应用华东师范大学 电子系 马 潮 9-15elseif (+key_time = 50) /

24、按键时间计数key_time = 0; / 按下时间0.5s,清按键计数器key_return = 2; / 输出“2”break;return key_return;函数 read_key_n()与前面的 read_key()结构非常类似,设计为每隔 10ms被调用执行一次,在构成状态机的 switch结构中使用了局部静态变量 key_time作为按键时间计数器,记录按键按下的时间值。函数 read_key_n()的返回参数提供上层程序使用。返回值为 0时,表示按键无动作;返回 1表示一次按键的“单发” (flash char led_710=0x3F,0x06,0x5B,0x4F,0x66

25、,0x6D,0x7D,0x07,0x7F,0x6F; flash char position6=0xfe,0xfd,0xfb,0xf7,0xef,0xdf;char time3; / 时、分、秒计数单元char dis_buff6; / 显示缓冲区,存放要显示的 6个字符的段码值char time_counter,key_stime_counter;第 9 章 键盘输入接口与状态机编程华东师范大学 电子系 马 潮 9-16char posit;bit point_on, time_1s_ok,key_stime_ok;void display(void) / 6位 LED数码管动态扫描函数。

26、。 。 。 。 。/ Timer 0 比较匹配中断服务,2ms 定时interrupt TIM0_COMP void timer0_comp_isr(void)。 。 。 。 。 。void time_to_disbuffer(void) / 时钟时间送显示缓冲区函数。 。 。 。 。 。#define key_input PIND.7 / 按键输入口#define key_state_0 0#define key_state_1 1#define key_state_2 2#define key_state_3 3char read_key_n(void)。 。 。 。 。 。void ma

27、in(void)PORTA = 0x00; / 显示控制 I/O端口初始化DDRA = 0xFF;PORTC = 0x3F;DDRC = 0x3F;DDRD = 0x00;/ T/C0 初始化TCCR0=0x0B; / 内部时钟,64 分频(4M/64=62.5KHz) ,CTC 模式TCNT0=0x00;OCR0=0x7C; / OCR0 = 0x7C(124),(124+1)/62.5=2msTIMSK=0x02; / 允许 T/C0比较匹配中断time2 = 23; time1 = 58; time0 = 55; / 设时间初值 23:58:55 基于 AVR 的单片嵌入式系统原理与实践

28、应用华东师范大学 电子系 马 潮 9-17posit = 0;time_to_disbuffer();#asm(“sei“) / 开放全局中断while (1)if (time_1s_ok)time_1s_ok = 0;point_on = point_on; / 1秒到,秒闪烁标志取反if (key_stime_ok)key_stime_ok = 0; / 10ms到switch (read_key_n()case 1:+time0;break;case 2:time0 += 10;break;if (time0 = 60) / 按键确认按下,秒加 1,以下时间调整time0 -= 60;i

29、f (+time1 = 60)time1 = 0;if (+time2 = 24) time2 = 0;time_to_disbuffer(); / 新调整好的时间送显示缓冲区;主程序中,每隔 10ms 调用 read_key_n()按键接口程序,并根据其返回值对秒位的时间进行加 1 或加 10 的处理。9.3 键盘输入接口设计在上节中按键的连接方法采用的是独立式按键接口方式。独立式按键就是各按键相互独立,每个按键各占用一位 I/O的口线,它们之间状态是独立的,相互之间没有影响,只第 9 章 键盘输入接口与状态机编程华东师范大学 电子系 马 潮 9-18要单独测试口线电平的高低就能判断键的状态

30、。独立式按键电路简单、配置灵活,软件结构也相对简单。此种接口方式适用于系统需要按键数目较少的场合。在按键数量较多的情况下,如系统需要 12或 16个按键的键盘时,采用独立式接口方式就会占用太多的 I/O口,因此一般适用于按键数量多的硬件连接方式往往使用矩阵式键盘接口。9.3.1 矩阵键盘的工作原理和扫描确认方式当键盘中按键数量较多时,为了减少对 I/O口的占用,通常将按键排列成矩阵形式,也称为行列键盘,这是一种常见的连接方式。矩阵式键盘接口见图 9-7所示,它由行线和列线组成,按键位于行、列的交叉点上。当键被按下时,其交点的行线和列线接通,相应的行线或列线上的电平发生变化,MCU 通过检测行或

31、列线上的电平变化可以确定哪个按键被按下。图 9-7为一个 4 x 3的行列结构,可以构成 12个键的键盘。如果使用 4 x 4 的行列结构,就能组成一个 16键的键盘。很明显,在按键数量多的场合,矩阵键盘与独立式按键键盘相比可以节省很多的 I/O口线。矩阵键盘不仅在连接上比单独式按键复杂,它的按键识别方法也比单独式按键复杂。在矩阵键盘的软件接口程序中,常使用的按键识别方法有行扫描法和线反转法。这两种方法的基本思路是采用循环查循的方法,反复查询按键的状态,因此会大量占用 MCU的时间,所以较好的方式也是采用状态机的方法来设计,尽量减少键盘查询过程对 MCU的占用时间。图 9-7 4*3矩阵键盘的

32、组成下面以图 9-7为例,介绍采用行扫描法对矩阵键盘进行判别的思路。图 9-7中,PD0、PD1、PD2 为 3根列线,作为键盘的输入口(工作于输入方式) 。PD3、PD4、PD5、PD6为 4根行线,工作于输出方式,由 MCU(扫描)控制其输出的电平值。行扫描法也称为逐行扫描查询法,其按键识别的过程如下。 将全部行线 PD3PD6 置低电平输出,然后读 PD0PD2 三根输入列线中有无低电平出现。只要有低电平出现,则说明有键按下(实际编程时,还要考虑按键的消抖) 。如读到的都是高电平,则表示无键按下。 在确认有键按下后,需要进入确定具体哪一个键闭合的过程。其思路是:依次将行线置为低电平,并检

33、测列线的输入(扫描) ,进而确认是具体的按键位置。如当PD5输出低电平时(PD3=1、PD4=1、PD5=0、PD6=1) ,测到 PD1的输入为低电平(PD0=1、PD1=0、PD2=1) ,则可确认按键 K3-2处于闭合状态。通过以上分析可以基于 AVR 的单片嵌入式系统原理与实践应用华东师范大学 电子系 马 潮 9-19看出,MCU 对矩阵键盘的按键识别,是采用扫描方式控制行线的输出和检测列线输入的信号相配合实现的。 矩阵按键的识别仅仅是确认和定位了行和列的交叉点上的按键,接下来还要考虑键盘的编码,即对各个按键进行编号。在软件中常通过计算的方法或查表的方法对按键进行具体的定义和编号。在单

34、片机嵌入式系统中,键盘扫描只是 MCU的工作内容之一。MCU 除了要检测键盘和处理键盘操作之外,还要进行其他事物的处理,因此,MCU 如何响应键盘的输入需要在实际系统程序设计时认真考虑。通常,完成键盘扫描和处理的程序是系统程序中的一个专用子程序,MCU 调用该键盘扫描子程序对键盘进行扫描和处理的方式有三种:程序控制扫描、定时扫描和中断扫描。 程序控制扫描方式。在主控程序中的适当位置调用键盘扫描程序,对键盘进行读取和处理。 定时扫描方式。在该方式中,要使用 MCU的一个定时器,使其产生一个 10ms 的定时中断,MCU 响应定时中断,执行键盘扫描,当在连续两次中断中都读到相同的按键按下(间隔 1

35、0ms作为消抖处理) ,MCU 才执行相应的键处理程序。 中断方式。使用中断方式时,键盘的硬件电路要做一定的改动,增加一个按键产生中断信号的输入线,当键盘有按键按下时,键盘硬件电路产生一个外部的中断信号,MCU 响应外部中断,进行键盘处理。下面我们介绍基于状态机并采用定时键盘扫描的键盘处理系统的设计方法。9.3.2 定时扫描方式的键盘接口程序根据图 9-7,下面的键盘接口函数 read_keyboaed()完成了对 4*3 键盘的扫描识别和键盘的编码。编码键盘的定义使用 define 语句定义,键盘的形式类似电话和手机键盘,如图 9-8 所示。键盘扫描处理的设计原则是:既要保证 MCU能及时的

36、判别按键的动作,处理按键输入的操作,又不能过多占用 MCU的工作时间,让它有充裕的时间去处理其它的操作。1 2 34 5 67 8 9* 0 #图 9-8 手机键盘第 9 章 键盘输入接口与状态机编程华东师范大学 电子系 马 潮 9-20#define No_key 255#define K1_1 1#define K1_2 2#define K1_3 3#define K2_1 4#define K2_2 5#define K2_3 6#define K3_1 7#define K3_2 8#define K3_3 9#define K4_1 10#define K4_2 0#define

37、K4_3 11#define Key_mask 0b00000111char read_keyboard()static char key_state = 0, key_value, key_line;char key_return = No_key,i;switch (key_state)case 0:key_line = 0b00001000;for (i=1; iflash char led_713=0x3F,0x06,0x5B,0x4F,0x66,0x6D, / 字型码0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x40;/ 后 3位为 “A” , “b”, “-”fl

38、ash char position8=0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe;char dis_buff8; / 显示缓冲区,存放要显示的 8个字符的段码值char key_stime_counter;char posit;bit key_stime_ok;void display(void) / 8位 LED数码管动态扫描函数PORTC = 0xff;PORTA = led_7dis_buffposit; PORTC = positionposit; if (+posit =8 ) posit = 0;/ Timer 0 比较匹配中断服务,2ms 定时

39、interrupt TIM0_COMP void timer0_comp_isr(void)display(); / 调用 LED扫描显示if (+key_stime_counter =5)key_stime_counter = 0;key_stime_ok = 1; / 10ms到#define No_key 255#define K1_1 1#define K1_2 2#define K1_3 3#define K2_1 4#define K2_2 5#define K2_3 6#define K3_1 7#define K3_2 8#define K3_3 9#define K4_1 1

40、0#define K4_2 0基于 AVR 的单片嵌入式系统原理与实践应用华东师范大学 电子系 马 潮 9-25#define K4_3 11#define Key_mask 0b00000111char read_keyboard()static char key_state = 0, key_value, key_line;char key_return = No_key,i;。 。 。 。 。 。 / 同上面 read_keyboard()void main(void)char i, key_temp;PORTA = 0x00; / 显示控制 I/O端口初始化DDRA = 0xFF;PO

41、RTC = 0xFF;DDRC = 0xFF;PORTD = 0xFF; / 键盘接口初始化DDRD = 0xF8; / PD2、PD1、PD0 列线,输入方式,上拉有效/ T/C0 初始化TCCR0=0x0B; / 内部时钟,64 分频(4M/64=62.5KHz) ,CTC 模式TCNT0=0x00;OCR0=0x7C; / OCR0 = 0x7C(124),(124+1)/62.5=2msTIMSK=0x02; / 允许 T/C0比较匹配中断for (i=0; i8 ;i+)dis_buffi= 12; / LED初始显示 8个“-”#asm(“sei“) / 开放全局中断while (

42、1)if (key_stime_ok)key_stime_ok = 0; / 10ms到key_temp = read_keyboard(); / 调用键盘接口函数读键盘if (key_temp != No_key) / 有按键按下for (i=0; i7; i+)dis_buffi = dis_buffi+1; / LED显示左移一位dis_buff7 = key_temp; / 最右显示新按下键的键值第 9 章 键盘输入接口与状态机编程华东师范大学 电子系 马 潮 9-26;3)思考与实践程序中 LED扫描和定时器的使用与以前的方式相同,每隔 2ms进行 LED的扫描,同时每隔 10ms调

43、用 read_keyboard()键盘接口程序读键盘,并根据返回结果调整 LED显示的内容。程序本身不复杂,主要体会键盘接口程序的功能和使用,请读者自己分析并实现。 本例中,在 T/C0的中断服务中进行了 LED的扫描,而读键盘和键盘处理是在主程序中完成的。如果将读键盘和键盘处理也放在 T/C0中断中完成是否可以?请深入分析这两种处理方式的优点和缺点,说明原因。 在 read_keyboard()中,行线输出语句为什么重复 2次? 说明在 read_keyboard()中,key_mask 的作用,另外是否可以将变量 key_line和key_value定义成普通的局部动态变量?为什么? 修改

44、程序,键盘上数字键功能不变,而“#”键的功能为总清除(即清除 LED上的全部的数字显示,显示复原为 8个“-” ) , “*”键的功能为修改键(表示最后输入的数字有误,LED 显示全部左移一位,清除最后输入的数字,最左边一位补入“-” ) 。思考与练习1在按键处理过程中,除了要进行消抖处理,还要判别按键的释放,如果不进行按键释放的判别,会发生什么现象?2为什么要使用状态机的程序设计方法?该方法有什么优点?说明其基本原理。3如何使用状态机的程序设计方法来设计嵌入式系统的软件,在程序设计中应注意和掌握那些原则?4说明矩阵式键盘的硬件结构和软件处理思想。5认真分析和理解本章中所给出的所有示例,并进行实践,思考和回答所有的问题。6简易秒表的设计与实现使用 6个数码管组成秒表的显示,两个一组,分别显示分、秒和百分之一秒。使用一个按键,作为秒表的记时控制。秒表初始显示“00.00.00” ;第一次按键,秒表启动百分之一秒的记时并显示;第二次按键,秒表停止百分之一秒的记时,显示器显示两次按键之间的相隔时间;第三次按键,秒表复位,显示“00.00.00” 。-本章参考文献:1 ATmega16 数据手册 (英文,CDROM) ,ATMEL,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报