目 录
项目二 简易数字时钟设计 ............................................................................................................... 4 任务2.1 实时时钟基本功能实现 ................................................................................................. 5
子任务2.1.1 时钟的数码管显示电路设计 .............................................................................. 5
2.1.1.1 认识数码管 ............................................................................................................................... 5 2.1.1.2 数码管接口电路设计 ............................................................................................................... 9 2.1.1.3 知识点小结 ............................................................................................................................... 9 2.1.1.4 课后练习 ................................................................................................................................... 9 子任务2.1.2 基本计时功能及显示软件设计 .......................................................................... 9 2.1.2.1 定时器中断计时子程序设计及仿真调试 ................................................................................ 9 2.1.2.2 数码管的显示编程及仿真调试 .............................................................................................. 11 2.1.2.3 数码管动态显示时间子程序设计及仿真调试 ...................................................................... 15 2.1.2.4 系统的软硬件联合仿真调试 .................................................................. 错误!未定义书签。 2.1.2.5 知识点小结 ............................................................................................................................. 18 2.1.2.6 课后练习 ................................................................................................................................. 18
任务2.2 时钟的修改及闹钟报警 ............................................................................................... 18
子任务2.2.1 时钟修改及声音报时电路设计 ........................................................................ 19 2.2.1.1 矩阵键盘电路设计 ................................................................................................................. 19 2.2.1.2 声音报警电路设计 ................................................................................................................. 21 2.2.1.3 知识点小结 ............................................................................................................................. 32 2.2.1.4 课后练习 ................................................................................................................................. 32 子任务2.2.2 系统软件设计 ................................................................................................... 32 2.2.2.1 矩阵键盘扫描子程序设计及仿真调试 .................................................................................. 32 2.2.2.2 时钟修改子程序设计及仿真调试.......................................................................................... 32 2.2.2.3 闹钟时间设定子程序设计及仿真调试 .................................................................................. 32 2.2.2.4 整点及闹钟声音报警子程序设计仿真调试 .......................................................................... 32 2.2.2.5 系统软硬件联合仿真调试 ..................................................................................................... 32 2.2.2.6 知识点小结 ............................................................................................................................. 32 2.2.2.7 课后练习 ................................................................................................................................. 32
项目三 数字电压表设计 ................................................................................................................. 33 任务3.1 电压采集、并口驱动液晶显示系统设计 ..................................................................... 33
子任务3.1.1 电压采集、并口驱动液晶显示电路设计 ........................................................ 33
3.1.1.1 电压采集电路设计 ................................................................................................................. 33 3.1.1.2 电压的并口驱动液晶显示电路设计 ...................................................................................... 33 3.1.1.3 知识点小结 ............................................................................................................................. 33 3.1.1.4 课后练习 ................................................................................................................................. 33 子任务3.1.2 电压采集、并口驱动液晶显示软件设计 ........................................................ 33 3.1.2.1 电压采集子程序设计及仿真调试.......................................................................................... 34
1
3.1.2.2 电压显示子程序设计及仿真调试 .......................................................................................... 34 3.1.2.3 系统的软硬件联合仿真调试 .................................................................................................. 34 3.1.2.4 知识点小结 ............................................................................................................................. 34 3.1.2.5 课后练习 ................................................................................................................................. 34
任务3.2 电压的I2C驱动液晶显示系统设计 ............................................................................ 34
子任务3.2.1 IC2串口驱动液晶显示器电路设计 ................................................................. 34 3.2.1.1 认识I2C .................................................................................................................................. 34 3.2.1.2 I2C接口电路设计 ................................................................................................................... 34 3.2.1.2 知识点小结 ............................................................................................................................. 34 3.2.1.2 课后练习 ................................................................................................................................... 34 子任务3.2.2 IC2串口驱动液晶显示器软件设计 ................................................................. 35 3.2.2.1 认识I2C通信协议 .................................................................................................................. 35 3.2.2.2 电压的I2C驱动液晶显示软件设计 ...................................................................................... 35 3.2.2.3 系统的软硬件联合仿真调试 .................................................................................................. 35 3.2.2.4 知识点小结 ............................................................................................................................. 35 3.2.2.5 课后练习 ................................................................................................................................. 35
项目四 遥控窗帘系统设计 ............................................................................................................. 36 任务4.1 使窗帘动起来 ................................................................................................................ 36
子任务4.1.1 窗帘运动控制电路设计 .................................................................................... 36
4.1.1.1 认识步进电机.......................................................................................................................... 36 4.1.1.2 步进电机接口电路设计 .......................................................................................................... 36 4.1.1.3 知识点小结 ............................................................................................................................. 36 4.1.1.3 课后练习 ................................................................................................................................. 36 子任务4.1.2 窗帘运动控制软件设计 .................................................................................... 36 4.1.2.1 步进电机控制方式 .................................................................................................................. 36 4.1.2.2 步进电机控制软件设计 .......................................................................................................... 36 4.1.2.3 系统软硬件联合仿真 .............................................................................................................. 36 4.1.2.4 知识点小结 ............................................................................................................................. 36 4.1.2.5 课后练习 ................................................................................................................................. 36
任务4.2 红外遥控窗帘设计 ......................................................................................................... 37
子任务4.2.1 红外遥控电路设计 ............................................................................................ 37 4.2.1.1 认识红外遥控装置 .................................................................................................................. 37 4.2.1.2 红外遥控接口电路设计 .......................................................................................................... 37 4.2.1.3 知识点小结 ............................................................................................................................. 37 4.2.1.3 课后练习 ................................................................................................................................. 37 子任务4.2.2 红外遥控软件设计 ............................................................................................ 37 4.1.2.1 认识红外遥控通信制式 .......................................................................................................... 37 4.1.2.2 红外遥控窗帘软件设计 .......................................................................................................... 37 4.1.2.3 系统软硬件联合仿真 .............................................................................................................. 37 4.1.2.4 知识点小结 ............................................................................................................................. 37
2
4.1.2.5 课后练习 ................................................................................................................................. 37
附录1: 引脚功能及索引 ............................................................................................................ 38 附录2: 自制电路板 .................................................................................................................... 39 附录3: 寄存器索引 .................................................................................................................... 40 附录4: 8051系列单片机汇编指令速查表及索引 ................................................................... 41 附录5: C51头文件 .................................................................................................................... 42 附录6: 常用51系列单片机速查表 .......................................................................................... 43 附录7: PROTUSE器件库速查..................................................................................................... 45
3
项目二 简易数字时钟设计
项目实现功能:使用单片机内部定时器设计一数字时钟,具体要求: 1. 实现时钟功能,并在数码管上实时显示。
2. 设计矩阵按键随时调节时钟的时、分、秒并能进行闹铃设置。 3. 能利用蜂鸣器进行整点及闹铃提示。
4. 请大家自行扩展显示年、月、日、星期功能。
项目设计又分为数字时钟基本计时功能设计、数字时钟数码管实时显示设计、时钟修改及闹钟功能设计、闹铃报时功能设计等4个任务,从简单到复杂一步一步介绍数字时钟的设计方法。
4
任务2.1 实时时钟基本功能实现
系统功能要求
设计数字时钟,实现时钟计时及实时显示功能,具体要求完成: 1. 使用单片机内部定时器,利用C51编程实现时钟的定时动能 2. 设计数码管显示接口电路
3. C51编程实现数字时钟的实时显示 4. 软硬件的仿真调试
教学目标
1. 2. 3. 4. 5. 6.
进一步掌握单片机内部定时器定时程序的设计方法 掌握数码管的基本工作原理
掌握单片机与数码管的接口电路设计方法 掌握数码管的动态实时显示程序设计方法 掌握数字时钟的Keil仿真调试方法 掌握数码管的Proteus仿真设计方法
子任务2.1.1 时钟的计时程序设计
2.1.1.1 单片机内部定时器编程实现时钟的计时
1.系统功能分析
数字时钟要求对时间进行不断地累加,选用12MHz晶振时,内部定时器最大定时时间为65.536ms,选择定时器为工作方式1,定时50ms,循环50ms定时20次对秒变量加1,秒加到60时,对分钟变量加1,分钟加到60时,对小时变量加1,小时加到24时,时分秒全部清零,重新开始计时,周而复始循环运行变能实现时钟功能。 2.程序流程图
系统程序包括主程序和定时中断服务程序两部分,此处仅仅实现基本计时功能,因而主程序主要完成初始化工作,之后便进入死循环,流程如图2-1-1,注意,为确保定时间的相对准确,定时器初始化时将定时中断设为高优先级。死循环的同时,定时器进行加1计数,溢出时转到定时中断服务程序完成时间的实时修改,程序流程如图2-1-2。
开始初始化化各变量定时器初始化循环等待定时中断图2-1-1 系统主程序流程图
5
开始保护现场选择1区R寄存器50ms定时初值送T0修改50ms循环次数N3.系统程序设计6
1s到?Y50ms循环次数赋20,秒单元内容加1等于60秒?NY秒单元内容清零分单元内容加1等于60分?NY分单元清零小时单元内容加1等于24时?NY小时单元清零将时分秒单元内容送显示缓冲区恢复现场中断返回图2-1-2 定时中断服务程序流程图
1).变量定义
表2-1-1 变量定义
变量名 timer[6] disp[8] 变量含义 存放实时时间 显示缓存区
con_50ms 50ms循环次数,秒定时用 2).系统源程序
#include data char timer[6]={0x00,0x00,0x00,0x00,0x00,0x00}; //存放实时时间data char disp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00};//显示缓冲区 data char con_50ms=0X00; //1秒定时用 /*********************初始化程序**********************/ clearmen() { int i; for(i=0;i<6;i++) disp[i]=timer[i]; TH0=0x3C;TL0=0xB0; //定时器初始化 TMOD=0X01;ET0=1;TR0=1;EA=1;PT0=1; //置定时器中断为高优先级 } /***********************主程序************************/ main() { clearmen(); while(1); } /*******************1秒中断处理程序*******************/ void time_intt0(void) interrupt 1 using 1 { TH0=0x3C;TL0+=0xB0; //考虑程序跳转等耗时 con_50ms++; if(con_50ms==20) { con_50ms=0x00; timer[0]++; if(timer[0]>=10) { timer[0]=0;timer[1]++; if(timer[1]>=6) { 7 timer[1]=0;timer[2]++; if(timer[2]>=10) { timer[2]=0;timer[3]++; if(timer[3]>=6) { timer[3]=0;timer[4]++; if(timer[4]>=10) { timer[4]=0;timer[5]++; } if(timer[5]==2 ) { if(timer[4]==4) { timer[4]=0;timer[5]=0; } } } } } } disp[0]=timer[0];disp[1]=timer[1];disp[2]=timer[2]; disp[3]=timer[3];disp[4]=timer[4];disp[5]=timer[5]; } } 源程序分析如下: 程序主要实现实时时钟的计时功能,为尽量使计时准确,做了如下两个方面的处理: 将定时器0中断设为高优先级,即PT0=1,这样处理后,在后续程序中,当有其他中断源与定时器0同时向CPU申请中断时,会优先处理定时器0中断; 定时中断服务程序中没有关定时器中断和定时器,配合“TL0+=0x0B;”语句可较好的提高计时精度。 但这种处理毕竟还是比较有限,如果需要更精确的定时,则可采用高精度的专业定时器芯片来实现。 5.系统程序的Keil仿真 建立项目,加入源程序在Keil软件中进行仿真,仿真时可调出数组变量timer[6]和disp[8]观察计时情况,仿真结果如图2-1-3。 8 图2-1-3 数字时钟计时功能程序仿真结果 2.1.1.2知识点小结 2.1.1.3 课后练习 子任务2.1.2 时钟的实时显示设计 时钟的显示可采用七段数码管、LED点阵、液晶显示器及触摸屏等显示器件实现,在此,选择最基础也是应用十分广泛的七段数码管来实现时钟的数码显示,侧重讲解数码管的显示原理和程序设计方法。 2.1.2.1 认识数码管 1. 什么是数码管 数码管是利用发光二极管构成的一种数字化显示器件,按段数分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元(多一个小数点显示);按能显示多少个“8”可分为1位、2位、4位等数码管,如图2-1-4。 9 (a) 1位数码管 (b) 2位数码管 (c) 4位数码管 图2-1-4 数码管 不管将几位数码管连在一起,数码管的显示原理都是一样的,都是靠点亮内部的发光二极管来发光,下面就来我们讲解一个数码管是如何亮起来的。 2.发光二极管工作原理 按发光二极管单元连接方式分为共阳极数码管和共阴极数码管,如图2-1-5。共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管,在应用时应将公共极COM接到+5V,当某一字段发光二极管的阴极为低电平时,相应字段就点亮,当某一字段的阴极为高电平时,相应字段就不亮。共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管,在应用时应将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮,当某一字段的阳极为低电平时,相应字段就不亮。 图2-1-5 数码管内部结构 可以利用万用表检测擞码管的引脚排列,对数字万用表来说,红色表笔连接表内部电池正极,黑色表笔连接表内部电池负极,当把数字万用表置于二极管挡时,其两表笔间开路电压约为1.5v,把两表笔正确加在发光二极管两端时,可以点亮发光二极管。 如图2-1-6所示,将数字万用表置于二极管挡,红表笔接在①脚,然后用黑表笔去接触其他各引脚,假设只有当接触到⑨脚时,数码管的a段发光,而接触其余引脚时则不发光。由此可知,被测数码管为共阴极结构类型,⑦脚是公共阴极,①脚则是数码管的a段。接下来再检测各段引脚,仍使用数字万用表二极管挡,将黑表笔固定接在③脚,用红表笔依次接触②、③、④、⑤、⑥、⑦、⑧、⑩引脚时,数码管的其他段先后分别发光,据此便 10 可绘出该数码管的内部结构和引脚排列图。 图2-1-6 数码管引脚排列的检测 2.1.2.2 数码管接口电路设计 选择共阳数码管,单片机的P2.0—P2.5口作为位选线分别接6个数码管的公共端,P0口接各位的段码,注意: P0口作为通用I/O口使用时,须外接上拉电阻,即图中的RP,同理,在P0口与断码线上串电阻起限流作用。 P2口经一非门接到数码管的位选信号段,此处非门的主要作用是增加P2口的驱动能力以满足数码管显示需要。 图2-1-7 数码管接口电路 11 2.1.2.3 数码管的显示编程及仿真调试 1.数码管的编码方法 从数码管的内部结构可知:要显示数字8,对于共阴数码管,给公共端送低电平的同时,给段引脚送0x7f;而对于共阳数码管则给公共端送高电平的同时给段选引脚送0x80。此处的0x7f和0x80即称为数字8的显示码,同理,可得到其他符号的显示代码如表2-1-1所示。这是我们根据实际电路图自己给出的编码,不同的电路,编码可能不同,共阳极的编码与共阴极的编码也是不同的,因此大家一定要掌握编码原理,也就是要明白数码管显示的原理。 表2-1-1 数码管的字符编码 显示字符 0123456789 共阴极段选码 3FH06H 共阳极段选码 C0HF9H 显示字符 C 共阴极段选码 39H 共阳极段选码 C6H AB 5BH4FH66H 6DH7DH07H 7FH6FH77H 7CH DEFP A4H B0H99H92H82H F8H80H90H88H83H UΓy 8. “灭” 5EH79H71H73H 3EH31H 6EHFFH00H A1H86H 8EH 8CH C1H CEH91H00H FFH 可以采用数组来定义数码管的字符编码: char code dis_7[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; 在编写显示程序时,配合位选信号,再根据显示数据调用相应的数组元素送到P0口。例如要显示3,则执行语句“P0=dis_7[3];”即可。 2.数码管的静态显示 LED显示器工作方式有两种:静态显示方式和动态显示方式。静态显示的特点是数码管的公共端一直有效,即若为共阴数码管,则COM端一直为0,每个数码管必须接一个8位锁存器用来锁存待显示的字形码。送入一次字形码显示字形一直保持,直到送入新字形码为止。这种方法的优点是占用CPU时间少,显示便于监测和控制。缺点是硬件电路比较复杂,成本较高。下面采用静态显示技术实现6个数码管同时显示数字0—9的效果。源程序如下: 12 #include \"reg51.h\" code char dis_7[11]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0xff}; /* 共阴LED段码表 \"0\" \"1\" \"2\" \"3\" \"4\" \"5\" \"6\" \"7\" \"8\" \"9\" \"不亮\"*/ /*****************1毫秒延时程序*****************/ delay1ms(int t) { int i,j; for(i=0;i char k; P2=0XC0; //送位选,选中全部6个数码管 for(k=0;k<10;k++) { P0=dis_7[k]; //送字符码(段选) delay1ms(1000); //延时1s } } /***********************主程序********************/ main() { while(1) { scan(); } } 分析上述程序可知,数码管的显示需要位选和段选(字符码)的配合才能实现,位选定位为哪个数码管显示数据,段选确定数码管显示的内容。Proteus仿真结果如图2-1-8。 图2-1-8 数码管静态显示的Proteus仿真 13 3.数码管的动态显示 动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。这样一来,就没有必要每一位数码管配一个锁存器,从而大大地简化了硬件电路。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。动态显示的亮度比静态显示要差一些,所以在选择限流电阻时应略小于静态显示电路中的。下面编程实现6个数码管显示不同的字符,源程序如下, #include \"reg51.h\" code char dis_7[11]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0xff}; code char dis_loc[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf}; //位选编码 /*****************1毫秒延时程序*****************/ delay1ms(int t) { int i,j; for(i=0;i } /*********************扫描程序*******************/ scan() { char k; for(k=0;k<6;k++) { P2=dis_loc[k]; //送位选,依次选中6个数码管 P0=dis_7[k]; //根据为选送字符码(段选) delay1ms(1); //延时1ms } } /***********************主程序********************/ main() { while(1) { scan(); } } 分析程序可知,动态显示的基本算法是依次让第一只数码管显示“0”1ms、第二只数码管显示“1”1ms„„第六只数码管显示“5”1ms、第一只数码管显示“0”1ms„„。即实现算法的方法是P2口依次送0xfe、0xfd、0xfb、0xf7、0xef、0xdf的同时,P0送相应的字符显示码0x3F、0x06、0x5B、0x4F、0x66、0x6D。仿真结果如图2-1-9。 14 图2-1-9 数码管动态显示仿真 2.1.2.4 实时时钟的数码管动态显示及仿真调试 数字时钟的通常显示时分秒,共需6个数码管,在前面的程序中专门定义了disp[8]数组变量作为显示缓冲区,在时钟修改程序中将当前时间按照秒个位、秒十位、分个位、分十位、小时个位及小时十位的顺序依次存放在该数组变量中。在显示程序中应按顺序调出该数组元素并在相应的数码管上进行显示。 另外,时钟显示时,通常应在小时、分钟和秒之间加小数点,而小数点是接在P0.7的,因此在第三个数码管(分钟个位)和第五个数码管(小时个位)应显示小数点,及执行语句“P0.7=1;”,C51源程序如下。 #include data char timer[6]={0x00,0x00,0x00,0x00,0x00,0x00}; //存放实时时间 data char disp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00};//显示缓冲区 code char dis_7[10]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; code char dis_loc[6]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf}; //位选编码 data char con_50ms=0X00; //1秒定时用 sbit DP=P0^7; //小数点 /*****************1毫秒延时程序*****************/ delay1ms(int t) { int i,j; for(i=0;i 15 char k; for(k=0;k<6;k++) { P2=dis_loc[k]; //送位选,依次选中6个数码管 P0=dis_7[disp[k]]; //被显示数据存放在disp[k]中 if(k==2||k==4) //是显示分钟或小时个位的数码管吗? { DP=1; //显示小数点 } delay1ms(1); //延时1ms } } /*********************初始化程序**********************/ clearmen() { int i; for(i=0;i<6;i++) disp[i]=timer[i]; TH0=0x3C;TL0=0xB0; //定时器初始化 TMOD=0X01;ET0=1;TR0=1;EA=1;PT0=1; //置定时器中断为高优先级 } /***********************主程序************************/ main() { clearmen(); while(1) { scan(); } } /*******************1秒中断处理程序*******************/ void time_intt0(void) interrupt 1 { TH0=0x3C;TL0+=0xB0; //考虑程序跳转等耗时 con_50ms++; if(con_50ms==20) { con_50ms=0x00; timer[0]++; if(timer[0]>=10) { 16 timer[0]=0;timer[1]++; if(timer[1]>=6) { timer[1]=0;timer[2]++; if(timer[2]>=10) { timer[2]=0;timer[3]++; if(timer[3]>=6) { timer[3]=0;timer[4]++; if(timer[4]>=10) { timer[4]=0;timer[5]++; } if(timer[5]==2 ) { if(timer[4]==4) { timer[4]=0;timer[5]=0; } } } } } } disp[0]=timer[0];disp[1]=timer[1];disp[2]=timer[2]; disp[3]=timer[3];disp[4]=timer[4];disp[5]=timer[5]; } } 程序分析如下: 第一个数码管显示秒个位、第二个显示秒十位„„依次循环,实现语句为 P2=dis_loc[k]; //送位选,依次选中6个数码管 P0=dis_7[disp[k]]; //被显示数据存放在disp[k]中 是否显示小数点,取决于当前显示的数码管,第三个和第五个数码管应显示小数点,实现的语句为: if(k==2||k==4) //是显示分钟或小时个位的数码管吗? { DP=1; //显示小数点 } 系统程序仿真如图2-1-10。 17 图2-1-10 数字时钟的数码管动态显示仿真 2.1.2.5 知识点小结 2.1.2.6 课后练习 任务2.2 时钟的修改及闹钟报警 系统功能要求 设计一键盘,完成时钟修正及闹铃设定功能,并实现时钟的整点报时和闹铃提示功能。具体要求完成: 1. 设计矩阵键盘电路 2. 设计键盘扫描、时钟修正和闹铃设定程序 3. 设计蜂鸣器发声电路,并设计整点报时和闹铃提示程序 4. 软硬件的仿真调试 教学目标 18 1. 掌握矩阵键盘电路及扫描程序设计方法 2. 掌握蜂鸣器接口电路及发声程序设计方法 3. 掌握时钟修正及闹铃设定程序设计方法 4. 掌握整点报时及闹铃提示程序设计方法 5. 掌握矩阵键盘及蜂鸣器发声程序的Proteus仿真设计方法 子任务2.2.1 时钟修正及闹铃设定功能设计 2.2.1.1 矩阵键盘电路设计 系统共设4个按键,分别定义为调时键、闹铃设定、加1键和减1键,本程序重点之一在于介绍矩阵键盘的设计方法,故刻意采用2*2矩阵键盘电路实现时钟修正及闹铃设定功能。 1. 矩阵键盘工作原理 矩阵式键盘中,行、列线分别连接到按键开关的两端。当无键按下时,行、列线断开;当有键按下时,行、列线将导通。如图2-1-1所示。矩阵键盘识别方法有扫描法和线反转法。 U1P10P11P12P13P14P15P16P17123456781312151431191891716P10P11P12P13P14P15P16P17INT1INT0T1T0P00P01P02P03P04P05P06P07P20P21P22P23P24P25P26P27VCCGNDRXDTXDALE/PPSEN39383736353433322122232425262728402010113029K0P10K4048CP14K1159DP15K226AEP16K337BFP17 19 K5K6K7P11P12P13K8K9K10K1189C52EA/VPX1X2RESETRDWRK12K13K14K15图2-1-1 矩阵键盘电路 1).扫描法 所谓行扫描法,就是通过行线发出低电平信号,如果该行线所连接的键没有按下的话,则列线所连接的输出端口得到的是全“1”信号;如果有键按下的话,则得到的是非全“1”信号。具体过程如下: 首先,为了提高效率,一般先快速检查整个键盘中是否有键按下(即粗扫描);再用 逐行扫描的方法来确定闭合键的具体位置(即细扫描):先扫描第0行,即输出1110(第0行为“0”,其余3行为“1”),然后读入列信号,判断是否为全“1” 。扫描原理如图2-2-2。 0K1K2K3K40K1K2K3K40K5K6K7K80K5K6K7K80K9K13K10K14K11K1512K160K9K13K10K14K11K1512K16001 1 1 11 0 1 1 (a)粗扫描——无键按下 (b)粗扫描——K6键按下 0K1K2K3K41K1K2K3K41K5K6K7K80K5K6K7K81K9K13K10K14K11K1512K161K9K13K10K14K11K1512K16111 1 1 11 0 1 1 (c)细扫描第一行 (d)细扫描第二行 图2-2-2 矩阵键盘扫描步骤 2).线反转法 线反转法也是识别闭合键的一种常用方法。该方法比行扫描法速度要快,但在硬件电路上要求行线与列线均需有上拉电阻,故比行扫描法稍复杂些。 2. 矩阵键盘接口电路设计 P1.0、P1.1作为行线分别接到4个按键的一端,另一端作为列线接到分别接到P1.6和P1.7引脚,矩阵键盘接口电路如图2-2-3。 图2-2-3 2*2矩阵键盘接线图 20 2.2.1.2 时间调节及闹铃设定程序设计 1.矩阵键盘扫描子程序设计及仿真调试 1).按键识别扫描原理 矩阵键盘扫描的基本原理是:写行线(列线),读列线(行线)。如图2-2-3所示,向P1.0写“0”即P1=0XFE;,读P1.6和P1.7,若P1.6=0则表示SET ALARM键按下,若P1.7=0,则表示SET TIME按下。同理向P1.1写“0”可以检测INC或DEC键的按键情况。 2).设计键盘扫描程序并显示键值 程序要求扫描按键并将键值在第一位数码管上显示,定义SET TIME键值为“1”,SET ALARM键值为“2”,INC键值为“3”,DEC键值为“4”。源程序如下,仿真结果如图2-2-4。 #include #define uchar unsigned char #define uint unsigned int code uchar dis_7[11]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00}; data uchar key_val=10; //上电无键按下不显 /*****************1毫秒延时程序*****************/ delay1ms(uint t) { uint i,j; for(i=0;i /*********************扫描程序*******************/ disp_scan() { P2=0xfe; //选中第一个数码管 P0=dis_7[key_val]; //被显示数据存放在disp[k]中 delay1ms(1); //延时1ms } /********************键盘扫描程序*********************/ void key_scan() { uchar temp; disp_scan(); P1=0XFE; //写行线P1.0=0 temp=P1&0xF0; //读列线并屏蔽列线(P1.6、P1.7) if(temp!=0xF0) { disp_scan(); disp_scan(); //延时去抖 P1=0XFE; temp=P1&0xF0; if(temp!=0xF0) 21 switch(temp) { case 0x70:key_val=1;break; //SET TIME键按下 case 0Xb0:key_val=2;break; //SET ALARM键按下 } while(temp!=0XF0){disp_scan(); temp=P1&0xf0;}//等待按键释放 } P1=0XFD; //写行线P1.1=0 temp=P1&0xF0; //读列线并屏蔽列线(P1.6、P1.7) if(temp!=0xF0) { disp_scan(); disp_scan(); //延时去抖 P1=0XFD; temp=P1&0xF0; if(temp!=0xF0) switch(temp) { case 0x70:key_val=3;break; //INC键按下 case 0Xb0:key_val=4;break; //DEC键按下 } while(temp!=0XF0){disp_scan(); temp=P1&0xf0;}//等待按键释放 } } void main() { while(1) key_scan(); } 图2-2-4 按键扫描及键值显示仿真 22 2.时间调节及闹铃设定程序设计 1).系统功能分析 系统设置4个按键,分别定义为调时键、闹铃设定、加1键和减1键,每个键的具体功能要求如下: 1). 按下调时键 关时钟计时功能,显示时间格式为“**:**:--”,被调节位进行0.5s间隔闪烁; 第一次按下则调分钟个位,此时,按加1键分钟加1,按减1键分钟减1; 再按调时键调小时个位,此时,按加1键小时加1,按减1键小时减1; 再按调时键退出调时状态,进入正常显示。 2). 按下闹铃设定键 若为闹铃时间设定状态,则依次进入分钟个位、小时个位的设定,再按,闹铃时 间设定完成并恢复正常时间显示功能; 不为闹铃时间设定状态,则闹铃开关标志取反,取反后,若为关闹铃,显示“00: 00:-0”1s后恢复正常计时功能。若为开闹铃,则进入闹铃分钟个位设定状态; 闹铃时间设定期间显示“**:**: -1”,被调时间闪烁显示,此时,按加1键被 调时间加1,按减1键减1。 2).系统程序流程图 系统程序包括主程序、显示程序、键盘扫描及按键功能程序、时钟计时中断服务程序和调时闪烁显示程序。 开始调时键按下?Y显示延时等待按键释放进入调时程序N闹铃设定键按下?Y显示延时等待按键释放进入闹铃设定程序开始N修改时间?N初始化变量Y初始化定时器加1键按下?Y显示延时等待按键释放进入时间加1程序N动态显示减1键按下?Y显示延时等待按键释放进入时间减1程序键盘扫描及按键功能处理N结束图2-2-5 系统主程序流 图2-2-6 键盘扫描程序流程 23 ①. 主程序 主程序完成初始化工作后,循环调用显示子程序和键盘扫描子程序,程序流程如图2-2-5。 ②. 键盘扫描及按键功能程序 键盘扫描程序可分为时间调节程序、闹铃设定程序、时间加1程序和时间减1程序几个模块程序流程分别如图2-2-6、2-2-7、2-2-8、2-2-9和2-2-10。注意:在进行键盘扫描期间,为了一直保持时间的显示,在延时去抖及按键等待释放期间调用显示扫描程序来实现延时。 开始在调闹钟吗?N调节单元为闪烁关显示吗?Y交换调时内容Ncon指向调时单元关T0,停止计时Y开T1,用于闪烁计时adj_clock=1,表示当前调时con=6?(表示结束调时)NY开T0,开启计时关T1,停止闪烁计时adj_clock=0,表示调时结束结束图2-2-7 调时键功能程序 24 开始在调时吗?N显示闹铃标志有效为调闹钟时间状态?N闹铃开关标志取反Y闹铃开?NY显示“**:**:-1”显示“**:**:-0”1s调节单元为闪烁关显示吗?YY交换调时内容N开T1,用于闪烁计时adj_clock=2,表示当前调闹铃时间con=6?(表示结束调时)NY关T1,停止闪烁计时adj_clock=0,表示调时结束结束图2-2-8 闹铃设定键功能程序 准备准备修改实时时间?Ytimer[con]+1进位调整更新显示内容修改实时时间?Ytimer[con]-1借位调整更新显示内容Yclock[con]+1进位调整更新显示内容Yclock[con]-1借位调整更新显示内容结束结束图2-2-9 加1按键功能程序 ③. 变量定义 变量名 timer[6] clock[6] disp[8] dis_7[12] dis_loc[6] con_50ms con adj_clock con04s DP clock_on disp_clock 数据类型 usgined char数组 usgined char数组 usgined char数组 usgined char数组 usgined char数组 usgined char usgined char usgined char usgined char sbit bit bit 图2-2-10 减1按键功能程序 变量含义 存放实时时间 存放闹铃时间 显示缓冲区,其中后两个元素用于闪烁显示 ‘0—9’、不显及‘-’显示代码 位选数组 50ms循环次数 调时偏移变量,用于调时单元选择 调时状态标志。0,不调时;1,调实时时间; 2调闹铃时间 闪烁计时50ms循环次数 小数点,定义为P0.7 闹铃开关标志。1,开闹铃;0,关闹铃 显示内容标志。1,显闹铃时间;0,显实时 时间 ④. 系统源程序 #include #define uchar unsigned char #define uint unsigned int data uchar timer[6]={0x00,0x00,0x00,0x00,0x00,0x00}; //存放实时时间 data uchar clock[6]= {0x00,0x00,0x00,0x00,0x00,0x00}; //存放闹铃时间 data uchar disp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00};//显示缓冲区 code uchar dis_7[12]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40}; code uchar dis_loc[6]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf}; //位选编码 25 data uchar con_50ms=0X00,con=0x00,adj_clock=0x00,con04s=0x00; sbit DP=P0^7; //小数点 bit clock_on=0,disp_clock=0; /*********************初始化程序**********************/ clearmen() { uint i; for(i=0;i<6;i++) disp[i]=timer[i]; TH0=0x3C;TL0=0xB0; //定时器0实时时钟计时初始化 TH1=0x3C;TL1=0xB0; //定时器调时闪烁计时初始化 TMOD=0X11;ET0=1;TR0=1;EA=1;PT0=1; //置定时器中断为高优先级 }/*****************1毫秒延时程序*****************/ delay1ms(uint t) { uint i,j; for(i=0;i uchar k; for(k=0;k<6;k++) { P2=dis_loc[k]; //送位选,依次选中6个数码管 P0=dis_7[disp[k]]; //被显示数据存放在disp[k]中 if(k==2||k==4) { DP=1; //显示小数点 } delay1ms(1); //延时1ms } } /********************键盘扫描程序*********************/ void key_scan() { uchar i,k,p,temp; disp_scan(); P1=0XFE; temp=P1&0xF0; if(temp!=0xF0) 26 { disp_scan(); disp_scan(); //延时去抖 P1=0XFE; temp=P1&0xF0; if(temp!=0xF0) switch(temp) { case 0x70: { while(temp==0x70){disp_scan(); temp=P1&0xf0;} if(adj_clock!=2) //在调闹钟时间吗? { if(disp[con]==10) { disp[7]=disp[con]; disp[con]=disp[6]; disp[6]=disp[7]; } //闪烁显示 con+=2;adj_clock=0x01;TR0=0;ET0=0;TR1=1;ET1=1; if(con>=6) {con=0;TR1=0;ET1=0;TR0=1;ET0=1;adj_clock=0x00;} } }break; case 0xb0: { while(temp==0xB0){disp_scan();temp=P1&0xf0;} if(adj_clock!=1) //在调时吗? { disp_clock=1; if(con==0){clock_on=~clock_on;} if(clock_on==1) { for(i=2;i<6;i++)disp[i]=clock[i]; disp[0]=1;disp[1]=11; if(disp[con]==10) { disp[7]=disp[con]; disp[con]=disp[6]; disp[6]=disp[7]; } //闪烁显示 con+=2;adj_clock=0x02;TR1=1;ET1=1; if(con>=6) {con=0;TR1=0;ET1=0;adj_clock=0x00;disp_clock=0;} } else { adj_clock=0x00; for(k=2;k<6;k++)disp[k]=clock[k]; disp[0]=0;disp[1]=11; //延时显示1s**:**:-0,关闹铃 for(p=0;p<100;p++)disp_scan(); 27 disp_clock=0; } } } } } if(adj_clock!=0X00) disp_scan(); P1=0XFD; temp=P1; temp=temp&0xF0; if(temp!=0xF0) { disp_scan(); disp_scan(); //延时去抖 P1=0XFD; temp=P1&0xF0; if(temp!=0xF0) switch(temp) { case 0X70: { while(temp==0x70){disp_scan();temp=P1&0xF0; } if(adj_clock==1) //调实时时间加1 { timer[con]++; if(timer[con]==10) {timer[con]=0;timer[con+1]++;} if(con==2) {if(timer[con+1]==6)timer[con+1]=0;} else {if(timer[con+1]==2&&timer[con]==4) {timer[con]=0;timer[con+1]=0;} } disp[con]=timer[con];disp[con+1]=timer[con+1]; disp[6]=0x0A; } else if(adj_clock==2) { clock[con]++; //调闹铃时间加1 if(clock[con]==10) {clock[con]=0;clock[con+1]++;} if(con==2) {if(clock[con+1]==6)clock[con+1]=0;} else if(clock[con+1]==2&&clock[con]==4) 28 {clock[con]=clock[con+1]=0;} disp[con]=clock[con];disp[con+1]=clock[con+1]; disp[6]=0x0A; } }break; case 0XB0: { while(temp==0xB0){disp_scan();temp=P1&0xF0;} if(adj_clock==1) { timer[con]--; //调实时时间减1 if(con==2) { if(timer[con]==0xff) {timer[con]=9;timer[con+1]--;} {if(timer[con+1]==0xff)timer[con+1]=5;} } else { if(timer[con]==0xff&&timer[con+1]==0x00) {timer[con]=3;timer[con+1]=2;} else if(timer[con]==0xff) {timer[con]=9;timer[con+1]--;} } disp[con]=timer[con];disp[con+1]=timer[con+1]; disp[6]=0x0A; } else if(adj_clock==2) //调闹铃时间减1 { clock[con]--; if(con==2) { if(clock[con]==0xff) {clock[con]=9;clock[con+1]--;} {if(clock[con+1]==0xff)clock[con+1]=5;} } else { if(clock[con]==0xff&&clock[con+1]==0x00) {clock[con]=3;clock[con+1]=2;} else if(clock[con]==0xff) {clock[con]=9;clock[con+1]--;} } disp[con]=clock[con];disp[con+1]=clock[con+1]; disp[6]=0x0A; } } } 29 } } /***********************主程序************************/ main() { clearmen(); while(1) { key_scan(); } } /*******************1秒中断处理程序*******************/ void time_intt0(void) interrupt 1 { char q; TH0=0x3C;TL0+=0xB0; //考虑程序跳转等耗时 con_50ms++; if(con_50ms==20) { con_50ms=0x00; timer[0]++; if(timer[0]>=10) { timer[0]=0;timer[1]++; if(timer[1]>=6) { timer[1]=0;timer[2]++; if(timer[2]>=10) { timer[2]=0;timer[3]++; if(timer[3]>=6) { timer[3]=0;timer[4]++; if(timer[4]>=10) { timer[4]=0;timer[5]++; } if(timer[5]==2 ) { if(timer[4]==4) { timer[4]=0;timer[5]=0; } } } } } } if(disp_clock==0&&adj_clock!=2) {for(q=0;q<6;q++)disp[q]=timer[q];} 30 } } /***************0.4秒闪烁中断程序 **************/ void time_intt1(void) interrupt 3 { EA=0;TR1=0;TH1=0x3C;TL1=0xB0;TR1=1; con04s++; if(con04s==8) { con04s=0x00; disp[7]=disp[con];disp[con]=disp[6];disp[6]=disp[7]; } EA=1; } ⑤. 仿真结果 图2-2-11 调时及闹铃设定程序仿真 31 2.2.1.3 知识点小结 2.2.1.4 课后练习 2.2.2.1 2.2.2.2 2.2.2.3 2.2.2.4 2.2.2.5 2.2.2.6 2.2.2.7 32 子任务2.2.2 系统软件设计 矩阵键盘扫描子程序设计及仿真调试 时钟修改子程序设计及仿真调试 闹钟时间设定子程序设计及仿真调试 整点及闹钟声音报警子程序设计仿真调试 系统软硬件联合仿真调试 知识点小结 课后练习 项目三 数字电压表设计 任务3.1 电压采集、并口驱动液晶显示系统设计 子任务3.1.1 电压采集、并口驱动液晶显示电路设计 3.1.1.1 电压采集电路设计 1.电压采集原理 2.A/D转换概述 3.ADC0809工作原理 4.ADC0809电路设计 3.1.1.2 电压的并口驱动液晶显示电路设计 1. 认识液晶显示器 2. 1602液晶显示接口电路设计 3.1.1.3 知识点小结 3.1.1.4 课后练习 子任务3.1.2 电压采集、并口驱动液晶显示软件设计 33 3.1.2.1 电压采集子程序设计及仿真调试 3.1.2.2 电压显示子程序设计及仿真调试 3.1.2.3 系统的软硬件联合仿真调试 3.1.2.4 知识点小结 3.1.2.5 课后练习 任务3.2 电压的I2C驱动液晶显示系统设计 子任务3.2.1 IC2串口驱动液晶显示器电路设计 3.2.1.1 认识I2C 3.2.1.2 I2C接口电路设计 3.2.1.2 知识点小结 3.2.1.2 课后练习 34 子任务3.2.2 IC2串口驱动液晶显示器软件设计 3.2.2.1 认识I2C通信协议 3.2.2.2 电压的I2C驱动液晶显示软件设计 3.2.2.3 3.2.2.4 3.2.2.5 系统的软硬件联合仿真调试 知识点小结 课后练习 35 4.1.1.1 4.1.1.2 4.1.1.3 4.1.1.3 4.1.2.1 4.1.2.2 4.1.2.3 4.1.2.4 4.1.2.5 36 项目四 遥控窗帘系统设计 任务4.1 使窗帘动起来 子任务4.1.1 窗帘运动控制电路设计 认识步进电机 步进电机接口电路设计 知识点小结 课后练习 子任务4.1.2 窗帘运动控制软件设计 步进电机控制方式 步进电机控制软件设计 系统软硬件联合仿真 知识点小结 课后练习 任务4.2 红外遥控窗帘设计 子任务4.2.1 红外遥控电路设计 4.2.1.1 认识红外遥控装置 4.2.1.2 红外遥控接口电路设计 4.2.1.3 4.2.1.3 4.1.2.1 4.1.2.2 4.1.2.3 4.1.2.4 4.1.2.5 知识点小结 课后练习 子任务4.2.2 红外遥控软件设计 认识红外遥控通信制式 红外遥控窗帘软件设计 系统软硬件联合仿真 知识点小结 课后练习 37 附录1: 引脚功能及索引 38 附录2: 自制电路板 39 附录3: 寄存器索引 40 附录4: 8051系列单片机汇编指令速查表及索引 41 附录5: C51头文件 42 附录6: 常用51系列单片机速查表 43 常用网站 www.51c51.com www.icpdf.com 44 附录7: Protuse器件库速查 45 46 因篇幅问题不能全部显示,请点此查看更多更全内容