首页 单片机最小系统板实验指导书

单片机最小系统板实验指导书

举报
开通vip

单片机最小系统板实验指导书单片机最小系统板实验指导书 单片机实验板 工 程 训 练 指 导 书 2005年10月 1 目 录 实验一 LED闪烁灯设计-------------------------------------------------4 实验二 模拟开关控制指示灯设计---------------------------------------------7 实验三 多路开关状态指示设计---------------------------------------————10 实验四 广告灯左、右移设计-----...

单片机最小系统板实验指导书
单片机最小系统板实验指导书 单片机实验板 工 程 训 练 指 导 书 2005年10月 1 目 录 实验一 LED闪烁灯设计-------------------------------------------------4 实验二 模拟开关控制指示灯设计---------------------------------------------7 实验三 多路开关状态指示设计---------------------------------------————10 实验四 广告灯左、右移设计---------------------------------------14 实验五 查询法设计广告灯---------------------------------18 实验六 报警产生器设计---------------------------------------------21 实验七 I/O并行口直接驱动LED显示设计-----------------------------——25 实验八 单键识别设计---------------------------------------———29 实验九 一键多功能按键识别设计---------------------------------33 实验十 00-99计数器设计--------------------------------————38 实验十一 六十秒计时器设计------------------------——————————42 实验十二 可预置可逆4位计数器设计-----------------------------------46 实验十三 动态数码显示设计---------------------------------------51实验十四 4×4矩阵式键盘识别设计--------------------------------55 实验十五 定时计数器T0作定时应用设计(一)----------------------64 实验十六 定时计数器T0作定时应用设计(二)——----------------------71 实验十七 9.9秒跑马表设计------------------------------------------76 实验十八 “嘀、嘀、„„”报警声设计---------------------------------82 实验十九 “叮咚”门铃设计-------------------------------------------87 实验二十 智能电子钟设计---------------------------------------------92 实验二十一 “新年好”音乐设计-----------------------------------------------102 实验二十二 电子琴设计-------------------------------------------------108 实验二十三 模拟计算器数字输入及显示设计-------------------------119 实验二十四 数字电压表设计--------------------——-------------------------126 实验二十五 DS18B20数字温度计设计---------------------------------131 附录A实验板中模拟/数字转换器ADC0804的参数及使用说明------------------------139 附录B 实验板中DS18B20智能温度控制器的参数及使用----------------------------141 2 单片机实验板详细说明 该单片机实验板设计巧妙,经过了严格的检查,可放心使用。 由于考虑到众多的实验要在此单片机实验板上完成,然而每个实验用到的单片机的I/O口不尽相同,所以设计时采用拨动拨码开关和替换跳线帽的位置来完成每个实验内容。 在完成各个实验内容时,首先要看清楚实验 电路 模拟电路李宁答案12数字电路仿真实验电路与电子学第1章单片机复位电路图组合逻辑电路课后答案 原理图,然后按照实验内容给出的单片机实验板上的硬件连线、拨动拨码开关或替换跳线帽的位置来完成系统设计。检查无误后下载程序。由于每个程序都经过了单片机实验板的验证,证明程序没有问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 。所以要是调不出来,肯定是硬件没有连好,再次检查直到完成实验。每做完一个实验后,把拨动拨码开关和跳线帽恢复到初始状态。 一、拨码开关和跳线帽的初始化状态介绍如下: 单片机实验板上有8联拨动拨码开关4个(JP1、JP2、JP3、JP4),2联拨动拨码开关1个(JP5),跳线帽13个。 在初始化状态下,拨动拨码开关都处于紧靠数字的位置,此位置下的拨动拨码开关为不用状态。8排针接插件J3上的8个跳线帽要全部连接在标号为P0位置上。单排针接插件J4上的跳线帽要连接在OE和GND的位置上。单排针接插件J5上的跳线帽连接在OE和GND的位置上。单排针接插件J6上的跳线帽要连接在OE和VCC的位置。单排针接插件J7上的跳线帽要连接在CS和GND的位置。双排针接插件J8上的跳线帽应该和J8上排插针相连。4个8联拨动拨码开关(JP1、JP2、JP3、JP4)应该全部所至下方。 二、实验中具体使用介绍如下: (1)当用到发光二极管时,要把8联拨动拨码开关JP4拨到ON状态。 (2) 当用到喇叭输出时,把2联拨动拨码开关JP5的1号拨动开关拨上去;当用DS18B20做测温时,把2联拨动拨码开关JP5的2号拨动开关拨上去。 (3)当用到矩阵键盘输入时,把8联拨动拨码开关JP3的拨动开关全部拨上去。 (4) 当用到拨动开关SW1—SW4时,把8联拨动拨码开关JP2对应的拨动开关拨上去。 (5) 当用到按键开关S18—S21时,把8联拨动拨码开关JP2对应的拨动开关拨上去。 (6) 当用8个动态数码管显示时,首先应该把单排针接插件J4的OE与VCC用跳线帽相连。同时8联拨动拨码开关JP1对应的拨动开关拨上去。8联拨动拨码开关JP1的S1—S8分别对应三极管Q2—Q9。 (7)当用8个动态数码管输入a—h数码时,如果用到P0口,不用移动跳线帽;如果用到P1口,把8个跳线帽移到下面的标有P1的位置。 (8) 当用P0口做数码管静态显示时,把单排针接插件J5的OE与VCC用跳线帽相连。 (9) 当用P2口做数码管静态显示时,把单排针接插件J6的OE与GND用跳线帽相连。 总之,在用单片机编写简单程序时,汇编语言编写起来比较简单,但复杂的程序还是用 编程是必学的。这里基本上所有的实验程序都采用汇编和C51编写起来比较简单。所以C51 C51两种编程 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 。有的实验还给出了两套 设计方案 关于薪酬设计方案通用技术作品设计方案停车场设计方案多媒体教室设计方案农贸市场设计方案 ,便于比较学习。 3 实验一 LED闪烁灯设计 一、实验目的 1、初步了解单片机I/O口的简单控制。 2、掌握单片机外围常用电路的固定接法。 二、设计原理 利用单片机控制一个发光二极管,使此发光二极管间隔0.2秒亮、灭一次。 三、参考电路 图1.1 LED闪烁灯外部电路原理图 四、电路硬件说明 如图1.1所示:在单片机的P1.0端口上通过8联拨动拨码开关JP4的相应拨码开关连接一个发光二极管D1。 序设计内容 五、程 (1) 延时程序的设计方法 : 单片机指令的执行时间是很短的,它的数量级为微秒级。在本程序设计中,要求LED闪烁灯的闪烁时间间隔为0.2秒。相对于微秒来说,相差太大,所以在执行某一指令时,需要插入延时程序,来达到的要求。然而这样的延时程序是如何设计呢,下面具体介绍其原理: 如图1.1所示,单片机所用的石英晶体为12MHz。因此,1个机器周期为1微秒。 延时10ms子程序 机器周期 微秒 MOV R6,#20 1个 1 D1: MOV R7,#248 1个 1+1×20 DJNZ R7,$ 2个 2×248+2×20×248 4 DJNZ R6,D1 2个 2×20 因此,上面的延时程序时间为10.478ms。 由以上可知,当R6,10、R7,248时,延时时间为5ms;R6,20、R7,248时,延时时间为10ms。通常所用延时时间以此为基本的计时单位。比如本实验要求为0.2秒,200ms,所以用10ms×R5,200ms,得到R5,20。延时子程序如下: DELAY: MOV R5,#20 1 MOV R6,#20 1+20 D1: D2: MOV R7,#248 1+20+20(1+20) DJNZ R7,$ 2×248+20×2×248+20(2×248+20×2×248) DJNZ R6,D2 2×20+2×20×20 DJNZ R5,D1 2×20 RET 2 上面的延时程序为0.220081s。 (2)单片机的 P1.0端口的输出控制方法: 如图1.1所示,根据发光二极管的单向导电性,当单片机的P1.0端口输出高电平,即P1.0,1时,发光二极管D1熄灭;当单片机的P1.0端口输出低电平,即P1.0,0时,发光二极管D1亮。可以使用SETB P1.0指令使单片机的P1.0端口输出高电平,使用CLR P1.0指令使单片机的P1.0端口输出低电平。 六、程序流程图(如图1.2所示) 图1.2 LED闪烁灯设计流程图 七、汇编源程序 ORG 0000H ;系统复位 LJMP START ;转入主程序 ORG 0003H ;外部中断0 RETI ;中断返回 ORG 000BH ;定时器0溢出中断 RETI 5 ORG 0013H ;外部中断1 RETI ORG 001BH ;定时器1溢出中断 RETI ORG 0023H ;外部中断2 RETI ORG 0100H START: CLR P1.0 ;和P1.0口接的二极管亮 LCALL DELAY200MS ;延时0.2秒 SETB P1.0 ;和P1.0口接的二极管灭 LCALL DELAY200MS ;延时0.2秒 LJMP START ;循环 DELAY200MS: MOV R5,#20 ;延时子程序 D1: MOV R6,#20 D2: MOV R7,#248 DJNZ R7,$ DJNZ R6,D2 DJNZ R5,D1 RET END 八、C语言源程序 #include sbit L1=P1^0; void delay02s(void) //延时子程序// { unsigned char i,j,k; for(i=20;i>0;i--) for(j=20;j>0;j--) for(k=248;k>0;k--); } void main(void) //主程序// { while(1) //进入循环// { L1=0; //指示灯亮// delay02s(); //延时0.2秒// L1=1; //指示灯灭// delay02s(); //延时0.2秒// } } 九、注意事项 (1)用Keil软件时,注意中文说明及注释。 (2) 用汇编语言编写程序时不区分大小写,但用C语言编写程序时注意区分大小写。 (3)汇编语言和C语言定义口的方式不同,如汇编语言为P1.0,P2.0,P3.0,而C语 言为P1_0 ,P2_0 ,P3_0。 6 实验二 模拟开关控制指示灯设计 一、实验目的 1、掌握单片机外围常用电路的固定接法。 2、掌握单片机利用模拟开关控制指示灯的简单设计。 二、设计原理 如图2.1所示,用发光二极管监视模拟开关的状态。如果模拟开关合上,发光二极管点亮;如果模拟开关打开,发光二极管熄灭。 三、参考电路 图2.1 模拟开关控制指示灯原理图 四、电路硬件说明 如图2.1所示,模拟开关SW1通过8联拨动拨码开关连接在单片机的P3.0端口上,用发光二极管D1(通过8联拨动拨码开关接在单片机的P1.0端口上)显示模拟开关SW1的状态。当模拟开关SW1断开时,单片机的P3.0端口为高电平;当模拟开关闭合时,单片机的P3.0端口为低电平。 五、程序设计内容 (1)开关状态的检测过程 对于单片机来说,开关状态的检测是从单片机的P3.0端口输入信号,然而输入的信号只有高、低电平两种。当拨动开关SW1拨上去(输入高电平)时,拨动开关SW1断开;当拨动开关SW1拨下来(输入低电平)时,拨动开关SW1闭合。单片机可以采用JB BIT或者JNB BIT指令来完成对拨动开关状态的检测。 (2)输出控制 7 如图2.1所示,当单片机的P1.0端口输出为高电平,即P1.0,1时,根据发光二极管的单向导电性可知,这时发光二极管D1熄灭;当单片机的P1.0端口输出为低电平,即P1.0,0时,发光二极管D1亮。可以使用SETB P1.0指令使单片机的P1.0端口输出高电平,使用CLR P1.0指令使单片机P1.0端口输出低电平。 六、程序流程图(如图2.2所示) 图2.2 模拟开关控制指示灯程序流程图 七、汇编源程序 ORG 0000H ;程序复位入口地址 LJMP START ;跳到主程序 ORG 0003H ;外部中断0入口地址 RETI ;中断返回 ORG 000BH ;定时器中断0入口地址 RETI ;中断返回 ORG 0013H ;外部中断1入口地址 RETI ;中断返回 ORG 001BH ;定时器中断1入口地址 RETI ;中断返回 ORG 0023H ;串行口中断入口地址 RETI ;中断返回 ORG 002BH ;定时器中断2入口地址 RETI ;中断返回 ORG 0100H START: JB P3.0,NEX ;P3.0为1,则跳NEX CLR P1.0 ;P1.0亮 SJMP START NEX: SETB P1.0 ;P1.0灭 SJMP START END 八、C语言源程序 8 #include main() { if(P3_0==1) { P1_0=0; //P1_0亮// } else { P1_0=1; //P1_0灭// } } 九、注意事项 如果程序下载到实验板上后,要把8联拨动拨码开关JP2和JP4的相应开关合上去。 9 实验三 多路开关状态指示设计 一、实验目的 利用多路模拟开关进行指示灯控制。 二、设计原理 如图3.1所示,单片机的P1.0,P1.3端口通过8联拨动拨码开关连接四个发光二极管D1,D4。单片机的P3.0,P3.3端口通过8联拨动拨码开关连接四个拨动开关SW1,SW4。编程时将拨动开关的状态反映到发光二极管上(开关闭合,对应的灯亮,开关断开,对应的灯灭)。 三、参考电路 图3.1 多路开关状态指示电路原理图 四、电路硬件说明 如图3.1所示,拨动开关SW1、SW2、SW3、SW4通过8联拨动拨码开关JP2接连单片机的P3.0、P3.1、P3.2、P3.3端口。单片机的P1.0、P1.1、P1.2、P1.3口通过8联拨动拨码开关JP4分别连接四个指示灯D1、D2、D3、D4。 五、程序设计内容 10 (1)开关状态检测 拨动开关状态的检测,对于单片机来说,是一种输入关系,轮流检测每个开关的状态,根据每个开关的状态让相应的发光二极管指示显示。在编写程序时,可以使用 JB P3.X或JNB P3.X指令来完成指示控制。 (2)单片机的输出控制 根据拨动开关SW1、SW2、SW3、SW4的状态,经由发光二极管D1,D4来指示显示。在编 可以用SETB P1.X和CLR P1.X指令来完成。 写程序时, 六、程序流程图(如图3.2所示) 图3.2 多路开关状态指示流程图 七、汇编源程序 ORG 0000H ;程序复位入口地址 LJMP START ;跳到主程序 ORG 0003H ;外部中断0入口地址 RETI ;中断返回 ORG 000BH ;定时器中断0入口地址 RETI ;中断返回 ORG 0013H ;外部中断1入口地址 RETI ;中断返回 ORG 001BH ;定时器中断1入口地址 RETI ;中断返回 ORG 0023H ;串行口中断入口地址 RETI ;中断返回 ORG 0100H START: LCALL KAIGUAN ;调用检测开关状态子程序 LJMP START ;跳回继续检测 KAIGUAN: JB P3.0,N1 ;判断p3.0是否按下 CLR P1.0 ;p3.0按下则亮p1.0 SJMP M1 ;跳到 m1 11 N1: SETB P1.0 ;p3.0没有按下则灭p1.0 M1: JB P3.1,N2 ;判断p3.1是否按下 CLR P1.1 ;p3.1按下则亮p1.1 SJMP M2 ;跳到 m2 N2: SETB P1.1 ;p3.1没有按下则灭p1.1 M2: JB P3.2,N3 ;判断p3.2是否按下 P1.2 ;p3.2按下则亮p1.2 CLR SJMP M3 ;跳到 m3 N3: SETB P1.2 ;p3.2没有按下则灭p1.2 M3: JB P3.3,N4 ;判断p3.3是否按下 CLR P1.3 ;p3.3按下则亮p1.3 SJMP M4 ;跳到 m4 N4: SETB P1.3 ;p3.3没有按下则灭p1.3 M4: LJMP KAIGUAN ;跳回检测开关状态子程序进行循环 RET ;子程序返回 END ;结束 八、C语言源程序 #include main() { if(P3_0==0) { P1_0=0; } else { P1_0=1; } if(P3_1==0) { P1_1=0; } else { P1_1=1; } if(P3_2==0) { P1_2=0; } else { P1_2=1; } if(P3_3==0) { P1_3=0; } else {P1_3=1; } 12 } 九、注意事项 (1)程序下载到实验板上后,要把8联拨动拨码开关JP2和JP4的相应按键合上去。 (2)与8联拨动拨码开关JP4相连的指示灯是高电平亮,低电平灭。 13 实验四 广告灯左、右移设计 一、实验目的 1.初步了解广告灯的移动设计。 2.掌握循环移动的原理。 二、设计原理 如图4.1所示,八个发光二极管D1,D8通过8联拨动拨码开关JP4分别连接在单片机的P1.0,P1.7端口上,做单一灯的左移右移。如果单片机的P1端口输出为“0”时,发光二极管亮,依次为P1.0?P1.1?P1.2?P1.3???P1.7?P1.6???P1.0亮,重复循环。 三、参考电路 图4.1 广告灯左、右移设计电路原理图 四、电路硬件说明 把“单片机系统”区域中的单片机的P1.0,P1.7端口通过8联拨动拨码开关JP4连接到“八路发光二极管指示模块”区域中的D1,D8端口上,要求:P1.0对应着D1,P1.1对应着D2,„„,P1.7对应着D8。 五、程序设计内容 运用输出端口指令MOV P1,A或MOV P1,,DATA,给累加器值或常数值,然后执行上述的指令,即可达到输出控制的动作。 每次送出的数据是不同的,具体的数据如下表4.2所示 表4.2 8个LED循环显示真值表 P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0 说明 D8 D7 D6 D5 D4 D3 D2 D1 1 1 1 1 1 1 1 0 D1亮 1 1 1 1 1 1 0 1 D2亮 1 1 1 1 1 0 1 1 D3亮 1 1 1 1 0 1 1 1 D4亮 1 1 1 0 1 1 1 1 D5亮 14 1 1 0 1 1 1 1 1 D6亮 1 0 1 1 1 1 1 1 D7亮 0 1 1 1 1 1 1 1 D8亮 六、程序流程图(如图4.3所示) 图4.3 广告灯左右移程序流程图 七、汇编源程序 ORG 0000H ;系统复位 LJMP START ;转入主程序 ORG 0003H ;外部中断0 RETI ;中断返回 ORG 000BH ;定时器0溢出中断 RETI ORG 0013H ;外部中断1 RETI ORG 001BH ;定时器1溢出中断 RETI ORG 0023H ;外部中断2 RETI ORG 0100H START: MOV R2,#7 MOV A,#0FEH SETB C ;给CY置1 LOOP: MOV P1,A LCALL DELAY RLC A ;带进位左移 DJNZ R2,LOOP ;R2减1不为0转到LOOP 15 MOV R2,#8 LOOP1: MOV P1,A LCALL DELAY RRC A ;带进位右移 DJNZ R2,LOOP1 ;R2减1不为0转到LOOP1 LJMP START DELAY: MOV R5,#20 ;延时0.2秒子程序 D1: MOV R6,#20 D2: MOV R7,#248 DJNZ R7,$ DJNZ R6,D2 DJNZ R5,D1 RET END 八、C语言源程序 #include unsigned char i; unsigned char temp; unsigned char a,b; void delay(void) //延时子程序// { unsigned char m,n,s; for(m=20;m>0;m--) for(n=20;n>0;n--) for(s=248;s>0;s--); } void main(void) { while(1) { temp=0xfe; P1=temp; delay(); for(i=1;i<8;i++) { a=temp<>(8-i); //向右移8-i位// P1=a|b; //a或b// delay(); } for(i=1;i<8;i++) { a=temp>>i; b=temp<<(8-i); P1=a|b; delay(); } } 16 } 九、注意事项 (1)程序下载到实验板上后,要把8联拨动拨码开关JP4的相应按键合上去。 (2)用C语言编写程序,利用左移和右移指令时,移入单元的数为0。 (3)在硬件电路中,发光二极管和电源之间必须加上合适的电阻。 17 实验五 查询法设计广告灯 一、实验目的 1.熟悉广告灯的移动设计。 2.掌握查询法在单片机编程中的使用。 二、设计原理 利用取表的方法,使单片机的P1端口做单一灯的变化:左移2次,右移2次,闪烁2 次(间隔的时间为0.2秒)。 三、参考电路 图5.1 查询设计广告灯电路原理图 四、电路硬件说明 在“单片机系统”区域中,把单片机的P1.0,P1.7端口通过8联拨动拨码开关JP4连接到“八路发光二极管指示模块”区域中的D1,D8端口上。要求:P1.0对应D1,P1.1对应D2,„„,P1.7对应D8。 五、程序设计内容 在利用表格进行程序设计时,要用以下的指令来完成: (1) 利用MOV DPTR,,DATA16指令使数据指针寄存器指到数据表格的首地址。 (2) 利用MOVC A,,A,DPTR指令,根据累加器A的值再加上DPTR的值,就可以使程序计数器PC指针指到表格内所需要取出的数据。因此,只要把控制码组建 图5.2 查询法设计广告灯流程图 18 成一个表格,利用MOVC A,,A,DPTR做取控制码的操作,就可方便地处理一些复杂的控 制动作。 六、程序流程图(如图5.2所示) 七、汇编源程序 ORG 0000H ;系统复位 LJMP START ;转入主程序 ORG 0003H ;外部中断0 RETI ;中断返回 ORG 000BH ;定时器0溢出中断 RETI ORG 0013H ;外部中断1 RETI ORG 001BH ;定时器1溢出中断 RETI 0023H ;外部中断2 ORG RETI ORG 0100H START: MOV DPTR, #TABLE ;把表格首地址给DPTR LOOP: CLR A ;A赋0 MOVC A,@A+DPTR ;查表得值送给A中 CJNE A,#01H,LOOP1 ;比较A等于#01,程序结束;否则跳转 SJMP START LOOP1: MOV P1,A ;把A送入P1口 LCALL DELAY1 ;调用延时 INC DPTR ;DPTR加1 SJMP LOOP DELAY1: MOV R3,#20 ;延时0.2S子程序 DELAY: MOV R4,#20 D1: MOV R5,#248 DJNZ R5,$ DJNZ R4,D1 DJNZ R3,DELAY RET TABLE: DB 0FEH,0FDH,0FBH,0F7H ;数据表格 DB 0EFH,0DFH,0BFH,07FH DB 0FEH,0FDH,0FBH,0F7H DB 0EFH,0DFH,0BFH,07FH DB 07FH,0BFH,0DFH,0EFH DB 0F7H,0FBH,0FDH,0FEH DB 07FH,0BFH,0DFH,0EFH DB 0F7H,0FBH,0FDH,0FEH DB 00H, 0FFH,00H, 0FFH DB 01H 19 END 八、C语言源程序 #include unsigned char code table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f, 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f, 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe, 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe, 0x00,0xff,0x00,0xff, 0x01};//数据数组// unsigned char i; //定义全局变量// void delay(void) //延时子程序// { unsigned char m,n,s; for(m=20;m>0;m--) for(n=20;n>0;n--) for(s=248;s>0;s--); } void main(void) { while(1) //循环// { if(table[i]!=0x01) //判断是否查完表格// { P1=table[i]; i++; delay(); } else { i=0; } } } 九、注意事项 (1)利用C语言编写程序时,一定要注意合局变量和局部变量的定义。 (2)利用汇编语言编写程序时,注意16位数据指针DPTR的用法。 20 实验六 报警产生器设计 一、实验目的 掌握利用单片机产生音频信号的方法。 二、设计原理 利用单片机产生1KHz的信号,并且让此信号响100ms;再利用单片机产生500Hz的信号,并且让此信号响200ms。同时让这两个信号交替产生。通过单片机的P1.0端口输出1KHz和500Hz的音频信号驱动扬声器,作为报警信号。单片机的 P3.0端口通过8联拨动拨码开关连接一拨动开关(如SW1)进行控制。拨动开关闭合时报警器报警,断开时报警器停止报警。 三、参考电路 图6.1 报警产生器原理图 四、电路硬件说明 把单片机的P1.0端口连接到“音频放大模块”区域中的SPK IN端口上;P3.0端口连接到“八路拨动开关”区域中的K1端口上,并在“音频放大模块”区域中的SPK OUT端口上接上一个8欧的或者是16欧的喇叭。 五、程序设计内容 500Hz信号周期为2ms,信号电平为每1ms取反1次,1KHz的信号周期为1ms,信号电平每500us取反1次,以此来产生报警信号。 六、程序流程图(如图6.2所示) 21 图6.2 报警产生器流程图 七、汇编源程序 FLAG BIT 00H 0000H ORG LJMP START ORG 0003H RETI ORG 000BH RETI ORG 0013H RETI ORG 001BH RETI ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序;;;;;;;;;; ORG 0100H START: LCALL BAOJING1 LCALL BAOJING2 LJMP START ;;;;;;;;;;500hz报警信号程序;;;;;;;;;; BAOJING1: MOV R2,#200 22 DV: CPL P1.0 LCALL DELAY500 LCALL DELAY500 DJNZ R2,DV RET ;;;;;;;;;;1khz报警信号程序;;;;;;;;;; R2,#200 BAOJING2: MOV DV1: CPL P1.0 LCALL DELAY500 DJNZ R2,DV1 RET ;;;;;;;;;;500us延时程序;;;;;;;;;; DELAY500: MOV R7,#249 LOOP: DJNZ R7,LOOP RET ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序 #include #include unsigned char count; void dely500(void) //延时子程序// { unsigned char i; for(i=250;i>0;i--) { _nop_(); } } void main(void) { while(1) //程序循环// { if(P3_0==0) //判断P3.0是否按下// { for(count=200;count>0;count--) { P1_0=~P1_0; dely500(); } for(count=200;count>0;count--) { P1_0=~P1_0; dely500(); dely500(); } } } } 23 九、注意事项 (1)程序下载后,一定要把8联拨动拨码开关JP5的第一个开关拨上去。 (2)程序下载后,要把8联拨动拨码开关JP3拨下,8联拨动拨码开关JP2拨上去。 24 实验七 I/O并行口直接驱动LED显示设计 一、实验目的 1.了解静态数码管的显示方法。 2.掌握共阴极数码管和共阳极数码管的接法以及区别。 二、设计原理 如图7.1所示,利用单片机P0端口的P0.0,P0.7连接到一个共阴数码管DS1的a,h的笔段上,数码管的公共端接地。在数码管上循环显示0,9数字,显示时间间隔为0.2秒。 三、参考电路 图7.1 I/O并行口直接驱动LED显示电路原理图 四、电路硬件说明 在“单片机系统”区域中,把单片机的P0.0,P0.7端口连接到静态数码管DS1上的a,h端口上;要求:P0.0与a相连,P0.1与b相连,P0.2与c相连,„„,P0.7与h相连。 五、程序设计内容 (1)LED数码显示原理: LED数码管内部由七个条形发光二极管和一个小圆点发光二极管组成,根据发光二极管的连接形式,可分为共阴极型和共阳极型。 LED数码管的a-g七个发光二极管加正向电压导通发亮,加反向电压截止熄灭。不同亮暗的二极管组合形成不同的字形,这种组合称之为字形码。见表7.2为共阴极数码管的字形码表。 25 (2)由于数码管显示数字0,9的字形码没有规律,只能采用查表的方式来完成所需要的要求。这样按着数字0,9的顺序,把每个数字的笔段代码按顺序排好并建立的表格如下所示:TABLE DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH 表7.2 共阴极的字形码表 “0” 3FH “8” 7FH “1” 06H “9” 6FH “2” 5BH “A” 77H “3” 4FH “b” 7CH “4” 66H “C” 39H “5” 6DH “d” 5EH “6” 7DH “E” 79H “7” 07H “F” 71H 六、程序流程图(如图7.3所示) 图7.3 I/O并行口直接驱动LED显示流程图 七、汇编源程序 ORG 0000H LJMP START ORG 0003H RETI ORG 000BH RETI ORG 0013H RETI ORG 001BH RETI 26 ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序;;;;;;;;;; ORG 0100H START: LCALL XIANSHI LJMP START ;;;;;;;;;;显示程序;;;;;;;;;; XIANSHI: MOV R1,#00H NEXT: MOV A,R1 MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A LCALL DELAY INC R1 CJNE R1,#10,NEXT RET ;;;;;;;;;;200ms延时程序;;;;;;;;;; DELAY: MOV R5,#20 MOV R6,#20 D1: D2: MOV R7,#248 DJNZ R7,$ DJNZ R6,D2 DJNZ R5,D1 RET ;;;;;;;;;;数码译码表;;;;;;;;;; TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序 #include unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; void delay200ms(void) //延时0.2秒的程序// { unsigned char i,j,k; for(i=20;i>0;i--) { for(j=20;j>0;j--) { for(k=248;k>0;k--); } } } void main(void) 27 { unsigned char a; while(1) { for(a=0;a<10;a++) { P0=table[a]; //取表中的数给P0口// delay200ms(); //每0.2秒显示一个数码// } } } 九、注意事项 1.当数码管显示数码时,一定要分清共阴极和共阳极。 2.下载程序后一定要把单排针接插件J5的跳线帽加到OE/VCC端。 28 实验八 单键识别设计 一、实验目的 1.了解按键识别方法。 2.掌握按键的消抖方法。 了解加法计数的原理。 3. 二、设计原理 每按下一次按键开关S18,计数值加1,然后通过和单片机的P1端口相连的“八路发光二极管指示模块”区域中的D1,D8显示出相应的二进制计数值。 三、参考电路 图8.1 单键识别电路原理图 四、电路硬件说明 (1)在“单片机系统”区域中,把单片机的P3.7端口通过8联拨动拨码开关JP2连接到“独立式键盘”区域中的S18端口上。 29 (2)在“单片机系统”区域中,把单片机的P1.0,P1.7端口通过8联拨动拨码开关JP4连接到“八路发光二极管指示模块”区域中的“D1,D7”端口上;要求,P1.0连接发光二极管D1,P1.1连接发光二极管D2,P1.2连接发光二极管D3,P1.3连接发光二极管D4,P1.4连接发光二极管D5,P1.5连接发光二极管D6,P1.6连接发光二极管D7,P1.7连接发光二极管D8。 五、程序设计内容 (1)作为一个按键,完整的过程是从没有按下到按下再到释放。也就是说,当按下一个按键时,某个命令只执行一次,然而在按键按下的过程中,不允许有干扰进来。因为,在按下的过程中,一旦有干扰过来,可能造成误触发过程,这不是所想要的。因此在按键按下的时候,就要把手动造成的干扰信号以及按键的机械接触等干扰信号滤除掉。一般情况下,可以采用电容来滤除掉这些干扰信号,但实际上,这会增加硬件成本及硬件电路的体积,因此采用软件滤波的方法去除这些干扰信号。一般情况下,一个按键按下的时候,总是在按下的时刻存在着一定的干扰信号,按下之后就基本上进入了稳定的状态。具体的一个按键从按下到释放的全过程的信号图如下图8.2所示: 图8.2 干扰信号示意图 从图中可以看出,在程序设计时,从按键被识别按下之后,延时5ms以上,从而避开了干扰信号区域。再来检测一次,看按键是否真得已经按下,若真得已经按下,这时肯定输出为低电平。如果这时检测到的是高电平,证明刚才是由干扰信号引起的误触发,CPU就认为是误触发信号而舍弃这次的按键识别过程。从而提高了系统的可靠性。 由于要求每按下一次,命令被执行一次,直到下一次再按下的时候,再执行一次命令,因此从按键被识别出来之后,就可以执行这次的命令。所以要有一个等待按键释放的过程,显然释放的过程,就是使其恢复成高电平状态。 图8.3(a) 按键识别流程图 30 (2)对于识别按键的指令,依然选择如下指令JB BIT,REL指令是用来检测BIT 是否为高电平,若BIT,1,则程序转向REL处执行程序,否则就继续向下执行程序。或者是 JNB BIT,REL指令是用来检测BIT是否为低电平,若BIT,0,则程序转向REL处执行程序,否则就继续向下执行程序。 六、程序设计流程图(如图8.3所示) (1)程序设计过程中按键识别过程的框图如图8.3(a)所示。 (2)按键控制程序流程图如图8.3(b)所示。 图8.3(b) 按键控制程序流程图 七、汇编源程序 ORG 0000H ;系统复位 LJMP START ;转入主程序 ORG 0003H ;外部中断0 RETI ;中断返回 ORG 000BH ;定时器0溢出中断 RETI ORG 0013H ;外部中断1 RETI ORG 001BH ;定时器1溢出中断 RETI ORG 0023H ;外部中断2 RETI ORG 0100H START: MOV R1,#00H ;初始化R7为0,从0开始计数 MOV A,R1 CPL A ;取反指令 MOV P1,A ;送出P1口由发光二极管显示 31 REL: JB P3.7,REL ;判断SP1是否按下 LCALL DELAY10MS ;若按下,则延时10ms左右 JB P3.7,REL ;再判断SP1是否真得按下 INC R1 ;若真得按下,则进行按键处理 MOV A,R1 ;计数内容加1,并送出P1口由 CPL A ;发光二极管显示 P1,A MOV JNB P3.7,$ ;等待SP1释放 SJMP REL ;继续对K1按键扫描 DELAY10MS: MOV R6,#20 ;延时10ms子程序 L1: MOV R7,#248 DJNZ R7,$ DJNZ R6,L1 RET END 八、C语言源程序 #include void delay10ms(void) //延时10毫秒// { unsigned char i,j; for(i=20;i>0;i--) { for(j=248;j>0;j--); } } void main(void) { unsigned char k; while(1) { if(P3_7==0) //看是否P3.7按下// { delay10ms(); //延时10毫秒// if(P3_7==0) //再看一遍是否真的按下// { k++; //如果按下,k记下按下的次数// if(k==256) //记到256次,k重0开始记// { k=0; } P1=~k; //由于是低电平亮,所以取反后再送P1口显示// while(P3_7==0); //判断P3.7是否弹起// } } } } 九、注意事项 (1)按键的识别一定要消除抖动干扰。 (2)键盘消抖所用的时间不少于5毫秒。 (3)下载结束后,拔掉下载线以防止P1端口对二极管的显示干扰。 32 实验九 一键多功能按键识别设计 一、实验目的 (1)了解按键识别方法。 (2)掌握一键多功能的设计原理。 二、设计原理 如图9.1所示,按键开关S18通过8联拨动拨码开关JP3接在单片机的P3.7管脚上,在单片机的P1端口接有四个发光二极管。上电的时候,接在P1.0管脚上的发光二极管D1在闪烁。当按下一次按键开关S18的时候,接在P1.1管脚上的发光二极管D2在闪烁。再按下按键开关S18的时候,接在P1.2管脚上的发光二极管D3在闪烁。第三次按下按键开关S18的时候,接在P1.3管脚上的发光二极管D4在闪烁。第四次按下按键开关S18的时候,回到D1闪烁,如此循环下去。 三、参考电路 图9.1 一键多功能识别技术电路原理图 四、电路硬件说明 (1)在“单片机系统”区域中,把单片机的P3.7端口连接到“独立式键盘”区域中的按键开关S18端口上。 33 (2)在“单片机系统”区域中,把单片机的P1.0,P1.4端口通过8联拨动拨码开关连接到“八路发光二极管指示模块”区域中的发光二极管“DL1,DL8”端口上;要求,P1.0连接D1,P1.1连接D2,P1.2连接D3,P1.3连接D4。 五、程序设计内容 (1)设计思想由来 很快认出。同在生活中,有张三、李四、王五、等等。由于每个人有不同的名子,就能样,对于要通过某个按键来识别其相应的功能,再给不同的功能模块赋予了不同的ID号标识。这样,每按下一次按键,ID就显不同的值,因此单片机就很容易识别不同功能的身份了。 (2)设计方法 从设计的原理可以看出,发光二极管D1到D4在每个时刻闪烁的时间是受按键开关S18来控制的。给发光二极管D1到D4闪烁的时段定义出不同的ID号,当D1在闪烁时,ID,0;当D2在闪烁时,ID,1;当D3在闪烁时,ID,2;当D4在闪烁时,ID,3;很显然,只要每次按下开关S18时,分别给出不同的ID号就能够实现所设计的要求了。 六、程序设计流程图(如图9.2所示)、 图9.2 一键多功能识别技术程序流程图 七、汇编源程序 ID EQU 30H ;定义相应的位 SP1 BIT P3.7 L1 BIT P1.0 34 L2 BIT P1.1 L3 BIT P1.2 L4 BIT P1.3 ORG 0000H ;系统复位 LJMP START ;转入主程序 ORG 0003H ;外部中断0 RETI ;中断返回 ORG 000BH ;定时器0溢出中断 RETI ORG 0013H ;外部中断1 RETI ORG 001BH ;定时器1溢出中断 RETI ORG 0023H ;外部中断2 RETI ORG 0100H ;程序入口地址 MOV ID,#00H START: JB SP1,REL ;判断按键是否按下 LCALL DELAY10MS ;延时消抖 JB SP1,REL ;再次判断 ;如果按下,用ID记下按键按下的次数 INC ID MOV A,ID CJNE A,#04,REL ;看按键是否按下4次 MOV ID,#00H ;如果是清0,重新记数 REL: JNB SP1,$ ;等待按键弹起 MOV A,ID CJNE A,#00H,IS0 ;是否第一次按下按键 SETB L4 ;如果是,第一指示灯显示 SETB L3 SETB L2 CPL L1 LCALL DELAY ;延时 SJMP START IS0: CJNE A,#01H,IS1 ;是否第二次按下按键 SETB L1 ;如果是第二个指示灯显示 CPL L2 LCALL DELAY SJMP START IS1: CJNE A,#02H,IS2 ;是否第三次按下按键 SETB L1 ;如果是第三个指示灯显示 SETB L2 CPL L3 LCALL DELAY SJMP START 35 IS2: CJNE A,#03H,IS3 ;是否第四次按下按键 SETB L1 ;如果是第四个指示灯显示 SETB L2 SETB L3 CPL L4 LCALL DELAY SJMP START IS3: LJMP START DELAY10MS: MOV R6,#20 ;延时子程序 LOOP1: MOV R7,#248 DJNZ R7,$ DJNZ R6,LOOP1 RET DELAY: MOV R5,#20 LOOP2: LCALL DELAY10MS DJNZ R5,LOOP2 RET END 八、C语言源程序 #include void delay10ms(void) //延时10毫秒子程序// { unsigned char i,j; for(i=20;i>0;i--) { for(j=248;j>0;j--); } } void delay200ms(void) //延时0.2秒程序// { unsigned char k; for(k=20;k>0;k--) { delay10ms(); } } void main(void) { unsigned char h; while(1) { if(P3_7==0) //看是否P3.7的按键按下// { delay10ms(); //延时10毫秒看是否干扰// if(P3_7==0) //重新看是否真的按下// { h++; //如果按下h加1,即h记下按键按下的次数// if(h==4) //如果h记到8次,则h清0重新记录次数// { h=0; } while(P3_7==0); //等待按键弹起// } } switch(h) 36 { case 0: //如果按键按下次数为1次时,进入此部分// P1_3=1; P1_0=~P1_0; //给P1.0取反,以达到闪烁的效果// delay200ms(); //每隔0.2秒闪烁一次// break; case 1: //按键按下的次数为2次时,进入此部分// P1_0=1; P1_1=~P1_1; //给P1.1取反,以达到每隔0.2秒闪烁一次// delay200ms(); break; case 2: //按键按下的次数为3次时,进入此部分// P1_1=1; P1_2=~P1_2; //给P1.2取反,以达到每隔0.2秒闪烁一次// delay200ms(); break; case 3: //按键按下为4次时,进入此部分// P1_2=1; P1_3=~P1_3; //给P1.3取反,以达到每隔0.2秒闪烁一次// delay200ms(); break; } } } 九、注意事项 汇编语言和C语言定义口的书写形式不同。如汇编语言为P1.0,P2.0,P3.0,而C语 言为P1_0 ,P2_0 ,P3_0。 37 实验十 00-99计数器设计 一、实验目的 1.掌握计数器的设计方法。 2.了解计数器的手动计数功能。 了解静态数码显示技术。 3. 二、设计原理 如图10.1所示,利用单片机来制作一个手动计数器,在单片机的P3.7管脚口接一个轻触开关,作为手动计数的按钮,用单片机管脚的P2.0,P2.7口连接一个共阴数码管,作为00-99计数的个位数显示,用单片机管脚的P0.0,P0.7口连接一个共阴数码管,作为00,99计数的十位数显示。 三、参考电路 图10.1 00-99计数器设计电路原理图 四、电路硬件说明 38 (1)在“单片机系统”区域中,把单片机的P0.0,P0.7端口连接到“静态数码显示模块”区域中的a,h端口上;要求:P0.0对应着a,P0.1对应着b,„„,P0.7对应着h。 (2)在“单片机系统”区域中,把单片机的P2.0,P2.7端口连接到“静态数码显示模块”区域中的a,h端口上;要求:P0.0对应着a,P0.1对应着b,„„,P0.7对应着h。 (3)在“单片机系统”区域中,把单片机的P3.7端口通过拨动开关JP2连接到“独立式键盘”区域中的按键开关S18上。 五、程序设计内容 (1)单片机对按键的识别过程的处理。 (2)单片机对正确识别的按键进行计数,计数满时,从零开始计数。 (3)单片机对计的数值要进行数码显示,计得的数是十进制数,含有十位和个位。要把十位和个位的数值分别到各自对应的数码管上并显示。分别送数时,可以把所计得的数值对10求余,即可得到个位数字;对10整除,即可得到十位数字。 (4)通过查表方式,分别显示出个位和十位的数字。 六、程序流程图(如图10.2所示) 图10.2 00-99计数器设计流程图 七、汇编源程序 ;;;;;;;;;;定义单元;;;;;;;;;; COUNT EQU 30H ;;;;;;;;;;入口地址;;;;;;;;;; ORG 0000H LJMP START ORG 0003H RETI ORG 000BH RETI ORG 0013H RETI 39 ORG 001BH RETI ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序;;;;;;;;;; ORG 0100H START: LCALL CHUSHIHUA NEXT: LCALL XIANSHI LCALL WT LCALL WAIT CJNE A,#100,NEXT LJMP START ;;;;;;;;;;初始化程序;;;;;;;;;; CHUSHIHUA: MOV COUNT,#00H RET ;;;;;;;;;;显示程序;;;;;;;;;; XIANSHI: MOV A,COUNT MOV B,#10 DIV AB MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,B MOVC A,@A+DPTR MOV P2,A RET ;;;;;;;;;;开关抬起检测程序;;;;;;;;;; WT: JNB P3.7,$ RET ;;;;;;;;;;开关按下次数记数程序;;;;;;;;;; WAIT: JB P3.7,WAIT LCALL DELAY10MS JB P3.7,WAIT INC COUNT MOV A,COUNT RET ;;;;;;;;;;10ms延时程序;;;;;;;;;; DELAY10MS: MOV R6,#20 D1: MOV R7,#248 DJNZ R7,$ DJNZ R6,D1 RET 40 ;;;;;;;;;;共阴数码表;;;;;;;;;; TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序 #include unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; void delay10ms(void) //延时10毫秒子程序// { unsigned char i,j; for(i=20;i>0;i--) { for(j=248;j>0;j--); } } void main(void) { unsigned char k; k=0; //先让十位和个位显示00// P0=table[k/10]; P2=table[k%10]; while(1) { if(P3_7==0) //看按键是否按下// { delay10ms(); //延时10毫秒// if(P3_7==0) //再判断按键是否真的按下// { k++; //记下按键按下的次数// if(k==100) //如果计数到100,返回0// { k=0; } while(P3_7==1); //等待按键弹起// P0=table[k/10]; //显示十位数// P2=table[k%10]; //显示个位数// } } } } 九、注意事项 (1)程序中数码管的显示为共阴极显示。 (2)用静态数码管DS1、DS2时,要把J5上的跳线帽加到OE和VCC上;把J6上的跳线帽加到OE和GND上。 41 实验十一 六十秒计时器设计 一、实验目的 1.了解计时器的功能。 2.掌握计时器的设计方法。 掌握静态数码显示技术。 3. 二、设计原理 如图11.1所示,在单片机的P0和P2端口分别接两个共阴极数码管。P0口驱动计时器显示的十位,P2口驱动计时器显示的个位。 三、参考电路 图11.1 六十秒计时器电路原理图 四、电路硬件说明 (1)在“单片机系统”区域中,把单片机的P0.0,P0.7端口连接到“静态数码显示模块”区域中的a,h端口上;要求:P0.0对应着a,P0.1对应着b,„„,P0.7对应着h。 42 (2)在“单片机系统”区域中,把单片机的P2.0,P2.7端口连接到“静态数码显示模块”区域中的a,h端口上;要求:P2.0对应着a,P2.1对应着b,„„,P2.7对应着h。 五、程序设计内容 (1)在设计过程中要用一个存储单元作为秒计数单元。当一秒钟到来时,就让秒计数单元加1;当秒计数达到60时,就自动返回到0,从新计数。 (2)对于秒计数单元中的数据来说,要把它的十位数和个数分开,方法仍采用对10整除和对10求余。 (3)当在数码管上显示数时,仍通过查表的方式完成。 (4)一秒时间的产生在这里采用软件精确延时的方法来完成,经过精确计算得到1秒时间为1.002秒。 DELY1S: MOV R5,#100 D2: MOV R6,#20 D1: MOV R7,#248 DJNZ R7,$ DJNZ R6,D1 DJNZ R5,D2 RET 六、程序流程图(如图11.2所示) 图11.2 60秒计时器设计流程图 七、汇编源程序 ;;;;;;;;;;定义单元;;;;;;;;;; COUNT EQU 30H ;;;;;;;;;;入口地址;;;;;;;;;; 43 ORG 0000H LJMP START ORG 0003H RETI ORG 000BH RETI ORG 0013H RETI ORG 001BH RETI ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序;;;;;;;;;; ORG 0100H START: LCALL CHUSHIHUA LCALL NEXT LJMP START ;;;;;;;;;;初始化程序;;;;;;;;;; CHUSHIHUA: MOV COUNT,#00H RET ;;;;;;;;;;计数显示程序;;;;;;;;;; NEXT: LCALL XIANSHI LCALL DELAY1S INC COUNT MOV A,COUNT CJNE A,#60,NEXT RET ;;;;;;;;;;显示程序;;;;;;;;;; XIANSHI: MOV A,COUNT MOV B,#10 DIV AB MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,B MOVC A,@A+DPTR MOV P2,A RET ;;;;;;;;;;1s延时程序;;;;;;;;;; DELAY1S: MOV R5,#100 D1: MOV R6,#20 D2: MOV ` R7,#248 44 DJNZ R7,$ DJNZ R6,D2 DJNZ R5,D1 RET ;;;;;;;;;;共阴数码表;;;;;;;;;; TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序 #include unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66, //数据表格// 0x6d,0x7d,0x07,0x7f,0x6f}; void delay1s(void) //1秒子程序// { unsigned char i,j,k; for(i=100;i>0;i--) { for(j=20;j>0;j--) { for(k=248;k>0;k--);} } } void main(void) { unsigned char m; m=0; //显示0秒// P0=table[m/10]; P2=table[m%10]; while(1) { delay1s(); //延时1秒// m++; //每到1秒加1// if(m==60) //如果到了60秒,重新开始计时// { m=0; } P0=table[m/10]; //显示// P2=table[m%10]; } } 九、注意事项 用静态数码管DS1、DS2时,要将J5上的OE和VCC通过跳线帽连接 、J6上的OE和GND通过跳线帽连接。 45 实验十二 可预置可逆4位计数器设计 一、实验目的 1.可预置可逆4位计数器设计 2.掌握计数器的预置、加法和减法。 二、设计原理 如图12.1所示,用单片机的P1.0,P1.3端口接四个发光二极管D1,D4,用来指示当前计数的数据。用单片机的P3.0,P3.3端口作为预置数据的输入端,通过8联拨动拨码开关JP2连接四个拨动开关SW1,SW4,用单片机的P3.6和P3.7端口连接两个按键开关,用做加计数和减计数开关。 三、参考电路 图12.1 可预置可逆4位计数器电路原理图 四、电路硬件说明 46 (1)在“单片机系统”区域中,把单片机的P1.0,P1.3管脚通过8联拨动拨码开关JP4连接到“八路发光二极管指示模块”区域中的D1,D4上;要求:P1.0对应着D1,P1.1对应着D2,P1.2对应着D3,P1.3对应着D4。 (2)在“单片机系统”区域中,把单片机的P3.0,P3.1,P3.2,P3.3管脚通过8联拨动拨码开关JP2连接到“四路拨动开关”区域中的拨码开关SW1,SW4上。 (3)在“单片机系统”区域中,把单片机的P3.6,P3.7管脚通过8联拨动拨码开关 18和S19上。 JP2连接到“独立式键盘”区域中的按键开关S 五、程序设计内容 (1)两个独立式按键识别的处理过程。 (2)预置初值的读取问题。 (3)LED输出指示。 六、程序流程图(如图12.2所示) 图12.2 可预置可逆计数器设计流程图 七、汇编源程序 ;;;;;;;;;;定义单元;;;;;;;;;; COUNT EQU 30H ;;;;;;;;;;入口地址;;;;;;;;;; ORG 0000H LJMP START 47 ORG 0003H RETI ORG 000BH RETI ORG 0013H RETI ORG 001BH RETI ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序入口;;;;;;;;;; ORG 0100H START: LCALL CHUSHIHUA MAIN: LCALL JIA LCALL JIAN LJMP MAIN ;;;;;;;;;;初始化程序;;;;;;;;;; CHUSHIHUA: MOV A,P3 A,#0FH ANL MOV COUNT,A MOV P1,A RET ;;;;;;;;;;加1程序;;;;;;;;;; JIA: JB P3.6,JIAN LCALL DELAY10MS JB P3.6,JIAN INC COUNT MOV A,COUNT CJNE A,#16,NEXT MOV A,P3 ANL A,#0FH MOV COUNT,A NEXT: MOV P1,A WAIT: JNB P3.6,$ RET ;;;;;;;;;;减1程序;;;;;;;;;; JIAN: JB P3.7,JIA LCALL DELAY10MS JB P3.7,JIA DEC COUNT MOV A,COUNT CJNE A,#0FFH,NEX 48 MOV A,P3 ANL A,#0FH MOV COUNT,A NEX: MOV P1,A WAIT1: JNB P3.7,$ RET ;;;;;;;;;;10MS延时程序;;;;;;;;;; DELAY10MS: MOV R6,#20 D1: MOV R7,#248 DJNZ R7,$ DJNZ R6,D1 RET ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序 #include void delay10ms(void) //10毫秒延时子程序// { unsigned char i,j; for(i=20;i>0;i--) for(j=248;j>0;j--); } { } void main(void) { unsigned char k; k=P3&0x0f; P1=k; //如果高电平时,指示灯亮,相反// while(1) { if(P3_6==0) //判断P3.6是否按下// { delay10ms(); //延时10毫秒// if(P3_6==0) //再次判断是否真的按下// { if(k>=15) //如果指示的数大于等于15,都以15计// { k=15; } else //否则一直能加到15// { k++; } P1=k; //送入P1口显示// while(P3_6==0); //等待按键弹起// } } if(P3_6==0) //判断是否P3.7按下// { delay10ms(); //延时10毫秒// if(P3_6==0) //再次判断是否真的按下// { if(k<=0) //如果K小于等于零,一切以0计// { k=0; } else 49 { k--; } //如果不小于零,一直减到0// P1=k; //送入P1口显示// while(P3_7==0); //等待P3.7弹起// } } } } 九、注意事项 (1)单片机中的指令在C语言中运用一定要大写。 (2)程序中要屏蔽P1口的高四位。 50 实验十三 动态数码显示设计 一、实验目的 1.掌握动态数码显示技术的设计方法。 2.掌握扫描在程序设计中的应用。 二、设计原理 如图13.1所示,在单片机的P1端口接动态数码管的字形码笔段,在单片机的P2端口接动态数码管的数位选择端。在单片机P3.0管脚处接一个开关,当开关连接高电平时,态数码管上显示“12345”字样;当开关连接低电平时,态数码管上显示“HELLO”字样。 三、参考电路 图13.1 动态数码显示电路原理图 四、电路硬件说明 (1)在“单片机系统”区域中,把单片机的P1.0,P1.7端口连接到“动态数码显示”区域中的a,h端口上。 51 (2)在“单片机系统”区域中,把单片机的P2.0,P2.7端口通过8联拨动拨码开关JP1连接到“动态数码显示”区域中的S1,S8端口上。 (3)在“单片机系统”区域中,把单片机的P3.0端口通过8联拨动拨码开关JP2连接到拨动开关区域中的SW1端口上。 五、程序设计内容 (1)动态扫描方法: 动态接口采用各数码管循环轮流显示的方法,当循环显示频率较高时,利用人眼的暂留特性,看不出显示的闪烁现象,这种显示需要一个接口完成字形码的输出(字形选择),另一接口完成各数码管的轮流点亮(数位选择)。 (2)在进行数码显示的时候,要对显示单元开辟8个显示缓冲区,在每个显示缓冲区装有显示的不同数据即可。 (3)对于显示不同字形码的数据采用查表方法来完成。 六、程序流程图 (如图13.2所示) 图13.2 动态数码显示程序流程图 七、汇编源程序 ;;;;;;;;;;入口地址;;;;;;;;;; ORG 0000H LJMP START ORG 0003H RETI ORG 000BH 52 RETI ORG 0013H RETI ORG 001BH RETI ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序入口;;;;;;;;;; ORG 0100H START: LCALL PANDUAN LCALL XIANSHI LJMP START ;;;;;;;;;;判断开关的状态;;;;;;;;;; PANDUAN: JB P3.0,SW LCALL DELAY10MS JB P3.0,SW MOV DPTR,#TABLE2 SJMP Q1 SW: JNB P3.0,PANDUAN MOV DPTR,#TABLE1 Q1: RET ;;;;;;;;;;显示程序;;;;;;;;;; XIANSHI: MOV R0,#00H MOV R1,#7FH NEXT: MOV A,R0 MOVC A,@A+DPTR MOV P0,A MOV A,R1 MOV P2,A LCALL DELAY INC R0 RR A MOV R1,A CJNE R1,#0FBH,NEXT RET ;;;;;;;;;;10ms延时程序;;;;;;;;;; DELAY10MS: MOV R6,#20 D1: MOV R7,#248 DJNZ R7,$ DJNZ R6,D1 RET ;;;;;;;;;;200ms延时程序;;;;;;;;;; 53 DELAY: MOV R5,#20 LOOP: LCALL DELAY10MS DJNZ R5,LOOP RET ;;;;;;;;;;共阴字母码表;;;;;;;;;; TABLE1: DB 76H,79H,38H,38H,3FH ;;;;;;;;;;共阴数码表;;;;;;;;;;; TABLE2: DB 06H,5BH,4FH,66H,6DH ;;;;;;;;;;结束标志;;;;;;;;;;;;; END 八、C语言源程序 #include unsigned char code table1[]={0x06,0x5b,0x4f,0x66,0x6d}; unsigned char code table2[]={0x76,0x79,0x38,0x38,0x3f}; void main(void) { unsigned char i,j,k,m; while(1) { j=0x7f; for(i=0;i<5;i++) //运行5次取出表中的5个数// { if(P3_0==0) //如果开关为0,则显示12345// { P0=table1[i]; } //送P1口显示// else //如果开关为1,显示HELLO// { P0=table2[i]; } //送P1口显示// P2=j; //显示码送入P2口// j=0x7f; //重赋初值// k=j>>(i+1); //右移i+1位// m=j<<(7-i); //左移7-i位// j=k|m; for(k=4;k>0;k--) //每隔一段时间显示一次// for(m=248;m>0;m--); } } } 九、注意事项 (1)程序中要注意共阴极数码管显示和共阳极数码管显示的区别,本程序在共阴极数 码管显示时,要把单排针接插件J4中的跳线帽加到OE和VCC上。 (2)程序下载后要把8联拨动拨码开关JP2中相应的拨码开关拨上去。 54 实验十四 4×4矩阵式键盘识别设计 一、实验目的 1.掌握4×4矩阵式键盘程序识别原理。 2.掌握4×4矩阵式键盘按键的设计方法。 二、设计原理 (1)如图14.2所示,用单片机的并行口P3连接4×4矩阵键盘,并以单片机的P3.0,P3.3各管脚作输入线,以单片机的P3.4,P3.7各管脚作输出线,在数码管上显示每个按键 “0,F”的序号。 (2)键盘中对应按键的序号排列如图14.1所示。 三、参考电路 图14.2 4×4矩阵式键盘识别电路原理图 55 图14.1 4×4键盘0-F显示 图14.3 4×4矩阵式键盘识别程序流程图 四、电路硬件说明 (1)在“单片机系统”区域中,把单片机的P3.0,P3.7端口通过8联拨动拨码开关JP3连接到“4×4行列式键盘”区域中的M1,M4,N1,N4端口上。 (2)在“单片机系统”区域中,把单片机的P0.0,P0.7端口连接到“静态数码显示模块”区域中的任何一个a,h端口上;要求:P0.0对应着a,P0.1对应着b,„„,P0.7对应着h。 五、程序设计内容 56 (1)4×4矩阵键盘识别处理 。 (2)每个按键都有它的行值和列值,行值和列值的组合就是识别这个按键的编码。矩 阵的行线和列线分别通过两并行接口和CPU通信。键盘的一端(列线)通过电阻接VCC,而 接地是通过程序输出数字“0”实现的。键盘处理程序的任务是:确定有无键按下,判断哪 一个键按下,键的功能是什么,还要消除按键在闭合或断开时的抖动。两个并行口中,一个 输出扫描码,使按键逐行动态接地;另一个并行口输入按键状态,由行扫描值和回馈信号共 同形成键编码而识别按键,通过软件查表,查出该键的功能。 六、程序流程图(如图14.3所示) 七、汇编源程序 ;;;;;;;;;;定义单元;;;;;;;;;; COUNT EQU 30H ;;;;;;;;;;入口地址;;;;;;;;;; ORG 0000H LJMP START ORG 0003H RETI ORG 000BH RETI ORG 0013H RETI ORG 001BH RETI ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序入口;;;;;;;;;; ORG 0100H START: LCALL CHUSHIHUA LCALL PANDUAN LCALL XIANSHI LJMP START ;;;;;;;;;;初始化程序;;;;;;;;;; CHUSHIHUA: MOV COUNT,#00H RET ;;;;;;;;;;判断哪个按键按下程序;;;;;;;;;; PANDUAN: MOV P3,#0FFH CLR P3.4 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ SW1 LCALL DELAY10MS 57 JZ SW1 MOV A,P3 ANL A,#0FH CJNE A,#0EH,K1 MOV COUNT,#0 LJMP DK K1: CJNE A,#0DH,K2 MOV COUNT,#4 LJMP DK K2: CJNE A,#0BH,K3 MOV COUNT,#8 LJMP DK K3: CJNE A,#07H,K4 MOV COUNT,#12 K4: NOP LJMP DK SW1: MOV P3,#0FFH CLR P3.5 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ SW2 LCALL DELAY10MS JZ SW2 MOV A,P3 ANL A,#0FH CJNE A,#0EH,K5 MOV COUNT,#1 LJMP DK K5: CJNE A,#0DH,K6 MOV COUNT,#5 LJMP DK K6: CJNE A,#0BH,K7 MOV COUNT,#9 LJMP DK K7: CJNE A,#07H,K8 MOV COUNT,#13 K8: NOP LJMP DK SW2: MOV P3,#0FFH CLR P3.6 MOV A,P3 ANL A,#0FH XRL A,#0FH 58 JZ SW3 LCALL DELAY10MS JZ SW3 MOV A,P3 ANL A,#0FH CJNE A,#0EH,K9 MOV COUNT,#2 LJMP DK K9: CJNE A,#0DH,KA MOV COUNT,#6 LJMP DK KA: CJNE A,#0BH,KB MOV COUNT,#10 LJMP DK KB: CJNE A,#07H,KC MOV COUNT,#14 KC: NOP LJMP DK SW3: MOV P3,#0FFH CLR P3.7 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ SW4 LCALL DELAY10MS JZ SW4 MOV A,P3 ANL A,#0FH CJNE A,#0EH,KD MOV COUNT,#3 LJMP DK KD: CJNE A,#0DH,KE MOV COUNT,#7 LJMP DK KE: CJNE A,#0BH,KF MOV COUNT,#11 LJMP DK KF: CJNE A,#07H,KG MOV COUNT,#15 KG: NOP LJMP DK SW4: LJMP PANDUAN DK: RET 59 ;;;;;;;;;;显示程序;;;;;;;;;; XIANSHI: MOV A,COUNT MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A LCALL DELAY SK: MOV A,P3 ANL A,#0FH XRL A,#0FH JNZ SK RET ;;;;;;;;;;10ms延时程序;;;;;;;;;; DELAY10MS: MOV R6,#20 D1: MOV R7,#248 DJNZ R7,$ DJNZ R6,D1 RET ;;;;;;;;;;200ms延时程序;;;;;;;;;; DELAY: MOV R5,#20 LOOP: LCALL DELAY10MS DJNZ R5,LOOP RET ;;;;;;;;;;共阴码表;;;;;;;;;; TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序 #include unsigned char code table[]={0x3f,0x66,0x7f,0x39, 0x06,0x6d,0x6f,0x5e, 0x5b,0x7d,0x77,0x79, 0x4f,0x07,0x7c,0x71}; void main(void) { unsigned char i,j,k,key; while(1) { P3=0xff; //给P3口置1// P3_4=0; //给P3.4这条线送入0// i=P3; i=i&0x0f; //屏蔽低四位// if(i!=0x0f) //看是否有按键按下// { for(j=50;j>0;j--) //延时// for(k=200;k>0;k--); 60 if(i!=0x0f) //再次判断按键是否按下// { switch(i) //看是和P3.4相连的四个按键中的哪个// { case 0x0e: key=0; break; case 0x0d: key=1; break; case 0x0b: key=2; break; case 0x07: key=3; break; } P0=table[key]; //送数到P0口显示// } } P3=0xff; P3_5=0; //读P3.5这条线// i=P3; i=i&0x0f; //屏蔽P3口的低四位// if(i!=0x0f) //读P3.5这条线上看是否有按键按下// { for(j=50;j>0;j--) //延时// for(k=200;k>0;k--); i=P3; //再看是否有按键真的按下// i=i&0x0f; if(i!=0x0f) { switch(i) //如果有,显示相应的按键// { case 0x0e: key=4; break; case 0x0d: key=5; break; case 0x0b: key=6; break; case 0x07: key=7; break; } P0=table[key]; //送入P0口显示// } 61 } P3=0xff; P3_6=0; //读P3.6这条线上是否有按键按下// i=P3; i=i&0x0f; if(i!=0x0f) { for(j=50;j>0;j--) for(k=200;k>0;k--); i=P3; i=i&0x0f; if(i!=0x0f) { switch(i) { case 0x0e: key=8; break; case 0x0d: key=9; break; case 0x0b: key=10; break; case 0x07: key=11; break; } P0=table[key]; } } P3=0xff; P3_7=0; //读P3.7这条线上是否有按键按下// i=P3; i=i&0x0f; if(i!=0x0f) { for(j=50;j>0;j--) for(k=200;k>0;k--); i=P3; i=i&0x0f; if(i!=0x0f) { switch(i) { case 0x0e: key=12; break; case 0x0d: key=13; 62 break; case 0x0b: key=14; break; case 0x07: key=15; break; } P0=table[key]; } } } } 九、注意事项 在硬件电路中,要把8联拨动拨码开关JP2拨下,把8联拨动拨码开关JP3拨上去。 63 实验十五 定时计数器T0作定时应用设计(一) 一、实验目的 1.掌握定时计数器T0的用法。 2.掌握定时计数器T0的功能。 二、设计原理 用单片机的定时/计数器T0产生一秒的定时时间,作为秒计数时间。当一秒产生时,秒计数加1,秒计数到60时,自动从0重新计数。 三、参考电路 图15.1定时计数器T0作定时应用(一)电路原理图 四、电路硬件说明 (1)在“单片机系统”区域中,把单片机的P0.0,P0.7端口连接到“静态数码显示模块”区域中的任何一个a,h端口上;要求:P0.0对应着a,P0.1对应着b,„„,P0.7对应着h。 64 (2)在“单片机系统”区域中,把单片机的P2.0,P2.7端口连接到“静态数码显示模块”区域中的任一个a,h端口上;要求:P2.0对应着a,P2.1对应着b,„„,P2.7对应着h。 五、程序设计内容 AT89S51单片机的内部16位定时/计数器是一个可编程定时/计数器,它既可以工作在13位定时方式,也可以工作在16位定时方式和8位定时方式。只要通过设置特殊功能寄存器TMOD,即可完成。定时/计数器何时工作也是通过软件TCON特殊功能寄存器来设定完成的。 现在选择16位定时工作方式,对于T0来说,最大定时也只有65536us,即65.536ms,无法达到所需要的1秒的定时,因此,必须通过软件来处理这个问题。假设取T0的最大定时为50ms,即要定时1秒就需要经过20次的50ms的定时。对于这20次就可以采用软件的方法来计算了。 因此,设定TMOD,00000001B,即TMOD,01H。 下面要给T0定时/计数器的TH0,TL0装入预置初值,通过下面的公式可以计算出 TH0,(65536,50000) / 256 TL0,(65536,50000) % 256 当T0在工作的时候,如何得知50ms的定时时间已到,通过检测TCON特殊功能寄存器中的TF0标志位,如果TF0,1表示定时时间已到。 六、程序流程图(如图15.2所示) 图15.2 定时计数器T0应用(一)程序流程图 65 七、汇编源程序(查询法) ;;;;;;;;;;定义单元;;;;;;;;;; COUNT EQU 30H ;;;;;;;;;;入口地址;;;;;;;;;; ORG 0000H LJMP START ORG 0003H RETI ORG 000BH RETI ORG 0013H RETI ORG 001BH RETI ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序入口;;;;;;;;;; ORG 0100H START: LCALL CHUSHIHUA LCALL XIANSHI LCALL MAIN LJMP START ;;;;;;;;;;初始化程序;;;;;;;;;; CHUSHIHUA: MOV COUNT,#00H RET ;;;;;;;;;;装初值程序;;;;;;;;;; CHUZHI: MOV TMOD,#01H MOV TH0,#3CH MOV TL0,#0B0H SETB TR0 RET ;;;;;;;;;;显示程序;;;;;;;;;; XIANSHI: MOV A,COUNT MOV B,#10 DIV AB MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,B MOVC A,@A+DPTR MOV P2,A RET 66 ;;;;;;;;;;60s计时显示程序;;;;;;;;; MAIN: MOV R5,#20 LCALL CHUZHI SK: JNB TF0,$ CLR TF0 LCALL CHUZHI DJNZ R5,SK INC COUNT LCALL XIANSHI MOV A,COUNT CJNE A,#60,MAIN RET ;;;;;;;;;;共阴数码表;;;;;;;;; TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序(查询法) #include unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; void main(void) { unsigned char i,j; TMOD=0x01; //设置定时器0方式1// TH0=(65536-50000)/256; //赋50毫秒的初值// TL0=(65536-50000)%256; TR0=1; //开启定时器0// i=0; j=0; P0=table[j/10]; //十位数放入P0口显示,// P2=table[j%10]; //个位数放入P2口显示// while(1) { if(TF0==1) //如果定时器溢出,则为50毫秒// { i++; //每到一个50毫秒,i加1// if(i==20) //如果到了20个50毫秒,则1秒的到来// { i=0; //i清0,重新计数// j++; //每到一个1秒,j加1// if(j==60) //如果计到60秒,则重新计数// { j=0; } P0=table[j/10]; //显示秒数的十位数// P2=table[j%10]; //显示秒数的个位数// } TF0=0; //关闭定时器0// TH0=(65536-50000)/256; //重新赋初值// 67 TL0=(65536-50000)%256; } } } 九、汇编源程序(中断法) ORG 0000H ;系统复位 LJMP ZHONGDUANDINGSHI;进入ZHONGDUANDINGSHI程序 ORG 0003H RETI ORG 000BH ;定时器中断 LJMP ZHONGDUAN ORG 0013H RETI ORG 001BH RETI ORG 0023H RETI ORG 002BH RETI ORG 0100H ;转入中断子程序 ZHONGDUANDINGSHI: MOV R0,#00H ;开始的显示00的程序 MOV A,R0 MOV B,#10 DIV AB MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,B MOVC A,@A+DPTR MOV P2,A MOV TMOD,#01H ;定义为定时器0的工作方式1 MOV TH0,#3CH ;给定时器的高位赋值 MOV TL0,#0B0H ;给定时器的低位赋值 SETB TR0 ;开定时器0 SETB ET0 ;开启分开关 SETB EA ;开启总开关 SJMP $ ;自身循环,等待中断 ZHONGDUAN: MOV TH0,#3CH ;进入中断子程序,并重新赋值 MOV TL0,#0B0H INC R1 ;记下中断次数 MOV A,R1 CJNE A,#20,NEXT ;是否有20次中断 MOV R1,#00H ;如果有,则清零,重新记 68 INC R0 ;同时R0加1 MOV A,R0 CJNE A,#60,NEX ;看是否加到60 MOV R0,#00H ;如果加到60次,重新记 NEX: MOV A,R0 ;把R0中所记的数显示出来 MOV B,#10 AB DIV MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A ;用P0显示十位 MOV A,B MOVC A,@A+DPTR MOV P2,A ;用P2显示个位 NEXT: RETI ;中断返回 TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH END 十、C语言源程序(中断法) #include unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; unsigned char i,j; void main(void) { TMOD=0x01; //定义为定时器0方式1// TH0=(65536-50000)/256; //赋初值// TL0=(65536-50000)%256; TR0=1; //开启定时器0// ET0=1; //开启定时器0溢出中断// EA=1; //开启总的中断开关// i=0; j=0; P0=table[j/10]; //显示秒数的十位// P2=table[j%10]; //显示秒数的个位// while(1); //等待中断// } void t0(void) interrupt 1 using 0 //定时器0溢出中断// { i++; //每到一个中断为50毫秒,i加1// if(i==20) //到来20次中断后,i重新计数// { i=0; j++; //每来20次中断即为1秒,j加1// if(j==60) //每到60秒,则重新计时// { j=0; } P0=table[j/10]; //显示秒计时的十位// P2=table[j%10]; //显示秒计时的个位// 69 } TH0=(65536-50000)/256; //重新赋定时器0的初值// TL0=(65536-50000)%256; } 十一、注意事项 程序初始化时,针对不同的定时器要赋予不同的初值。 70 实验十六 定时计数器T0作定时应用设计(二) 一、实验目的 1.了解定时计数器T0在程序设计中的应用。 2.掌握定时器T0的功能以及用法。 二、设计原理 如图16.1所示,用单片机的定时/计数器T0产生2秒钟的定时,每当2秒定时到来时,更换指示灯闪烁。每个指示灯闪烁的频率为0.2秒,也就是说,开始D1指示灯以0.2秒的速率闪烁,当2秒定时到来之后,D2开始以0.2秒的频率闪烁,如此循环下去。0.2秒的闪烁的频率也由定时/计数器T0来完成。 三、参考电路 图16.1定时计数器T0应用(二)电路原理图 四、电路硬件说明 在“单片机系统”区域中,把单片机的P1.0,P1.3端口通过8联拨动拨码开关JP4连接到“八路发光二极管指示模块”区域中的闪烁灯D1,D4上。 71 五、程序设计内容 (1)本程序采用中断方式来完成,因此,对于中断源必须有它的中断入口地址。对于定时/计数器T0来说,中断入口地址为000BH。所以在中断入口地方加入长跳转指令来执行中断服务程序。书写汇编源程序格式如下所示: ORG 00H LJMP START ORG 0BH ;定时/计数器T0中断入口地址 LJMP INT_T0 START: NOP ;主程序开始 . INT_T0: PUSH ACC ;定时/计数器T0中断服务程序 PUSH PSW . POP PSW POP ACC RETI ;中断服务程序返回 END (2)定时2秒,采用16位定时50ms,共定时40次才可达到2秒,每50ms产生一中断。定时的40次计数在中断服务程序中完成。同样,0.2秒的定时,需要4次才可达到。对于中断程序,在主程序中要开中断。 (3)由于定时每2秒一次,D1,D4要交替闪烁。采用ID标号来识别。当ID,0时,D1在闪烁;当ID,1时,D2在闪烁;当ID,2时,D3在闪烁;当ID,3时,D4在闪烁。 六、程序流程图 (如图16.2所示) 图16.2 定时计数器T0应用(二)程序流程图 72 七、汇编源程序 ;;;;;;;;;;定义单元;;;;;;;;;; TCOUNT2S EQU 30H TCNT02S EQU 31H ID EQU 32H ;;;;;;;;;;入口地址;;;;;;;;;; ORG 0000H LJMP START ORG 0003H RETI ORG 000BH LJMP INT_T0 ORG 0013H RETI ORG 001BH RETI ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序入口;;;;;;;;;; ORG 0100H START: LCALL CHUSHIHUA LJMP START ;;;;;;;;;;初始化程序;;;;;;;;;; CHUSHIHUA: MOV TCOUNT2S,#00H MOV TCNT02S,#00H MOV ID,#00H MOV TMOD,#01H MOV TH0,#60 MOV TL0,#176 SETB TR0 SETB ET0 SETB EA SJMP $ RET ;;;;;;;;;;中断子程序;;;;;;;;;; INT_T0: MOV TH0,#60 MOV TL0,#176 INC TCOUNT2S MOV A,TCOUNT2S CJNE A,#40,NEXT MOV TCOUNT2S,#00H INC ID 73 MOV A,ID CJNE A,#04H,NEXT MOV ID,#00H NEXT: INC TCNT02S MOV A,TCNT02S CJNE A,#4,DONE MOV TCNT02S,#00H MOV A,ID CJNE A,#00H,SID1 SETB P1.1 SETB P1.2 SETB P1.3 CPL P1.0 SJMP DONE SID1: CJNE A,#01H,SID2 SETB P1.0 CPL P1.1 SJMP DONE SID2: CJNE A,#02H,SID3 SETB P1.0 SETB P1.1 CPL P1.2 SJMP DONE SID3: CJNE A,#03H,SID4 SETB P1.0 SETB P1.1 SETB P1.2 CPL P1.3 SID4: SJMP DONE DONE: RETI ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序 #include unsigned char i,j,k; //此处应定义为全局变量// void main(void) { TMOD=0x01; //设置为定时器0方式1// TH0=(65536-50000)/256; //给定时器0赋初值// TL0=(65536-50000)%256; TR0=1; //开启定时器0// ET0=1; //开启定时器0溢出中断// EA=1; //开启中断总开关// while(1); //等待中断// 74 } void t0(void) interrupt 1 using 0 { i++; //每来一个50毫秒i加1// if(i==40) //看是否2秒到来// { i=0; //如果到了2秒,i重新计50毫秒来的次数// j++; //j用于记下第几个指示灯闪烁// if(j==4) //如果闪到第四个闪烁灯,j为0// { j=0; } } k++; //每到一个50毫秒k加1// if(k==4) //看是否到了0.2秒// { k=0; //如果到了0.2秒,则k清0// switch(j) //看应该是哪个指示灯闪烁// { case 0: P1_3=1; P1_0=~P1_0; break; case 1: P1_0=1; P1_1=~P1_1; break; case 2: P1_1=1; P1_2=~P1_2; break; case 3: P1_2=1; P1_3=~P1_3; break; } } } 九、注意事项 程序下载后,要把8联拨动拨码开关JP4的相应开关拨上去。 75 实验十七 9.9秒跑马表设计 一、实验目的 1.了解9.9秒跑马表的设计原理。 2.掌握定时器的多重用途。 二、设计原理 (1)开始时,显示“00”,第1次按下按键开关S20后就开始计时。 (2)第2次按下按键开关S20后,计时停止。 (3)第3次按下按键开关S20后,计时归零。 (4)程序循环。 三、参考电路 图17.1 9.9秒跑马表电路原理图 四、电路硬件说明 76 (1)在“单片机系统”区域中,把单片机的P0.0,P0.7端口连接到“静态数码显示模块”区域中的任一个a,h端口上;要求:P0.0对应着a,P0.1对应着b,„„,P0.7对应着h。 (2)在“单片机系统”区域中,把单片机的P2.0,P2.7端口连接到“静态数码显示模块”区域中的任一个a,h端口上;要求:P2.0对应着a,P2.1对应着b,„„,P2.7对应着h。 3)在“单片机系统”区域中,把单片机的P3.5管脚通过8联拨动拨码开关JP2连接( 到“独立式键盘”区域中的按键开关S20端口上。 五、程序设计内容 用按键控制跑马表,开始时,数码管显示“00”;如果第一次按下按键时;跑马表开始计时;第二次按下按键后,计时开始;第三次按下按键后,计时归零。如此循环。 六、程序流程图(如图17.2所示) 图17.2 跑马表设计流程图 七、汇编源程序 ;;;;;;;;;;定义单元;;;;;;;;;; TCNTA EQU 30H TCNTB EQU 31H SEC EQU 32H KEYCNT EQU 33H ;;;;;;;;;;入口地址;;;;;;;;;; 77 ORG 0000H LJMP START ORG 0003H RETI ORG 000BH LJMP INT_T0 ORG 0013H RETI ORG 001BH RETI ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序入口;;;;;;;;;; ORG 0100H START: LCALL CHUSHIHUA LCALL XIANSHI LCALL MAIN LJMP START ;;;;;;;;;;初始化程序;;;;;;;;;; CHUSHIHUA: MOV SEC,#00H MOV KEYCNT,#00H RET ;;;;;;;;;;显示程序;;;;;;;;;; XIANSHI: MOV A,SEC MOV B,#10 DIV AB MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,B MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P2,A RET ;;;;;;;;;;9.9s计数,停止,清零显示程序;;;;;;;;;; MAIN: MOV TMOD,#02H SETB ET0 SETB EA MAIN_1: JB P3.5,MAIN_1 LCALL DELY10MS JB P3.5,MAIN_1 INC KEYCNT 78 MOV A,KEYCNT CJNE A,#01H,MAIN_2 SETB TR0 MOV TH0,#06H MOV TL0,#06H MOV TCNTA,#00H MOV TCNTB,#00H LJMP MAIN_0 MAIN_2: CJNE A,#02H,MAIN_3 CLR TR0 LJMP MAIN_0 MAIN_3: CJNE A,#03H,MAIN_0 MOV SEC,#00H LCALL XIANSHI MOV KEYCNT,#00H MAIN_0: JNB P3.5,$ LJMP MAIN_1 ;;;;;;;;;;10ms延时程序;;;;;;;;;; DELY10MS: MOV R6,#20 DELY10MS_1: MOV R7,#248 DJNZ R7,$ DJNZ R6,DELY10MS_1 RET ;;;;;;;;;;中断子程序;;;;;;;;;; INC TCNTA INT_T0: MOV A,TCNTA CJNE A,#100,INT_T0_1 MOV TCNTA,#00H INC TCNTB MOV A,TCNTB CJNE A,#4,INT_T0_1 MOV TCNTB,#00H INC SEC MOV A,SEC CJNE A,#100,INT_T0_2 MOV SEC,#00H INT_T0_2: LCALL XIANSHI INT_T0_1: RETI ;;;;;;;;;;共阴数码表;;;;;;;;;; TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序 79 #include unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; unsigned char m,n,a; void main(void) { unsigned char i,j,k; TMOD=0x02; //设置定时器0方式2// ET0=1; //开启定时器0中断// EA=1; //开启中断总开关// m=0; //开始显示0// P0=table[m/10]; P2=table[m%10]; while(1) { if(P3_5==0) //看P3.5是否按下// { for(i=20;i>0;i--) //延时判断// for(j=248;j>0;j--); if(P3_5==0) //再次判断// { while(P3_5==0); //如果有按下,等待按键弹起// k++; //k记下按键按下的次数// switch(k) //看按键按下的次数// case 1: //如果按下的是第一次,开启定时器开始计时// { TH0=0x06; TL0=0x06; TR0=1; break; case 2: //如果按下的是第二次,停止计时// TR0=0; break; case 3: //如果按下的是第三次,显示00// k=0; m=0; P0=table[m/10]; P2=table[m%10]; break; } } } } } void t0(void) interrupt 1 using 0 { n++; //每到一个250微秒,n加1// if(n==40) { n=0; //每到一个10毫秒,n清0,a加1// 80 a++; if(a==10) { a=0; //每到一个0.1秒,a清0,m加1// m++; if(m==100) //每到10秒,重新开始计时// { m=0; } //显示// P0=table[m/10]; P2=table[m%10]; } } } 九、注意事项 利用静态数码管DS1、DS2时,要把单排针接插件J5上的跳线帽加到OE和VCC上;把单排针接插件J6上的跳帽加到OE和GND上。 81 实验十八 “嘀、嘀、„„”报警声设计 一、实验目的 1.了解“嘀、嘀、„„”报警声的设计原理。 2.掌握频率的产生方法。 .了解报警信号的产生与报警器的控制。 3 二、设计原理 如图18.1所示,用AT89S51单片机产生“嘀、嘀、„”报警声并从P1.0端口输出,产生1KHz的频率。根据图18.1可知:1KHZ方波从P1.0输出0.2秒,接着的0.2秒从P1.0输出电平信号,如此循环下去,就形成所需的报警声了。 三、参考电路 图18.1 “嘀、嘀、„„”报警声电路原理图 四、电路硬件说明 82 (1)在“单片机系统”区域中,把P1.0端口连接到“音频放大模块”区域中的SPK IN端口上。 (2)在“音频放大模块”区域中,在SPK OUT端口上连接一个8欧或16欧的喇叭。 五、程序设计内容 (1)生活中常常会遇到各种各样的报警声,例如“嘀、嘀、„”就是常见的一种声音 ”0.2秒钟,然后断0.2秒钟,如此循环下去。假报警声。但对于这种报警声,应该是“嘀 设“嘀”的频率为1KHz,则报警声时序如图18.2所示: 图18.2 报警声时序图 (2)上述波形信号如何用单片机来产生呢, 由于要产生上面的信号,把上面的信号分成两部分:一部分为1KHZ方波,占用时间为0.2秒;另一部分为低电平,也是占用0.2秒。因此,利用单片机的定时/计数器T0作为定时,可以定时0.2秒。同时,也用单片机产生1KHZ的方波,对于1KHZ的方波信号周期为1ms,高电平占用0.5ms,低电平占用0.5ms。所以也采用定时器T0来完成0.5ms的定时。最后,可以选定定时/计数器T0的定时时间为0.5ms。而要定时的0.2秒是0.5ms的400倍,也就是说以0.5ms定时400次就达到0.2秒的定时时间了。 六、程序流程图(如图18.3所示) 图18.3(a) “嘀、嘀、„„”报警声主程序框图 83 “嘀、嘀、„„”报警声中断服务程序框图 图18.3(b) 七、汇编源程序 ;;;;;;;;;;定义单元;;;;;;;;;; COUNT EQU 30H ;;;;;;;;;;入口地址;;;;;;;;;; ORG 0000H LJMP START ORG 0003H RETI ORG 000BH RETI ORG 0013H RETI 001BH ORG RETI ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序入口;;;;;;;;;;; ORG 0100H START: LCALL BAOJING LCALL DIANPING LJMP START 84 ;;;;;;;;;;报警信号程序;;;;;;;;;; BAOJING: MOV R7,#4 BAOJING_2: MOV R6,#100 BAOJING_1: CPL P1.0 LCALL DELAY05 DJNZ R6,BAOJING_1 DJNZ R7,BAOJING_2 RET ;;;;;;;;;;电平信号程序;;;;;;;;;; DIANPING: MOV R7,#4 DIANPING_3: MOV R6,#100 DIANPING_4: CLR P1.0 LCALL DELAY05 DJNZ R6,DIANPING_4 DJNZ R7,DIANPING_3 RET ;;;;;;;;;;5ms延时程序;;;;;;;;;; DELAY05: MOV R5,#20 DELAY05_1: MOV TMOD,#02H MOV TH0,#00H TL0,#06H MOV SETB TR0 JNB TF0,$ DJNZ R5,DELAY05_1 RET ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序 #include bit FLAG; unsigned char i; void main(void) { TMOD=0x01; //设置为定时器0方式1// TH0=(65536-1000)/256; //给定时器0赋初值// TL0=(65536-1000)%256; ET0=1; //开启定时器0溢出中断// EA=1; //开启中断总开关// TR0=1; //开启定时器0// while(1); //等待中断// } void t0(void) interrupt 1 using 0 { TH0=(65536-1000)/256; //重新赋值// TL0=(65536-1000)%256; 85 i++; //每到一个1毫秒,i加1// if(i==200) //计时到0.2秒时,i清0,重新计// { i=0; FLAG=~FLAG; //每0.2秒FLAG变换一次// } if(FLAG==1) //如果FLAG为1时,P1.0输出1KHZ的信号// P1_0=~P1_0; } { } 九、注意事项 在硬件电路中,要把2联拨动拨码开关JP5的第一个开关拨上去。 86 实验十九 “叮咚”门铃设计 一、实验目的 1. 了解“叮咚”门铃的设计原理。 2. 掌握不同频率信号的设计方法。 二、设计原理 当按下开关S18,AT89S51单片机产生的“叮咚”声从P1.0端口输出到LM386,经过放大之后送入喇叭。 三、参考电路 图19.1 “叮咚”门铃设计电路原理图 四、电路硬件说明 在“单片机系统”区域中,把单片机的P3.7端口通过8联拨动拨码开关JP2连接到“独立式键盘”区域中的S18端口上。把P1.0端口连接到“音频放大模块”区域中的SPK IN端口上,并 在“音频放大模块”区域中的SPK OUT端口上连接一个8欧或16欧的喇叭。 把P3.7端口通过拨动开关JP2连接到“独立式键盘”区域中的S18端口上。 五、程序设计内容 87 (1)用单片机定时/计数器T0来设计产生700HZ和500HZ的频率。用定时/计数器T0,取定时250us。因此,700HZ的频率要经过3次250us的定时,而500HZ的频率要经过4次250us的定时。 (2)在设计中,只有当按下SP1之后,才启动T0开始工作。当T0工作完毕,回到最初状态。 (3)“叮”和“咚”声音各占用0.5秒,因此定时/计数器T0要完成0.5秒的定时,对于以250us为基准定时2000次才可以。 六、程序流程图(如图19.2所示) 图19.2 “叮咚”门铃 七、汇编源程序 ;;;;;;;;;;定义单元;;;;;;;;;; T500HZ EQU 30H T700HZ EQU 31H T05SA EQU 32H T05SB EQU 33H FLAG EQU 00H STOP EQU 01H ;;;;;;;;;;入口地址;;;;;;;;;; ORG 0000H LJMP START ORG 0003H RETI ORG 000BH LJMP INT_T0 ORG 0013H 88 RETI ORG 001BH RETI ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序入口;;;;;;;;;; ORG 0100H START: LCALL CHUSHIHUA LCALL LINGSHENG LJMP START ;;;;;;;;;;初始化程序;;;;;;;;;; CHUSHIHUA: MOV TMOD,#02H MOV TH0,#06H MOV TL0,#06H SETB ET0 SETB EA RET ;;;;;;;;;;铃声程序;;;;;;;;;; LINGSHENG: JB P3.7,LINGSHENG LCALL DELAY10MS JB P3.7,LINGSHENG SETB TR0 CLR FLAG CLR STOP MOV T500HZ,#00H MOV T700HZ,#00H MOV T05SA,#00H MOV T05SB,#00H JNB STOP,$ LJMP LINGSHENG ;;;;;;;;;;10ms延时程序;;;;;;;;;; DELAY10MS: MOV R6,#20 D1: MOV R7,#248 DJNZ R7,$ DJNZ R6,D1 RET ;;;;;;;;;;中断程序;;;;;;;;;; INT_T0: INC T05SA MOV A,T05SA CJNE A,#100,INT_T0_2 MOV T05SA,#00H INC T05SB 89 MOV A,T05SB CJNE A,#20,INT_T0_2 MOV T05SB,#00H JB FLAG,INT_T0_1 CPL FLAG LJMP INT_T0_2 INT_T0_1: SETB STOP CLR TR0 LJMP INT_T0_0 INT_T0_2: JB FLAG,INT_T0_3 INC T700HZ MOV A,T700HZ CJNE A,#03H,INT_T0_0 MOV T700HZ,#00H CPL P1.0 LJMP INT_T0_0 INT_T0_3: INC T500HZ MOV A,T500HZ CJNE A,#04H,INT_T0_0 MOV T500HZ,#00H CPL P1.0 LJMP INT_T0_0 INT_T0_0: RETI ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序 #include unsigned char i,j; unsigned char T7KHZ,T5KHZ; unsigned int k; bit FLAG; bit STOP; void main(void) { TMOD=0x02; //设置为定时器0方式2// TH0=0x06; //给定时器0赋初值// TL0=0x06; ET0=1; //开定时器0中断// EA=1; //开中断总开关// while(1) { if(P3_7==0) //判断P3.7是否按下// { for(i=10;i>0;i--) //延时一段时间// for(j=248;j>0;j--); if(P3_7==0) //再次判断P3.7是否真的按下// 90 { FLAG=0; //所用的条件赋初值// STOP=0; TR0=1; //开启定时器0// while(STOP==0); //等待STOP为1// } } } } void t0(void) interrupt 1 using 0 { k++; //用k记下中断到来次数// if(k==2000) //看中断到来的次数是否到了2000次// { k=0; //如果中断到了2000次,则0.5秒的时间到// if(FLAG==0) //如果0.5秒后FLAG为0,FLAG取反变为1// { FLAG=~FLAG; } else //如果第二个0.5秒后FLAG为1,则STOP为1,停止计时// { STOP=1; TR0=0; } } if(FLAG==0) //如果FLAG为0,P1.0口输出7KHZ的信号// T7KHZ++; { if(T7KHZ==3) { T7KHZ=0; P1_0=~P1_0; } } else //如果FLAG为1,P1.0口输出5KHZ的信号// { T5KHZ++; if(T5KHZ==4) { T5KHZ=0; P1_0=~P1_0; } } } 九、注意事项 在C语言程序中,一定要注意全局变量和局部变量的定义。 91 实验二十 智能电子钟设计 一、实验目的 1(了解智能电子钟的设计原理。 2.掌握定时器的用法。 .掌握时、分、秒的计时和显示方法。 3 4.掌握加法和减法的设计方法。 二、设计原理 如图20.1所示, LED数码管时钟电路采用24h计时方式,时、分、秒用六位数码管显示。该电路只使用开关即可进入调时、省电(不显示数码管)和正常显示三种状态。 三、参考电路 图20.1 智能电子钟电路原理图 92 四、电路硬件说明 (1)在“单片机系统”中,把单片机的P3.5、P3.6、P3.7端口通过拨动开关连接到“独立式键盘”区域中的S16、S17、S18端口上。 (2)把8排针接插件J3的8个黄色跳线帽全部插到下面,使单片机的P1口连接到“动 P2.1对应S2„„P2.5对应S6。 态数码显示模块”区域上,拨动拨码开关使P2.0对应S1, 五、程序设计内容(由于按键在0.5和1秒之内不好控制,所以在C语言中用三个按键来调整时间) (1)在汇编程序中,按下按键,若按下时间小于1s,进入省电状态(数码管不亮,时钟不停),否则进入调分状态,等待操作。此时计时器停止走动。当再次按下按钮,若按下时间小于0.5s则时间加1min;若按下时间大于0.5s,则进入小时调整状态。在小时调整状态下,当按键按下的时间大于0.5s时退出调整状态,时钟继续走动。 (2)在C语言程序中,利用与单片机的P3.5、P3.6、P3.7这三个端口相连的三个键设置时、分、秒。 六、程序流程图(如图20..2所示) 图20.2 智能电子钟设计流程图 七、汇编源程序 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 中断入口程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ORG 0000H ;程序执行开始地址 93 LJMP START ;跳到标号START执行 ORG 0003H ;外中断0中断程序入口 RETI ;外中断0中断返回 ORG 000BH ;定时器T0中断程序入口 LJMP INTT0 ;跳至INTTO执行 ORG 0013H ;外中断1中断程序入口 RETI ;外中断1中断返回 ORG 001BH ;定时器T1中断程序入口 LJMP INTT1 ;跳至INTT1执行 ORG 0023H ;串行中断程序入口地址 RETI ;串行中断程序返回 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 主 程 序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; START: MOV R0,#70H ;清70H-7AH共11个内存单元 MOV R7,#0BH CLEARDISP: MOV @R0,#00H INC R0 DJNZ R7,CLEARDISP MOV 20H,#00H ;清20H(标志用) ;放入"熄灭符"数据 MOV 7AH,#0AH MOV TMOD,#11H ;设T0、T1为16位定时器 MOV TL0,#0B0H ;50MS定时初值(T0计时用) MOV TH0,#3CH ;50MS定时初值 MOV TL1,#0B0H ;50MS定时初值(T1闪烁定时用) MOV TH1,#3CH ;50MS定时初值 SETB EA ;总中断开放 SETB ET0 ;允许T0中断 SETB TR0 ;开启T0定时器 MOV R4,#14H ;1秒定时用初值(50MS×20) START1: LCALL DISPLAY ;调用显示子程序 JNB P3.7,SETMM1 ;P3.7口为0时转时间调整程序 SJMP START1 ;P3.7口为1时跳回START1 SETMM1: LJMP SETMM ;转到时间调整程序SETMM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 1秒计时程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;T0中断服务程序 INTT0: PUSH ACC ;累加器入栈保护 PUSH PSW ;状态字入栈保护 CLR ET0 ;关T0中断允许 CLR TR0 ;关闭定时器T0 MOV A,#0B7H ;中断响应时间同步修正 ADD A,TL0 ;低8位初值修正 94 MOV TL0,A ;重装初值(低8位修正值) MOV A,#3CH ;高8位初值修正 ADDC A,TH0 MOV TH0,A ;重装初值(高8位修正值) SETB TR0 ;开启定时器T0 DJNZ R4, OUTT0 ;20次中断未到中断退出 ADDSS: MOV R4,#14H ;20次中断到(1秒)重赋初值 MOV R0,#71H ;指向秒计时单元(71H-72H) ACALL ADD1 ;调用加1程序(加1秒操作) MOV A,R3 ;秒数据放入A(R3为2位十进制数组合) CLR C ;清进位标志 CJNE A,#60H,ADDMM ADDMM: JC OUTT0 ;小于60秒时中断退出 ACALL CLR0 ;大于或等于60秒时对秒计时单元清0 MOV R0,#77H ;指向分计时单元(76H-77H) ACALL ADD1 ;分计时单元加1分钟 MOV A,R3 ;分数据放入A CLR C ;清进位标志 CJNE A,#60H,ADDHH ADDHH: JC OUTT0 ;小于60分时中断退出 ;大于或等于60分时分计时单元清0 ACALL CLR0 MOV R0,#79H ;指向小时计时单(78H-79H) ACALL ADD1 ;小时计时单元加1小时 MOV A,R3 ;时数据放入A CLR C ;清进位标志 CJNE A,#24H,HOUR HOUR: JC OUTT0 ;小于24小时中断退出 ACALL CLR0 ;大于或等于24小时小时计时单元清0 OUTT0: MOV 72H,76H ;中断退出时将分、时计时单元数据移 MOV 73H,77H ;入对应显示单元 MOV 74H,78H MOV 75H,79H POP PSW ;恢复状态字(出栈) POP ACC ;恢复累加器 SETB ET0 ;开放T0中断 RETI ;中断返回 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 闪动调时 程 序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;T1中断服务程序,用作时间调整时调整单元闪烁指示 INTT1: PUSH ACC ;中断现场保护 PUSH PSW MOV TL1,#0B0H ;装定时器T1定时初值 MOV TH1,#3CH 95 DJNZ R2,INTT1OUT ;0.3秒未到退出中断(50MS中断6次) MOV R2,#06H ;重装0.3秒定时用初值 CPL 02H ;0.3秒定时到对闪烁标志取反 JB 02H,FLASH1 ;02H位为1时显示单元"熄灭" MOV 72H,76H ;02H位为0时正常显示 MOV 73H,77H MOV 74H,78H MOV 75H,79H INTT1OUT: POP PSW ;恢复现场 POP ACC RETI ;中断退出 FLASH1: JB 01H,FLASH2 ;01H位为1时,转小时熄灭控制 MOV 72H,7AH ;01H位为0时,"熄灭符"数据放入分 MOV 73H,7AH ;显示单元(72H-73H),将不显示分数据 MOV 74H,78H MOV 75H,79H AJMP INTT1OUT ;转中断退出 FLASH2: MOV 72H,76H ;01H位为1时,"熄灭符"数据放入小时 MOV 73H,77H ;显示单元(74H-75H),小时数据将不显示 MOV 74H,7AH MOV 75H,7AH AJMP INTT1OUT ;转中断退出 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 加1子 程 序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ADD1: MOV A,@R0 ;取当前计时单元数据到A DEC R0 ;指向前一地址 SWAP A ;A中数据高四位与低四位交换 ORL A,@R0 ;前一地址中数据放入A中低四位 ADD A,#01H ;A加1操作 DA A ;十进制调整 MOV R3,A ;移入R3寄存器 ANL A,#0FH ;高四位变0 MOV @R0,A ;放回前一地址单元 MOV A,R3 ;取回R3中暂存数据 INC R0 ;指向当前地址单元 SWAP A ;A中数据高四位与低四位交换 ANL A,#0FH ;高四位变0 MOV @R0,A ;数据放入当削地址单元中 RET ;子程序返回 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 清零程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;对计时单元复零用 96 CLR0: CLR A ;清累加器 MOV @R0,A ;清当前地址单元 DEC R0 ;指向前一地址 MOV @R0,A ;前一地址单元清0 RET ;子程序返回 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 时钟调整程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;当调时按键按下时进入此程序 SETMM: CLR ET0 ;关定时器T0中断 CLR TR0 ;关闭定时器T0 LCALL DL1S ;调用1秒延时程序 JB P3.7,CLOSEDIS ;键按下时间小于1秒,关闭显示(省电) MOV R2,#06H ;进入调时状态,赋闪烁定时初值 SETB ET1 ;允许T1中断 SETB TR1 ;开启定时器T1 SET2: JNB P3.7,SET1 ;P3.7口为0(键未释放),等待 SETB 00H ;键释放,分调整闪烁标志置1 SET4: JB P3.7,SET3 ;等待键按下 LCALL DL05S ;有键按下,延时0.5秒 P3.7,SETHH ;按下时间大于0.5秒转调小时状态 JNB MOV R0,#77H ;按下时间小于0.5秒加1分钟操作 LCALL ADD1 ;调用加1子程序 MOV A,R3 ;取调整单元数据 CLR C ;清进位标志 CJNE A,#60H,HHH ;调整单元数据与60比较 HHH: JC SET4 ;调整单元数据小于60转SET4循环 LCALL CLR0 ;调整单元数据大于或等于60时清0 CLR C ;清进位标志 AJMP SET4 ;跳转到SET4循环 CLOSEDIS: SETB ET0 ;省电(LED不显示)状态。开T0中断 SETB TR0 ;开启T0定时器(开时钟) CLOSE: JB P3.7,CLOSE ;无按键按下,等待。 LCALL DISPLAY ;有键按下,调显示子程序延时削抖 JB P3.7,CLOSE ;是干扰返回CLOSE等待 WAITH: JNB P3.7,WAITH ;等待键释放 LJMP START1 ;返回主程序(LED数据显示亮) SETHH: CLR 00H ;分闪烁标志清除(进入调小时状态) SETHH1: JNB P3.7,SET5 ;等待键释放 SETB 01H ;小时调整标志置1 SET6: JB P3.7,SET7 ;等待按键按下 LCALL DL05S ;有键按下延时0.5秒 JNB P3.7,SETOUT ;按下时间大于0.5秒退出时间调整 MOV R0,#79H ;按下时间小于0.5秒加1小时操作 97 LCALL ADD1 ;调加1子程序 MOV A,R3 CLR C CJNE A,#24H,HOUU ;计时单元数据与24比较 HOUU: JC SET6 ;小于24转SET6循环 LCALL CLR0 ;大于或等于24时清0操作 AJMP SET6 ;跳转到SET6循环 SETOUT: JNB P3.7,SETOUT1 ;调时退出程序。等待键释放 LCALL DISPLAY ;延时削抖 JNB P3.7,SETOUT ;是抖动,返回SETOUT再等待 CLR 01H ;清调小时标志 CLR 00H ;清调分标志 CLR 02H ;清闪烁标志 CLR TR1 ;关闭定时器T1 CLR ET1 ;关定时器T1中断 SETB TR0 ;开启定时器T0 SETB ET0 ;开定时器T0中断(计时开始) LJMP START1 ;跳回主程序 SET1: LCALL DISPLAY ;键释放等待时调用显示程序(调分) AJMP SET2 ;防止键按下时无时钟显示 SET3: LCALL DISPLAY ;等待调分按键时时钟显示用 AJMP SET4 SET5: LCALL DISPLAY ;键释放等待时调用显示程序(调小时) AJMP SETHH1 ;防止键按下时无时钟显示 SET7: LCALL DISPLAY ;等待调小时按键时时钟显示用 AJMP SET6 SETOUT1: LCALL DISPLAY ;退出时钟调整时键释放等待 AJMP SETOUT ;防止键按下时无时钟显示 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 显示程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 显示数据在70H-75H单元内,用六位LED共阳数码管显示,P0口输出 ;段码数据,P3口作扫描控制,每个LED数码管亮1MS时间再逐位循环。 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DISPLAY: MOV R1,#70H ;指向显示数据首址 MOV R5,#0FEH ;扫描控制字初值 PLAY: MOV A,R5 ;扫描字放入A MOV P2,A ;从P2口输出 MOV A,@R1 ;取显示数据到A MOV DPTR,#TAB ;取段码表地址 MOVC A,@A+DPTR ;查显示数据对应段码 MOV P1,A ;段码放入P0口 LCALL DL1MS ;显示1MS INC R1 ;指向下一地址 98 MOV A,R5 ;扫描控制字放入A JNB ACC.5,ENDOUT ;ACC.5=0时一次显示结束 RL A ;A中数据循环左移 MOV R5,A ;放回R5内 AJMP PLAY ;跳回PLAY循环 ENDOUT: SETB P2.5 ;一次显示结束,P2口复位 MOV P1,#0FFH ;P0口复位 RET ;子程序返回 TAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;1MS延时程序,LED显示程序用 DL1MS: MOV R6,#14H DL1: MOV R7,#19H DL2: DJNZ R7,DL2 DJNZ R6,DL1 RET ;20MS延时程序,采用调用显示子程序以改善LED的显示闪烁现象 DS20MS: ACALL DISPLAY ACALL DISPLAY ACALL DISPLAY RET ;延时程序,用作按键时间的长短判断 DL1S: LCALL DL05S LCALL DL05S RET DL05S: MOV R3,#20H ;8毫秒*32=0.196秒 DL05S1: LCALL DISPLAY DJNZ R3,DL05S1 RET END ;程序结束 八、C语言源程序 #include unsigned char code SHUOZI[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71,0x00}; unsigned char SHAOMIAO[]={0xfe,0xfd,0xfb,0xf7, //扫描码// 0xef,0xdf,0xbf,0x7f}; unsigned char DANYUAN[8]={0,0,16,0,0,16,0,0}; unsigned char k,a,second,minite,hour; unsigned int m; void main(void) { unsigned char i,j; TMOD=0x02; //设置定时器0方式2// 99 TH0=0x06; //赋初值// TL0=0x06; ET0=1; //开定时器0中断// EA=1; //开总的中断开关// TR0=1; //开定时器0// while(1) { if(P3_7==0) //判断P3.7是否按下// { for(i=10;i>0;i--) //延时等待// for(j=248;j>0;j--); if(P3_7==0) //再次判断// { second++; //如果按下,秒加1// if(second==60) //看是否秒加到60// { second=0; } //如果秒加到60,重新计// DANYUAN[0]=second%10; //所加秒数的个位放入DANYUAN[0]中// DANYUAN[1]=second/10; //所加秒数的十位放入DANYUAN[1]中// while(P3_7==0); //等待P3.7按键弹起// } } if(P3_6==0) //判断P3.6是否按下// { for(i=10;i>0;i--) //延时等待// ); for(j=248;j>0;j-- if(P3_6==0) //再次判断是否真的按下// { minite++; //如果按下分钟加1// if(minite==60) //如果分钟数加到60// { minite=0; } //重新计分钟数// DANYUAN[3]=minite%10;//所加分钟数的个位放入DANYUAN[3]中// DANYUAN[4]=minite/10;//所加分钟数的十位放入DANYUAN[4]中// while(P3_6==0); //等待P3.6按键弹起// } } if(P3_5==0) //判断P3.5是否按下// { for(i=10;i>0;i--) //延时等待// for(j=248;j>0;j--); if(P3_5==0) //再次判断是否真的按下// { hour++; //如是,小时数加1// if(hour==24) //看是否加到24小时// { hour=0; } //如果加到24小时,重新计// DANYUAN[6]=hour%10; //所加小时数的个位放入DANYUAN[6]中// DANYUAN[7]=hour/10; //所加小时数的十位放入DANYUAN[7]中// while(P3_5==0); //等待P3.5按键弹起// } } } } 100 void t0(void) interrupt 1 using 0 //中断程序// { k++; //记下中断到来的次数// if(k==8) //看是否来到8次// { k=0; //如果到来8次,重新记// P1=SHUOZI[DANYUAN[a]]; //取显示数显示// P2=SHAOMIAO[a]; //取扫描数扫描// 指向下一个单元// a++; //每显示一个单元,a加一次, if(a==8) //如果显示完8个单元,重新显示// { a=0; } } m++; //同样,m出记下中断到来的次数// if(m==4000) //如果到来4000次中断,即1秒到来1次// { m=0; //重新记下中断次数// second++; //每来1秒,second加1// if(second==60) //看是否记到60秒// { second=0; //如果到了60秒,second重新计// minite++; //每到60秒,minite加1// if(minite==60) //看是否到了60分// { minite=0; //如果到了60分钟,重新计// hour++; //每来60分钟,hour加1// if(hour==24) //看是否到了24小时// { hour=0; } //如果到了24小时,重新计// } } DANYUAN[0]=second%10; //相应的数给相应的单元显示// DANYUAN[1]=second/10; DANYUAN[3]=minite%10; DANYUAN[4]=minite/10; DANYUAN[6]=hour%10; DANYUAN[7]=hour/10; } } 九、注意事项 检查硬件电路是否达到要求。 101 实验二十一 “新年好”音乐设计 一、实验目的 1(了解“新年好”音乐的设计原理。 2. 掌握中断在频率设计中的应用。 3. 掌握给定时器赋变量的方法。 二、设计原理 如图21.1,用AT89S51单片机产生优美的音乐声从P1.0端口输出。通过定时器的定时来产生不同频率的方波,驱动喇叭发出不同音阶的声音,再利用延迟来控制发音时间的长短,即可控制音调中的节拍。 三、参考电路 图21.1 “新年好”音乐电路原理图 四、电路硬件说明 102 (1)在“单片机系统”中,把P1.0端口连接到“音频放大模块”区域中的SPK IN端口。 (2)在“音频放大模块”区域中的SPK OUT端口连接一个8欧或者是16欧的喇叭。 五、程序设计内容 (1)音乐产生的方法: 一首音乐是由许多不同的音阶组成的,而每个音阶对应着不同的频率。这样就可以利用不同的频率的组合,构成所想要的音乐了。当然,对于单片机来说产生不同的频率非常方便, 计数器T0来产生这样的方波频率信号。所以,只要把一首歌曲的音可以利用单片机的定时/ 阶对应频率关系弄正确即可。现在以单片机12MHZ晶振为例,列出高、中、低音符与单片机计数T0相关的计数值。如下表21.2所示: 表21.2 音符与频率对照表 音符 频率(HZ) 简谱码(T值) 音符 频率(HZ) 简谱码(T值) 低1 DO 262 63628 # 4 FA# 740 64860 #1 DO# 277 63731 中 5 SO 784 64898 低2 RE 294 63835 # 5 SO# 831 64934 #2 RE# 311 63928 中 6 LA 880 64968 低 3 M 330 64021 # 6 932 64994 低 4 FA 349 64103 中 7 SI 988 65030 # 4 FA# 370 64185 高 1 DO 1046 65058 低 5 SO 392 64260 # 1 DO# 1109 65085 # 5 SO# 415 64331 高 2 RE 1175 65110 低 6 LA 440 64400 # 2 RE# 1245 65134 # 6 466 64463 高 3 M 1318 65157 低 7 SI 494 64524 高 4 FA 1397 65178 中 1 DO 523 64580 # 4 FA# 1480 65198 # 1 DO# 554 64633 高 5 SO 1568 65217 中 2 RE 587 64684 # 5 SO# 1661 65235 # 2 RE# 622 64732 高 6 LA 1760 65252 中 3 M 659 64777 # 6 1865 65268 中 4 FA 698 64820 高 7 SI 1967 65283 下面为这个音符建立一个表格,有助于单片机通过查表的方式来获得相应的数据,低音在0,19之间,中音在20,39之间,高音在40,59之间。 TABLE: DW 0,63628,63835,64021,64103,64260,64400,64524,0,0 DW 0,63731,63928,0,64185,64331,64463,0,0,0 DW 0,64580,64684,64777,64820,64898,64968,65030,0,0 DW 0,64633,64732,0,64860,64934,64994,0,0,0 DW 0,65058,65110,65157,65178,65217,65252,65283,0,0 DW 0,65085,65134,0,65198,65235,65268,0,0,0 DW 0 103 2、下表21.3为音乐的音拍和延时的时间,其中节拍以C调为单位。 表21.3 节拍与延时对照表 曲调值 DELAY 曲调值 DELAY 调4/4 125ms 调4/4 62ms 调3/4 187ms 调3/4 94ms 调2/4 250ms 调2/4 125ms 3、对于不同的曲调也可以用单片机的另外一个定时/计数器来完成。 下面就AT89S51单片机如何产生“新年好”歌曲来说明。在这个程序中是利用两个定时/计数器来完成的。其中T0用来产生音符频率,T1用来产生音拍。 六、程序流程图(如图21.4所示) 图21.4 “新年好”音乐设计流程图 七、汇编源程序 ;;;;;;;;;;入口地址;;;;;;;;;; ORG 0000H LJMP START ORG 0003H RETI ORG 000BH LJMP INT_T0 ORG 0013H RETI ORG 001BH RETI 104 ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序入口;;;;;;;;;; ORG 0100H START: LCALL CHUSHIHUA LCALL MAIN LJMP START ;;;;;;;;;;初始化程序;;;;;;;;;; CHUSHIHUA: MOV TMOD,#01H MOV IE,#82H MOV DPTR,#TABLE RET ;;;;;;;;;;音乐产生程序;;;;;;;;;; MAIN: CLR A MOVC A,@A+DPTR MOV R1,A INC DPTR CLR A MOVC A,@A+DPTR MOV R0,A ORL A,R1 JZ MAIN_1 MOV A,R0 ANL A,R1 CJNE A,#0FFH,MAIN_2 LJMP MAIN_0 MAIN_2: MOV TH0,R1 MOV TL0,R0 SETB TR0 SJMP MAIN_3 MAIN_1: CLR TR0 MAIN_3: CLR A INC DPTR MOVC A,@A+DPTR MOV R2,A MAIN_4: LCALL DELAY200 DJNZ R2,MAIN_4 INC DPTR LJMP MAIN MAIN_0: RET ;;;;;;;;;;中断程序;;;;;;;;;; INT_T0: MOV TH0,R1 105 MOV TL0,R0 CPL P1.0 RETI ;;;;;;;;;;200ms延时程序;;;;;;;;;; DELAY200: MOV R3,#20 DELAY200A: MOV R4,#20 R5,#248 DELAY200B: MOV DJNZ R5,$ DJNZ R4,DELAY200B DJNZ R3,DELAY200A RET ;;;;;;;;;;音符音节代码表;;;;;;;;;; TABLE: DB 0FEH, 25H,02H, 0FEH,25H,02H DB 0FEH,25H,04H,0FDH,80H,04H DB 0FEH,84H,02H,0FEH,84H,02H DB 0FEH,84H,04H,0FEH,25H,04H DB 0FEH,25H,02H,0FEH,84H,02H DB 0FEH,0C0H,04H,0FEH,0C0H,04H DB 0FEH,98H,02H,0FEH,84H,02H DB 0FEH,57H,08H,00H,00H,04H DB 0FFH,0FFH ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序 #include unsigned char code YINFU[]={0xfe,0x25,0x02,0xfe,0x25,0x02, 0xfe,0x25,0x04,0xfd,0x80,0x04, 0xfe,0x84,0x02,0xfe,0x84,0x02, 0xfe,0x84,0x04,0xfe,0x25,0x04, 0xfe,0x25,0x02,0xfe,0x84,0x02, 0xfe,0xc0,0x04,0xfe,0xc0,0x04, 0xfe,0x98,0x02,0xfe,0x84,0x02, 0xfe,0x57,0x08,0x00,0x00,0x04}; unsigned char m,n,a,b; void delay200ms(void) //0.2秒延时子程序// { unsigned char i,j,k; for(i=20;i>0;i--) { for(j=20;j>0;j--) { for(k=248;k>0;k--); } } } void main(void) { TMOD=0x01; //设置为定时器0方式1// 106 ET0=1; //开启定时器0中断// EA=1; //开启中断总开关// m=0; //设置m查找音符的高位// n=1; //设置n查找音符的低位// a=2; //设置a查找音节产生的数// while(1) { TR0=1; //开启定时器0// TH0=YINFU[m]; //取产生音符的初值给定时器0// TL0=YINFU[n]; b=YINFU[a]; //取出要产生的音节数// for(b;b>0;b--) //以0.2秒为最小单元的音节产生方式// { delay200ms(); } m=m+3; //每隔三位取一次// n=n+3; a=a+3; if(a==47) //每加到47时为音乐演奏完// { m=0; //演奏完时,重新赋值// n=1; a=2; } } } void t0(void) interrupt 1 using 0 //中断程序// { TH0=YINFU[m]; TL0=YINFU[n]; P1_0=~P1_0; } 九、注意事项 在程序中,应该特别注意音符和节拍的频率以及周期设置。 107 实验二十二 电子琴设计 一、实验目的 1.了解电子琴的设计原理。 2.掌握矩阵键盘的识别方法。 .掌握音符的产生方法。 3 二、设计原理 (1)由4X4组成16个按钮矩阵,设计成16个音。 (2)可随意弹奏想要表达的音乐。 三、参考电路 图22.1 电子琴设计电路原理图 四、电路硬件说明 108 (1)在“单片机系统”区域中,把单片机的P1.0端口利用导线连接到“音频放大模块”区域中的SPK IN端口上; (2)在“单片机系统“区域中,把单片机的P3.0,P3.7端口连接到“4X4行列式键盘”区域中的M1-M4与N1-N4端口上。 五、程序设计内容 (1)要想了解音乐,就得知道低、中、高音部分。所以给出了4X4行列式键盘与音符的对应关系表22.2: 表22.2 音符与键盘对照表 键值 对应音符 键值 对应音符 键值 对应音符 2 1(中) 7 6(中) 1 5(低) 6 2(中) B 7(中) C 4(低) A 3(中) F 1(高) 8 3(低) E 4(中) 9 7(低) 4 2(低) 3 5(中) 5 6(低) 0 1(低) (2)下面给出了产生相应音符的频率值: TABLE1: DB 0FAH,15H,0FAH,67H,0FBH,06H,0FBH,90H DB 0FCH,0CH,0FCH,44H,0FCH,0ACH,0FDH,09H 0FDH,34H,0FDH,82H,0FDH,0C8H,0FEH,06H DB DB 0FEH,22H,0FEH,56H,0FEH,85H,0FEH,9AH 六、程序流程图(如图22.3所示) 109 图22.3 电子琴设计流程图 七、汇编源程序 ;;;;;;;;;;定义单元;;;;;;;;;; COUNT EQU 30H STH0 EQU 31H 32H STL0 EQU SECOND EQU 33H ;;;;;;;;;;入口地址;;;;;;;;;; ORG 0000H LJMP START ORG 0003H RETI ORG 000BH LJMP INT_T0 ORG 0013H RETI ORG 001BH RETI ORG 0023H RETI ORG 002BH RETI ;;;;;;;;;;主程序入口;;;;;;;;;; ORG 0100H START: LCALL CHUSHIHUA LCALL PANDUAN LCALL XIANSHI LJMP START ;;;;;;;;;;初始化程序;;;;;;;;;; CHUSHIHUA: MOV COUNT,#00H MOV STH0,#00H MOV STL0,#00H MOV SECOND,#00H MOV TMOD,#01H MOV IE,#82H RET ;;;;;;;;;;判断哪个按键按下程序;;;;;;;;;; PANDUAN: MOV P3,#0FFH CLR P3.4 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ PANDUAN_1_1 110 LCALL DELAY10MS JZ PANDUAN_1_1 MOV A,P3 ANL A,#0FH CJNE A,#0EH,PANDUAN_1 MOV COUNT,#0 LJMP PANDUAN_0 PANDUAN_1: CJNE A,#0DH,PANDUAN_2 MOV COUNT,#4 LJMP PANDUAN_0 PANDUAN_2: CJNE A,#0BH,PANDUAN_3 MOV COUNT,#8 LJMP PANDUAN_0 PANDUAN_3: CJNE A,#07H,PANDUAN_4 MOV COUNT,#12 PANDUAN_4: NOP LJMP PANDUAN_0 PANDUAN_1_1: MOV P3,#0FFH CLR P3.5 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ PANDUAN_1_2 LCALL DELAY10MS JZ PANDUAN_1_2 MOV A,P3 ANL A,#0FH CJNE A,#0EH,PANDUAN_5 MOV COUNT,#1 LJMP PANDUAN_0 PANDUAN_5: CJNE A,#0DH,PANDUAN_6 MOV COUNT,#5 LJMP PANDUAN_0 PANDUAN_6: CJNE A,#0BH,PANDUAN_7 MOV COUNT,#9 LJMP PANDUAN_0 PANDUAN_7: CJNE A,#07H,PANDUAN_8 MOV COUNT,#13 PANDUAN_8: NOP LJMP PANDUAN_0 PANDUAN_1_2: MOV P3,#0FFH CLR P3.6 MOV A,P3 ANL A,#0FH 111 XRL A,#0FH JZ PANDUAN_1_3 LCALL DELAY10MS JZ PANDUAN_1_3 MOV A,P3 ANL A,#0FH CJNE A,#0EH,PANDUAN_9 MOV COUNT,#2 LJMP PANDUAN_0 PANDUAN_9: CJNE A,#0DH,PANDUAN_A MOV COUNT,#6 LJMP PANDUAN_0 PANDUAN_A: CJNE A,#0BH,PANDUAN_B MOV COUNT,#10 LJMP PANDUAN_0 PANDUAN_B: CJNE A,#07H,PANDUAN_C MOV COUNT,#14 PANDUAN_C: NOP LJMP PANDUAN_0 PANDUAN_1_3: MOV P3,#0FFH CLR P3.7 MOV A,P3 ANL A,#0FH XRL A,#0FH JZ PANDUAN_1_4 LCALL DELAY10MS JZ PANDUAN_1_4 MOV A,P3 ANL A,#0FH CJNE A,#0EH,PANDUAN_D MOV COUNT,#3 LJMP PANDUAN_0 PANDUAN_D: CJNE A,#0DH,PANDUAN_E MOV COUNT,#7 LJMP PANDUAN_0 PANDUAN_E: CJNE A,#0BH,PANDUAN_F MOV COUNT,#11 LJMP PANDUAN_0 PANDUAN_F: CJNE A,#07H,PANDUAN_G MOV COUNT,#15 PANDUAN_G: NOP LJMP PANDUAN_0 PANDUAN_1_4: LJMP PANDUAN PANDUAN_0: RET 112 ;;;;;;;;;;按键代表相应音符程序;;;;;;;;;; XIANSHI: MOV A,COUNT MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,COUNT B,#2 MOV MUL AB MOV SECOND,A MOV DPTR,#TABLE1 MOVC A,@A+DPTR MOV STH0,A MOV TH0,A INC SECOND MOV A,SECOND MOVC A,@A+DPTR MOV STL0,A MOV TL0,A SETB TR0 XIANSHI_1: MOV A,P3 A,#0FH ANL XRL A,#0FH JNZ XIANSHI_1 CLR TR0 RET INT_T0: MOV TH0,STH0 MOV TL0,STL0 CPL P1.0 RETI ;;;;;;;;;;10ms延时程序;;;;;;;;;; DELAY10MS: MOV R6,#20 D1: MOV R7,#248 DJNZ R7,$ DJNZ R6,D1 RET ;;;;;;;;;;200ms延时程序;;;;;;;;;; DELAY: MOV R5,#20 LOOP: LCALL DELAY10MS DJNZ R5,LOOP RET ;;;;;;;;;;共阴按键代码表;;;;;;;;;; TABLE: DB 3FH,06H,5BH,4FH DB 66H,6DH,7DH,07H DB 7FH,6FH,77H,7CH 113 DB 39H,5EH,79H,71H ;;;;;;;;;;音符代码表;;;;;;;;;; TABLE1: DB 0FAH,15H,0FAH,67H,0FBH,06H,0FBH,90H DB 0FCH,0CH,0FCH,44H,0FCH,0ACH,0FDH,09H DB 0FDH,34H,0FDH,82H,0FDH,0C8H,0FEH,06H DB 0FEH,22H,0FEH,56H,0FEH,85H,0FEH,9AH ;;;;;;;;;;结束标志;;;;;;;;;; END 八、C语言源程序 #include unsigned char code XIANSHI[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71}; unsigned int code YINYUE[]={64021,64103,64260,64400, 64524,64580,64684,64777, 64820,64898,64968,65030, 65058,65110,65157,65178}; unsigned char i,j,k,key; void main(void) { TMOD=0x01; //设置定时器0方式1// ET0=1; //开启定时器0溢出中断// EA=1; //开启中断总开关// while(1) { P3=0xff; //给P3口置1// P3_4=0; //扫描P3.4这条件线上的四个按键// k=P3; //用于k判断// k=k&0x0f; //屏蔽高四位,判断低四位// if(k!=0x0f) //判断是否有键按下// { for(i=20;i>0;i--) //延时// for(j=248;j>0;j--); k=P3; //再判断一次// k=k&0x0f; if(k!=0x0f) { switch(k) //看是P3.4这条线上的哪个按键// { case 0x0e: //如果是第一个按键// key=0; //给key赋0// break; case 0x0d: key=1; break; case 0x0b: key=2; break; 114 case 0x07: key=3; break; } P0=XIANSHI[key]; //取表显示相应的按键数// TH0=YINYUE[key]/256; //取相应按键的音符的初值// TL0=YINYUE[key]%256; TR0=1; //开启定时器0// k=P3; k=k&0x0f; while(k!=0x0f) //等待按键弹起// { k=P3; k=k&0x0f; } TR0=0; //按键弹起后,关闭定时器0// } } P3=0xff; //扫描P3.5这条线上的四个键// P3_5=0; k=P3; k=k&0x0f; if(k!=0x0f) { for(i=20;i>0;i--) for(j=248;j>0;j--); k=P3; k=k&0x0f; if(k!=0x0f) { switch(k) { case 0x0e: key=4; break; case 0x0d: key=5; break; case 0x0b: key=6; break; case 0x07: key=7; break; } P0=XIANSHI[key]; TH0=YINYUE[key]/256; TL0=YINYUE[key]%256; 115 TR0=1; k=P3; k=k&0x0f; while(k!=0x0f) { k=P3; k=k&0x0f; } TR0=0; } } P3=0xff; //扫描P3.6这条线上的四个键// P3_6=0; k=P3; k=k&0x0f; if(k!=0x0f) { for(i=20;i>0;i--) for(j=248;j>0;j--); k=P3; k=k&0x0f; if(k!=0x0f) switch(k) { { case 0x0e: key=8; break; case 0x0d: key=9; break; case 0x0b: key=10; break; case 0x07: key=11; break; } P0=XIANSHI[key]; TH0=YINYUE[key]/256; TL0=YINYUE[key]%256; TR0=1; k=P3; k=k&0x0f; while(k!=0x0f) { k=P3; k=k&0x0f; } 116 TR0=0; } } P3=0xff; //扫描P3.7这条线上的四个键// P3_7=0; k=P3; k=k&0x0f; if(k!=0x0f) { for(i=20;i>0;i--) for(j=248;j>0;j--); k=P3; k=k&0x0f; if(k!=0x0f) { switch(k) { case 0x0e: key=12; break; case 0x0d: key=13; break; case 0x0b: key=14; break; case 0x07: key=15; break; } P0=XIANSHI[key]; TH0=YINYUE[key]; TL0=YINYUE[key]; TR0=1; k=P3; k=k&0x0f; while(k!=0x0f) { k=P3; k=k&0x0f; } TR0=0; } } } } void t0(void) interrupt 1 using 0 //中断子程序// { TH0=YINYUE[key]/256; 117 TL0=YINYUE[key]%256; P1_0=~P1_0; } 九、注意事项 在硬件电路中,要把8联拨动拨码开关JP2拨下,把8联拨动拨码开关JP3拨上去。 118 实验二十三 模拟计算器数字输入及显示设计 一、实验目的 1.了解数字计算器的输入法与显示的设计原理。 2.熟练运用一键多功能技术。 熟练运用动态显示技术。 3. 4.熟练运用报警信号的产生方法。 二、设计原理 (1)开机时,显示“0”。 (2)第一次按下时,显示“0D1”;第二次按下时,显示“0D1D2”;第三次按下时,显示“0D1D2D3”,直到8个数全部显示完毕,再按下按键时,给出“嘀”提示音。 三、参考电路 图23.1 模拟计算器数字输入及显示设计电路原理图 四、电路硬件说明 119 (1)在“单片机系统”区域中,把P1.0端口连接到“音频放大模块”区域中的SPK IN端口上; (2)在“单片机系统”区域中,把P3.0,P3.7端口连接到“4X4行列式键盘”区域中的M1,M4 N1,N4端口上; (3) 在“单片机系统”区域中,把P0.0,P0.7端口连接到“动态数码显示”区域中的A,H端口上; 4) 在“单片机系统”区域中,把P2.0,P2.7端口连接到“动态数码显示”区域中( 的S1,S8端口上。 五、程序设计内容 (1)按键识别功能。 (2)行列式键盘输入及按键功能设定。 (3)动态数码显示。 (4)数码显示方式处理。 (5)设定报警功能。 六、程序流程图(如图23.2所示) 图23.2 模拟计算器数字输入及显示设计流程图 七、汇编源程序(略) 八、C语言源程序 #include unsigned char code XIANSHI[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; 120 unsigned char code SHAOMIAO[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//共阴极扫描码表格// unsigned char DANYUAN[8]={0,16,16,16,16,16,16,16}; unsigned char k,key,m,n; bit WEI; void change(unsigned char *p,unsigned char count) while(count>0) { { *(p+count)=*(p+count-1); count--; } } void main(void) { unsigned char i,j; TMOD=0x01; //设置为定时器0方式1// TH0=(65536-2000)/256; //给定时器0赋初值// TL0=(65536-2000)%256; ET0=1; //开定时器0溢出中断// EA=1; //开中断总开关// TR0=1; //开定时器0// while(1) { P3=0xff; P3_4=0; //扫描P3.4这条线上的四个按键// k=P3; k=k&0x0f; if(k!=0x0f) //看P3.4这条线上是否真的有按键按下// { for(i=50;i>0;i--) //延时一段时间// for(j=200;j>0;j--); k=P3; //再判断一次// k=k&0x0f; if(k!=0x0f) { switch(k) //通过可能发生的四种可能比较看是哪个按键按下// { case 0x0e: key=0; break; case 0x0d: key=1; break; case 0x0b: key=2; break; case 0x07: key=3; break; } 121 if((key>=0)&&(key<16)) { m++; //每按下一次按键,m加1// if(m<8) //如果单元没有占满,继续送// { change(DANYUAN,m); //调用函数把低位的数送入高位// DANYUAN[0]=key; //把key中的数送入第一个单元// } else { m=8;//如果8个单元已占满,设置报警信号即WEI为1// WEI=1; } } k=P3; //等待按键弹起// k=k&0x0f; while(k!=0x0f) { k=P3; k=k&0x0f; } WEI=0; //关闭报警信号// } } P3=0xff; P3_5=0; //扫描P3.5这条线上的四个按键// k=P3; k=k&0x0f; if(k!=0x0f) //看P3.5这条线上是否有按键按下// { for(i=50;i>0;i--) //延时等待// for(j=200;j>0;j--); k=P3; //再看一次// k=k&0x0f; if(k!=0x0f) { switch(k) //通过比较看是P3.5这条线上的哪一个按键按下// { case 0x0e: key=4; break; case 0x0d: key=5; break; case 0x0b: key=6; break; case 0x07: key=7; break; } 122 if((key>=0)&&(key<16)) //如果key为0-16中的数,把数送入单元中// { m++; //每按下一次按键,m加1// if(m<8) //如果单元没有占满,继续送// { change(DANYUAN,m); //调用函数把低位的数送入高位// DANYUAN[0]=key; //把key中的数送入第一个单元// } else { m=8; //如果8个单元已占满,设置报警信号即WEI为1// WEI=1; } } k=P3; k=k&0x0f; while(k!=0x0f) //等待按键弹起// { k=P3; k=k&0x0f; } WEI=0; //关闭报警信号// } } P3=0xff; //扫描P3.6这条线上的四个按键是否按下// P3_6=0; k=P3; k=k&0x0f; if(k!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); k=P3; k=k&0x0f; if(k!=0x0f) { switch(k) { case 0x0e: key=8; break; case 0x0d: key=9; break; case 0x0b: key=10; break; case 0x07: key=11; break; } 123 if((key>=0)&&(key<16)) { m++; if(m<8) { change(DANYUAN,m); DANYUAN[0]=key; } else { m=8; WEI=1; } } k=P3; k=k&0x0f; while(k!=0x0f) { k=P3; k=k&0x0f; } WEI=0; } } P3=0xff; //扫描P3.7这条线上的四个按键是否按下// P3_7=0; k=P3; k=k&0x0f; if(k!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); k=P3; k=k&0x0f; if(k!=0x0f) { switch(k) { case 0x0e: key=12; break; case 0x0d: key=13; break; case 0x0b: key=14; break; case 0x07: key=15; break; } 124 if((key>=0)&&(key<16)) { m++; if(m<8) { change(DANYUAN,m); DANYUAN[0]=key; } else { m=8; WEI=1; } } k=P3; k=k&0x0f; while(k!=0x0f) { k=P3; k=k&0x0f; } WEI=0; } } } } void t0(void) interrupt 1 using 0 //中断子程序// { TH0=(65536-2000)/256; //重新给定时器0赋初值// TL0=(65536-2000)%256; P0=XIANSHI[DANYUAN[n]]; //表格中取出的显示码送入P0口// P2=SHAOMIAO[n]; //表格中取出的扫描码送入P2口// n++; if(n==8) //如果8个单元中的数已经取完,重新重低位开始取// { n=0; } if(WEI==1) //如果报警信号到,报警// { P1_0=~P1_0; } } 九、注意事项 在硬件电路中,要把8联拨动拨码开关JP2拨下,把8联拨动拨码开关JP3拨上去。 125 实验二十四 数字电压表设计 一、实验目的 1. 了解数字电压表的设计原理。 2.了解外部数据采集。 .熟悉采集数据的处理。 3 4(掌握ADC0804的功能及用法。 5(熟练掌握动态显示技术及用法。 二、设计原理 如图24.1所示,利用单片机AT89S51与ADC0804设计一个数字电压表,可以测量0,5V之间的直流电压值,并通过三位数码显示。 三、参考电路 图24.1 数字电压表电路原理图 四、电路硬件说明 (1)把8排针接插件J3与单片机P0口连接的黄色跳线帽全部连到P1口上,这样P0口与ADC0804的D0-D8相连,P1口连到了“动态数码显示模块”区域的输入端a-h,拨动8联拨动拨码开关JP1使P2.0对应S1,P2.1对应S2,P2.2对应S3。 126 (2)把单排接插件J7的CS与GND利用黄色跳线帽相连,把单排接插件J8下面的两端用黄色跳线帽相连。 (3)用于测外部输入小于5V直流电压时,把单排接插件J8上面的两端相连。 五、程序设计内容 ADC0804采集到的模拟量(电压)转换成数字量并通过单片机用数码显示。 六、程序流程图(如图24.2所示) 图24.2 数字电压表设计流程图 七、汇编源程序 ORG 0000H LJMP START ORG 0003H RETI ORG 000BH RETI ORG 0013H RETI ORG 001BH RETI ORG 0023H RETI ORG 0100H START: MOV R1,#70H MOV R2,#8 ;;;;;;;;;;;;;;;70到77单元清零,初始化;;;;;;;;;;;;;;; NEX: MOV @R1,#00H 127 INC R1 DJNZ R2,NEX MOV P0,#0FFH MOV P1,#0FFH MOV P2,#0FFH MOV P3,#0FFH ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;显示; XIANSHI: MOV R3,#20H XIANSHI2: MOV A,70H MOV B,#100 MUL AB MOV A,B ;丢掉低四位相当于除以256 MOV B,#20 ;除以20是百位上的数 DIV AB MOV DPTR,#TAB1 MOVC A,@A+DPTR MOV P2,#11111011B MOV P1,A LCALL DELAY10MS MOV A,B B,#2 MOV DIV AB ;除以2是十位上的数 MOV DPTR,#TAB MOVC A,@A+DPTR MOV P2,#11111101B MOV P1,A LCALL DELAY10MS MOV A,B MOV B,#5 MUL AB ;乘2得个位数 MOVC A,@A+DPTR MOV P2,#11111110B MOV P1,A LCALL DELAY10MS DJNZ R3,XIANSHI2 ;;;;;;;;;;;输入的时钟信号;;;;;;;;;;;;;;;;;启动 CAIJI0: CLR P3.6 NOP NOP NOP NOP NOP SETB P3.6 NOP 128 NOP NOP NOP NOP ;;;;;;;;;;;;;;;;;;;;;采集信号;;;;;;;;;;;;;;;;;;;;;;; CAIJI: JB P3.2,CAIJI2 ;等待启动转换的控制来临 LJMP CAIJI CAIJI2: CLR P3.7 ;外部读取转换结果的控制输出信号,低电平有效 MOV A,P0 MOV 70H,A SETB P3.7 LJMP XIANSHI DELAY10MS: MOV R5,#10 D1: MOV R6,#248 DJNZ R6,$ DJNZ R5,D1 RET TAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH TAB1: DB 0BFH,86H,0DBH,0CFH,0E6H,0EDH,0FDH,87H,0FFH,0EFH END 八、C语言源程序 #include unsigned char code TABLE1[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; unsigned char code TABLE[]={0xbf,0x86,0xdb,0xcf,0xe6, 0xed,0xfd,0x87,0xdd,0xef}; unsigned char j,k; unsigned int n,m; void delay(unsigned char i) //延时子程序// { for(j=i;j>0;j--) for(k=10;k>0;k--); } void xianshi(unsigned char A1,unsigned char A2,unsigned char A3) { P1=TABLE[A1]; P2=0xfb; delay(100); P1=TABLE1[A2]; P2=0xfd; delay(100); P1=TABLE1[A3]; P2=0xfe; delay(100); 129 } void main(void) { unsigned char A1,A2,A3; while(1) //数据采集部分// { A1=0; A2=0; P3_6=1; delay(1); P3_6=0; delay(1); P3_6=1; while(P3_2==0); P3_7=0; delay(10); m=P0; P3_7=1; n=m*50; m=n/255; m=m*10; A1=m/100; A2=m%100/10; A3=m%100%10; xianshi(A1,A2,A3); delay(10); } } 九、注意事项 在硬件电路中,把单排接插件J7的CS与GND用黄色跳线帽相连,单排接插件J8下面 的两端用黄色跳线帽相连,2联拨动拨码开关JP5的SK拨上去。 130 实验二十五 DS18B20数字温度计设计 一、实验目的 1.了解DS18B20数字温度计的设计原理。 2(掌握DS18B20的用法。 (掌握采集数据的方法。 3 二、设计原理 如图25.1,用一片DS18B20构成测温系统,测量的温度精度达到0.1度,测量的温度的范围在,20度到,100度之间,用3位数码管完成相应的显示。 三、参考电路 图25.1 DS18B20数字温度计电路原理图 四、电路硬件说明 (1)在“单片机系统”区域中,把单片机的P0.0,P0.7端口通过跳线J3连接到“动态数码显示”区域中的ABCDEFGH端子上。 131 (2)在“单片机系统”区域中,把单片机的P2.0,P2.7通过8联拨动拨码开关JP1连接到“动态数码显示”区域中的S1、S2、S3、S4、S5、S6、S7、S8端子上。 (3)把DS18B20的DQ端子通过2联拨动拨码开关JP5连接到“单片机系统”区域中的P1.1端子上。 五、程序设计内容 由于DS18B20采用的是1,Wire总线 协议 离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载 方式,即在一根数据线实现数据的双向传输,而对AT89S51单片机来说,硬件上并不支持单总线协议,因此,必须采用软件的方法来模拟单总线的协议时序来完成对DS18B20芯片的访问。 由于DS18B20是在一根I/O线上读写数据,因此,对读写的数据位有着严格的时序要求。DS18B20有严格的通信协议来保证各位数据传输的正确性和完整性。该协议定义了几种信号的时序:初始化时序、读时序、写时序。所有时序都是将主机作为主设备,单总线器件作为从设备。而每一次命令和数据的传输都是从主机主动启动写时序开始,如果要求单总线器件回送数据,在进行写命令后,主机需启动读时序完成数据接收。数据和命令的传输都是低位在先。 (1)DS18B20的复位时序: (2)DS18B20的读时序: 对于DS18B20的读时序分为读0时序和读1时序两个过程。 对于DS18B20的读时隙是从主机把单总线拉低之后,在15秒之内就得释放单总线,以让DS18B20把数据传输到单总线上。DS18B20在完成一个读时序过程,至少需要60us才能完成。 (3)DS18B20的写时序 对于DS18B20的写时序仍然分为写0时序和写1时序两个过程。 对于DS18B20写0时序和写1时序的要求不同,当要写0时序时,单总线要被拉低至少60us,保证DS18B20能够在15us到45us之间能够正确地采样IO总线上的“0”电平,当要写1时序时,单总线被拉低之后,在15us之内就得释放单总线。 132 六、程序流程图(如图25.2所示) 图25.2 DS18B20数字温度计程序流程图 七、汇编源程序 ;;;;;;;;;;定义单元;;;;;;;;; TEMPER_L EQU 29H TEMPER_H EQU 28H FLAG1 EQU 38H ;是否检测到DS18B20标志位 A_BIT EQU 20H ;数码管个位数存放内存位置 B_BIT EQU 21H ;数码管十位数存放内存位置 XS EQU 30H ORG 0000H LJMP START ORG 0003H RETI ORG 000BH RETI ORG 0013H 133 RETI ORG 001BH RETI ORG 0023H RETI ORG 0100H ;;;;;;;;;;主程序;;;;;;;;;; START: LCALL CHUSHIHUA LCALL MAIN LJMP START ;;;;;;;;;;初始化程序;;;;;;;;;; CHUSHIHUA: MOV TEMPER_L,#00H MOV TEMPER_H,#00H MOV FLAG1,#00H MOV A_BIT,#00H MOV B_BIT,#00H MOV XS,#00H RET ;;;;;;;;;;温度测量,转换,显示程序;;;;;;;;;; MAIN: LCALL GET_TEMPER ;调用读温度子程序 MOV A,29H MOV B,A CLR C RLC A CLR C RLC A CLR C RLC A CLR C RLC A SWAP A MOV 31H,A MOV A,B MOV C,40H ;将28H中的最低位移入C RRC A MOV C,41H RRC A MOV C,42H RRC A MOV C,43H RRC A MOV 29H,A LCALL DISPLAY ;调用数码管显示子程序 AJMP MAIN 134 ;;;;;;;; 这是DS18B20复位初始化子程序;;;;;;;;; INIT_1820: SETB P1.1 NOP CLR P1.1 ;;;;;;;;;主机发出延时537微秒的复位低脉冲;;;;; MOV R1,#2 TSR1: MOV R0,#107 DJNZ R0,$ DJNZ R1,TSR1 SETB P1.1 ;然后拉高数据线 NOP NOP NOP MOV R0,#25H TSR2: JNB P1.1,TSR3 ;等待DS18B20回应 DJNZ R0,TSR2 LJMP TSR4 ; 延时 TSR3: SETB FLAG1 ; 置标志位,表示DS1820存在 LJMP TSR5 TSR4: CLR FLAG1 ; 清标志位,表示DS1820不存在 TSR7 LJMP TSR5: MOV R0,#117 TSR6: DJNZ R0,TSR6 ; 时序要求延时一段时间 TSR7: SETB P1.1 RET ;;;;;;;;;;;;; 读出转换后的温度值;;;;;;;;;;;;;;; GET_TEMPER: SETB P1.1 LCALL INIT_1820 ;先复位DS18B20 JB FLAG1,TSS2 ; 判断DS1820是否存在? RET TSS2: MOV A,#0CCH ; 跳过ROM匹配 LCALL WRITE_1820 MOV A,#44H ; 发出温度转换命令 LCALL WRITE_1820 ;这里通过调用显示子程序实现延时一段时间,等待AD转换结束,12位的话750微秒 LCALL DISPLAY LCALL INIT_1820 ;准备读温度前先复位 MOV A,#0CCH ; 跳过ROM匹配 LCALL WRITE_1820 MOV A,#0BEH ; 发出读温度命令 LCALL WRITE_1820 LCALL READ_18200 ; 将读出的温度数据保存到35H/36H RET ;;;;;;;;;;写DS18B20的子程序(有具体的时序要求);;;;;;;; 135 WRITE_1820: MOV R2,#8 ;一共8位数据 CLR C WR1: CLR P1.1 MOV R3,#6 DJNZ R3,$ RRC A MOV P1.1,C MOV R3,#23 DJNZ R3,$ SETB P1.1 NOP DJNZ R2,WR1 SETB P1.1 RET ;;;; 读DS18B20的程序,从DS18B20中读出两个字节的温度数据 ;;;; READ_18200: MOV R4,#2 ; 将温度高位和低位从DS18B20中读出 MOV R1,#29H ; 低位存入29H(TEMPER_L),高位存入 28H(TEMPER_H) RE00: MOV R2,#8 ;数据一共有8位 RE01: CLR C SETB P1.1 NOP NOP CLR P1.1 NOP NOP NOP SETB P1.1 MOV R3,#9 RE10: DJNZ R3,RE10 MOV C,P1.1 MOV R3,#23 RE20: DJNZ R3,RE20 RRC A DJNZ R2,RE01 MOV @R1,A DEC R1 DJNZ R4,RE00 RET GJDQ: LJMP XIANSHI KJDQ: LJMP XIANSHI DISPLAY: MOV A,29H ;将29H中的十六进制数转换成10进制 MOV B,A RLC A 136 RLC A RLC A JC KJDQ RLC A JC ZANKAN JNC GJDQ ZANKAN: RLC A JC ZANKAN1 JNC GJDQ ZANKAN1: RLC A JC ZANKAN2 JNC GJDQ ZANKAN2: RLC A JC KJDQ XIANSHI: MOV A,B MOV B,#10 ;10进制/10=10进制 DIV AB MOV B_BIT,A ;十位在A MOV A_BIT,B ;个位在B MOV R0,#4 CLR C ;多加的 DPL1: MOV R1,#250 ;显示1000次 DPLOP: MOV DPTR,#NUMTAB1 MOV A,A_BIT ;取个位数 MOVC A,@A+DPTR ;查个位数的7段代码 MOV P0,A ;送出个位的7段代码 CLR P2.1 ;开个位显示 ACALL D1MS ;显示1MS SETB P2.1 MOV DPTR,#NUMTAB MOV A,B_BIT ;取十位数 MOVC A,@A+DPTR ;查十位数的7段代码 MOV P0,A ;送出十位的7段代码 CLR P2.2 ;开十位显示 ACALL D1MS ;显示1MS SETB P2.2 JC XSW ;多加的 MOV A,31H MOV B,#160 DIV AB MOV XS,B XSW: MOV A,XS MOVC A,@A+DPTR MOV P0,A 137 CLR P2.0 ACALL D1MS SETB P2.0 SETB C ;多加的 DJNZ R1,DPLOP ;250次没完循环 DJNZ R0,DPL1 ;4个250次没完循环 RET ;;;;;;;;;;1MS延时(按12MHZ算);;;;;;;;;;;;; D1MS: MOV R7,#80 DJNZ R7,$ RET NUMTAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H DB 7FH,6FH,7FH,7FH,7FH,7FH,7FH,7FH NUMTAB1: DB 0BFH,86H,0DBH,0CFH,0E6H,0EDH,0FDH,87H,0FFH,0EFH END 八、注意事项 在单片机程序中,0CCH、0BEH是DS18B20的指令命令。在硬件电路中要把2联拨动拨码开关JP5的TP键拨上去。 138 附录A 实验板中模拟/数字转换器ADC0804的参数及使用说明 在数字系统的应用中,通常要将一些被测量的物理量通过传感器送到数字系统进行加工处理;经过处理获得的输出数据又要送回物理系统,对系统物理量进行调节和控制。传感器输出的模拟电信号首先要转换成数字信号,数字系统才能对模拟信号进行处理。这种模拟量到数字量的转换称为模-数(A/D)转换。处理后获得的数字量有时又需转换成模拟量,这种转 模(D/A)变换。A/D变换器简称为ADC和D/A变换器简称为DAC是数字系统和模拟换称为数- 系统的接口电路。 模拟/数字转换器ADC0804就是其中的一种A/D变换器。如下为ADC0804的参数及使用说明: 试验原理图: ADC0804的规格及引脚图 /CS:芯片选择信号。 /WR:用来启动转换的控制当/WR自HI变为LO 时,转换器被清除;当/WR回到HI时,转换VREF:辅助参考电压。 正式启动; /RD:外部读取转换结果的控制脚输出信号。DB0~DB7:8位数字输出。 低电平有效 /INTR:中断请求信号输出,高电平转换结AGND,DGND:模拟信号以及数字信号接地。 束 CLK IN,CLK R:时钟输入或接振荡元件(R,VIN(+),VIN(-):差动模拟电压输入。输C),频率约限制在100KHz~1460KHz 入单端正电压时,VIN(-)接地; VCC:电源供应以及作为电路的参考电压。 139 ADC0804电压输入与数字输出关系如表所示 与满刻度的比率 相对电应值VREF=2.560伏 高四位字节 低四位字节 高四位字节电压 低四位字节电压 十六进制 二进制码 F 1111 15/16 15/256 4.800 0.300 E 1110 14/16 14/256 4.480 0.280 D 1101 13/16 13/256 4.160 0.260 C 1100 12/16 12/256 3.840 0.240 B 1011 11/16 11/256 3.520 0.220 A 1010 10/16 10/256 3.200 0.200 9 1001 9/16 9/256 2.880 0.180 8 1000 8/16 8/256 2.560 0.160 7 0111 7/16 7/256 2.240 0.140 6 0110 6/16 6/256 1.920 0.120 5 0101 5/16 5/256 1.600 0.100 4 0100 4/16 4/256 1.280 0.080 3 0011 3/16 3/256 0.960 0.060 2 0010 2/16 2/256 0.640 0.040 1 0001 1/16 1/256 0.320 0.020 0 0000 0 0 140 附录B 实验板中DS18B20智能温度控制器的参数及使用 DALLAS最新单线数字温度传感器DS18B20简介新的“一线器件”体积更小、适用电压更宽、更经济 Dallas 半导体公司的数字化温度传感器DS1820是世界上第一片支持 “一线总线”接口的温度传感器。一线总线独特而且经济的特点,使用户可轻松地组建传感器网络,为测量系统的构建引入全新概念。DS18B20、 DS1822 “一线总线”数字化温度传感器 同 支持“一线总线”接口,测量温度范围为 -55?C~+125?C,在DS1820一样,DS18B20也 -10~+85?C范围内,精度为?0.5?C。DS1822的精度较差为? 2?C 。现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。适合于恶劣环境的现场温度测量,如:环境控制、设备或过程控制、测温类消费电子产品等。与前一代产品不同,新的产品支持3V~5.5V的电压范围,使系统设计更灵活、方便。而且新一代产品更便宜,体积更小。 DS18B20、 DS1822 的特性 DS18B20可以程序设定9~12位的分辨率,精度为?0.5?C。可选更小的封装方式,更宽的电压适用范围。分辨率设定,及用户设定的报警温度存储在EEPROM中,掉电后依然保存。DS18B20的性能是新一代产品中最好的~性能价格比也非常出色~ DS1822与 DS18B20软件兼容,是DS18B20的简化版本。省略了存储用户定义报警温度、分辨率参数的EEPROM,精度降低为?2?C,适用于对性能要求不高,成本控制严格的应用,是经济型产品。 继“一线总线”的早期产品后,DS1820开辟了温度传感器技术的新概念。DS18B20和DS1822使电压、特性及封装有更多的选择,让可以构建适合自己的经济的测温系统。 一、DS18B20的内部结构 DS18B20内部结构主要由四部分组成:64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。 (1)DS18B20的管脚排列如下: (2) 64 b闪速ROM的结构如下: 141 开始8位是产品类型的编号,接着是每个器件的惟一的序号,共有48位,最后8位是前56位的CRC校验码,这也是多个DS18B20可以采用一线进行通信的原因。 (3)温度传感器: (4) 非易市失性温度报警触发器TH和TL,可通过软件写入用户报警上下限。 (5) 高速暂存存储器 DS18B20温度传感器的内部存储器包括一个高速暂存RAM和一个非易失性的可电擦除的 EP2RAM。后者用于存储TH,TL值。数据先写入RAM,经校验后再传给EP2RAM。而配置寄存器为高速暂存器中的第5个字节,他的内容用于确定温度值的数字转换分辨率,DS18B20工作时按此寄存器中的分辨率将温度转换为相应精度的数值。该字节各位的定义如下: 低5位一直都是1,TM是测试模式位,用于设置DS18B20在工作模式还是在测试模式。在DS18B20出厂时该位被设置为0,用户不要去改动,R1和R0决定温度转换的精度位数,即是来设置分辨率,如表1所示(DS18B20出厂时被设置为12位)。 由表1可见,设定的分辨率越高,所需要的温度数据转换时间就越长。因此,在实际应用中要在分辨率和转换时间权衡考虑。 高速暂存存储器除了配置寄存器外,还有其他8个字节组成,其分配如下所示。其中温度信息(第1,2字节)、TH和TL值第3,4字节、第6,8字节未用,表现为全逻辑1;第9字节读出的是前面所有8个字节的CRC码,可用来保证通信正确。 142 当DS18B20接收到温度转换命令后,开始启动转换。转换完成后的温度值就以16位带符号扩展的二进制补码形式存储在高速暂存存储器的第1,2字节。单片机可通过单线接口读到该数据,读取时低位在前,高位在后,数据格式以0.062 5 ?/LSB形式表示。温度值格式如下: 对应的温度计算:当符号位S=0时,直接将二进制位转换为十进制;当S=1时,先将补码变换为原码,再计算十进制值。表2是对应的一部分温度值。 DS18B20完成温度转换后,就把测得的温度值与TH,TL作比较,若T>TH或T
本文档为【单片机最小系统板实验指导书】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_594886
暂无简介~
格式:doc
大小:1MB
软件:Word
页数:0
分类:生活休闲
上传时间:2017-12-13
浏览量:20