《单片机应用系统设计第二章.ppt》由会员分享,可在线阅读,更多相关《单片机应用系统设计第二章.ppt(54页珍藏版)》请在三一办公上搜索。
1、第二章 单片机的C语言应用举例,2.1 闪烁灯 2.2 I/O并行口直接驱动LED显示2.3 多路开关状态指示 2.4 定时计数器T0作定时应用技术2.5 报警声,单片机编程语言概述,汇编语言 51单片机的基本指令共有111条,其中单字节指令49条、双字节指令45条、三字节指令17条。单机器周期指令64条,双机器周期指令45条,只有乘、除两条指令的执行时间为4个机器周期。,高级语言,常用的51系列单片机高级语言C语言C51与ANSI C完全一样,程序结构上也是一样的。与ANSI C不同的是针对单片机开发的特殊性,在单片机C语言中增加了对单片机寄存器等的定义和说明,因此在使用单片机C语言时,应该
2、要特别注意一些特殊寄存器的定义。,设计要求:如下图所示,P1.0端口上接一个发光二极管L1,使L1在不停的一亮一灭,一亮一灭的时间间隔为0.2s。,2.1 闪烁灯,电路原理图,把“单片机系统”区域中的P1.0端口用导线连接到“发光二极管指示模块”区域中的L1端口上。,系统板上硬件连线,程序设计内容,(1)延时程序的设计方法 作为单片机的指令的执行的时间是很短,数量大微秒级,因此,要求的闪烁时间间隔为0.2秒,相对于微秒来说,相差太大,所以我们在执行某一指令时,插入延时程序,来达到我们的要求,但这样的延时程序是如何设计呢?下面具体介绍其原理:,如电路原理图所示的石英晶体为12MHz,因此,1个机
3、器周期为1微秒 机器周期 微秒 MOV R6,#202个2 D1:MOV R7,#2482个2 2224849820 DJNZ R7,$2个 2248(498DJNZ R6,D12个22040 10002 因此,上面的延时程序时间为10.002ms。由以上可知,当R610、R7248时,延时5ms,R620、R7248时,延时10ms,以此为基本的计时单位。如本设计要求0.2秒200ms,10msR5200ms,则R520,延时子程序如下:DELAY:MOV R5,#20 D1:MOV R6,#20 D2:MOV R7,#248 DJNZ R7,$DJNZ R6,D2 DJNZ R5,D1 R
4、ET,如图所示,当P1.0端口输出高电平,即P1.01时,根据发光二极管的单向导电性可知,这时发光二极管L1熄灭;当P1.0端口输出低电平,即P1.00时,发光二极管L1亮;我们可以使用SETBP1.0指令使P1.0端口输出高电平,使用CLRP1.0指令使P1.0端口输出低电平。,(2)输出控制,程序框图,ORG 0 START:CLR P1.0 LCALL DELAY SETB P1.0 LCALL DELAY LJMP START DELAY:MOV R5,#20;延时子程序,延时0.2秒 D1:MOV R6,#20 D2:MOV R7,#248 DJNZ R7,$DJNZ R6,D2 D
5、JNZ R5,D1 RET END,汇编源程序,#include sbit L1=P10;void delay02s(void)/延时0.2秒子程序 unsigned char i,j,k;for(i=20;i0;i-)for(j=20;j0;j-)for(k=248;k0;k-);void main(void)while(1)L1=0;delay02s();L1=1;delay02s();,C语言源程序,2.2 I/O并行口直接驱动LED显示,设计要求:利用AT89S51单片机的P0端口的连接到一个共阴数码管的a-h的笔段上,数码管的公共端接地。在数码管上循环显示0-9数字,时间间隔0.2s
6、。,电路原理图,把“单片机系统”区域中的P0.0/AD0P0.7/AD7端口用8芯排线连接到“四路静态数码显示模块”区域中的任一个数码管的ah端口上;要求:P0.0/AD0与a相连,P0.1/AD1与b相连,P0.2/AD2与c相连,P0.7/AD7与h相连。,系统板上硬件连线,(1)LED数码显示原理 七段LED显示器内部由七个条形发光二极管和一个小圆点发光二极管组成,根据各管的极管的接线形式,可分成共阴极型和共阳极型。LED数码管的ga七个发光二极管因加正电压而发亮,因加零电压而不以发亮,不同亮暗的组合就能形成不同的字形,这种组合称之为字形码。,程序设计内容,“0”3FH“8”7FH“1”
7、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,共阴极的字形码,(2)由于显示的数字09的字形码没有规律可循,只能采用查表的方式来完成所需的要求了。按照数字09的顺序,把每个数字的笔段代码按顺序排好!建立的表格如下所示:TABLEDB3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,程序框图,ORG 0 START:MOV R1,#00H NEXT:MOV A,R1 MOV DPTR,#TABLE MOVC A,A+DPTR MOV P0,A LCA
8、LL DELAY INC R1 CJNE R1,#10,NEXT LJMP START DELAY:MOV R5,#20 D2:MOV R6,#20 D1:MOV R7,#248 DJNZ R7,$DJNZ R6,D1 DJNZ R5,D2 RET TABLE:DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH END,汇编源程序,#include unsigned char code table=0 x3f,0 x06,0 x5b,0 x4f,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f;unsigned char dispcoun
9、t;void delay02s(void)unsigned char i,j,k;for(i=20;i0;i-)for(j=20;j0;j-)for(k=248;k0;k-);void main(void)while(1)for(dispcount=0;dispcount10;dispcount+)P0=tabledispcount;delay02s();,C语言源程序,2.3 多路开关状态指示,设计要求 AT89S51单片机的P1.0P1.3接四个发光二极管L1L4,P1.4P1.7接了四个开关K1K4,编程将开关的状态反映到发光二极管上。(开关闭合,对应的灯亮,开关断开,对应的灯灭)。,电
10、路原理图,系统板上硬件连线,1 把“单片机系统”区域中的P1.0P1.3用导线连接到“八路发光二极管指示模块”区域中的L1L4端口上;2 把“单片机系统”区域中的P1.4P1.7用导线连接到“四路拨动开关”区域中的K1K4端口上;,程序设计内容,1 开关状态检测 对于开关状态检测,相对单片机来说,是输入关系,我们可轮流检测每个开关状态,根据每个开关的状态让相应的发光二极管指示,可以采用JBP1.X,REL或JNBP1.X,REL指令来完成;也可以一次性检测四路开关状态,然后让其指示,可以采用MOVA,P1指令一次把P1端口的状态全部读入,然后取高4位的状态来指示。2 输出控制 根据开关的状态,
11、由发光二极管L1L4来指示,我们可以用SETBP1.X和CLRP1.X指令来完成,也可以采用MOVP1,1111XXXXB方法一次指示。,程序框图,方法一(汇编源程序),ORG 00H START:MOV A,P1 ANL A,#0F0H RR A RR A RR A RR A XOR A,#0F0H MOV P1,A SJMP START END,方法一(C语言源程序),#include unsigned char temp;void main(void)while(1)temp=P14;temp=temp|0 xf0;P1=temp;,方法二(汇编源程序),ORG 00H START:JB
12、 P1.4,NEXT1 CLR P1.0 SJMP NEX1 NEXT1:SETB P1.0 NEX1:JB P1.5,NEXT2 CLR P1.1 SJMP NEX2 NEXT2:SETB P1.1 NEX2:JB P1.6,NEXT3 CLR P1.2 SJMP NEX3 NEXT3:SETB P1.2 NEX3:JB P1.7,NEXT4 CLR P1.3 SJMP NEX4 NEXT4:SETB P1.3 NEX4:SJMP START END,方法二(C语言源程序),#include void main(void)while(1)if(P1_4=0)P1_0=0;else P1_0=
13、1;if(P1_5=0)P1_1=0;else P1_1=1;,if(P1_6=0)P1_2=0;else P1_2=1;if(P1_7=0)P1_3=0;else P1_3=1;,2.4 定时计数器T0作定时应用技术,设计要求 用AT89S51单片机的定时/计数器T0产生一秒的定时时间,作为秒计数时间,当一秒产生时,秒计数加1,秒计数到60时,自动从0开始。硬件电路如下图所示。,电路原理图,系统板上硬件连线,1 把“单片机系统”区域中的P0.0/AD0P0.7/AD7端口用8芯排线连接到“四路静态数码显示模块”区域中的任一个ah端口上;要求:P0.0/AD0对应着a,P0.1/AD1对应着b
14、,P0.7/AD7对应着h。2 把“单片机系统”区域中的P2.0/A8P2.7/A15端口用8芯排线连接到“四路静态数码显示模块”区域中的任一个ah端口上;要求:P2.0/A8对应着a,P2.1/A9对应着b,P2.7/A15对应着h。,程序设计内容,AT89S51单片机的内部16位定时/计数器是一个可编程定时/计数器,它既可以工作在13位定时方式,也可以工作在16位定时方式和8位定时方式。只要通过设置特殊功能寄存器TMOD,即可完成。定时/计数器何时工作也是通过软件来设定TCON特殊功能寄存器来完成的。现在我们选择16位定时工作方式,对于T0来说,最大定时也只有65536us,即65.536
15、ms,无法达到我们所需要的1秒的定时,因此,我们必须通过软件来处理这个问题,假设我们取T0的最大定时为50ms,即要定时1秒需要经过20次的50ms的定时。对于这20次我们就可以采用软件的方法来统计了。因此,我们设定TMOD00000001B,即TMOD01H 下面我们要给T0定时/计数器的TH0,TL0装入预置初值,通过下面的公式可以计算出 TH0(21650000)/256 TL0(21650000)MOD256 当T0在工作的时候,我们如何得知50ms的定时时间已到,这回我们通过检测TCON特殊功能寄存器中的TF0标志位,如果TF01表示定时时间已到。,程序框图,汇编源程序(查询法),S
16、ECONDEQU 30H TCOUNTEQU 31H ORG 00H START:MOV SECOND,#00H MOV TCOUNT,#00H MOV TMOD,#01H MOV TH0,#(65536-50000)/256 MOV TL0,#(65536-50000)MOD 256 SETB TR0 DISP:MOV A,SECOND 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,WAIT:JNB TF0,WAIT CLR TF0 MOV TH0,#(65536-
17、50000)/256 MOV TL0,#(65536-50000)MOD 256 INC TCOUNT MOV A,TCOUNT CJNE A,#20,NEXT MOV TCOUNT,#00H INC SECOND MOV A,SECOND CJNE A,#60,NEX MOV SECOND,#00H NEX:LJMP DISP NEXT:LJMP WAIT TABLE:DB FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH END,C语言源程序(查询法),#include unsigned char code dispcode=0 x3f,0 x06,0 x5b,
18、0 x4f,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f,0 x77,0 x7c,0 x39,0 x5e,0 x79,0 x71,0 x00;unsigned char second;unsigned char tcount;void main(void)TMOD=0 x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;TR0=1;tcount=0;second=0;P0=dispcodesecond/10;P2=dispcodesecond%10;,while(1)if(TF0=1)tcount+;if(tcount=20
19、)tcount=0;second+;if(second=60)second=0;P0=dispcodesecond/10;P2=dispcodesecond%10;TF0=0;TH0=(65536-50000)/256;TL0=(65536-50000)%256;,SECONDEQU 30H TCOUNTEQU 31H ORG 00H LJMP START ORG 0BH LJMP INT0X START:MOV SECOND,#00H MOV A,SECOND MOV B,#10 DIV AB MOV DPTR,#TABLE MOVC A,A+DPTR MOV P0,A MOV A,B MO
20、VC A,A+DPTR MOV P2,A MOV TCOUNT,#00H MOV TMOD,#01H MOV TH0,#(65536-50000)/256 MOV TL0,#(65536-50000)MOD 256 SETB TR0 SETB ET0 SETB EA SJMP$,汇编源程序(中断法),INT0X:MOV TH0,#(65536-50000)/256 MOV TL0,#(65536-50000)MOD 256 INC TCOUNT MOV A,TCOUNT CJNE A,#20,NEXT MOV TCOUNT,#00H INC SECOND MOV A,SECOND CJNE A
21、,#60,NEX MOV SECOND,#00H NEX:MOV A,SECOND 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 NEXT:RETI TABLE:DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH END,#include unsigned char code dispcode=0 x3f,0 x06,0 x5b,0 x4f,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f,0 x77,0 x7c
22、,0 x39,0 x5e,0 x79,0 x71,0 x00;unsigned char second;unsigned char tcount;void main(void)TMOD=0 x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;TR0=1;ET0=1;EA=1;tcount=0;second=0;P0=dispcodesecond/10;P2=dispcodesecond%10;while(1);,C语言源程序(中断法),void t0(void)interrupt 1 using 0 tcount+;if(tcount=20)tcou
23、nt=0;second+;if(second=60)second=0;P0=dispcodesecond/10;P2=dispcodesecond%10;TH0=(65536-50000)/256;TL0=(65536-50000)%256;,2.5“嘀、嘀、”报警声,设计要求 用AT89S51单片机产生“嘀、嘀、”报警声从P1.0端口输出,产生频率为1KHz,根据下图可知:1KHZ方波从P1.0输出0.2秒,接着0.2秒从P1.0输出电平信号,如此循环下去,就形成我们所需的报警声了。,电路原理图,系统板硬件连线,1 把“单片机系统”区域中的P1.0端口用导线连接到“音频放大模块”区域中的SP
24、K IN端口上;2 在“音频放大模块”区域中的SPK OUT端口上接上一个8欧或者是16欧的喇叭。,程序设计方法,1生活中我们常常到各种各样的报警声,例如“嘀、嘀、”就是常见的一种声音报警声,但对于这种报警声,嘀0.2秒钟,然后断0.2秒钟,如此循环下去,假设嘀声的频率为1KHz,则报警声时序图如下图所示:,上述波形信号如何用单片机来产生呢?2 由于要产生上面的信号,我们把上面的信号分成两部分,一部分为1KHZ方波,占用时间为0.2秒;另一部分为电平,也是占用0.2秒;因此,我们利用单片机的定时/计数器T0作为定时,可以定时0.2秒;同时,也要用单片机产生1KHZ的方波,对于1KHZ的方波信号
25、周期为1ms,高电平占用0.5ms,低电平占用0.5ms,因此也采用定时器T0来完成0.5ms的定时;最后,可以选定定时/计数器T0的定时时间为0.5ms,而要定时0.2秒则是0.5ms的400倍,也就是说以0.5ms定时400次就达到0.2秒的定时时间了。,主程序框图,中断服务程序框图,汇编源程序,T02SA EQU 30H T02SB EQU 31H FLAG BIT 00H ORG 00H LJMP START ORG 0BH LJMP INT_T0 START:MOV T02SA,#00H MOV T02SB,#00H CLR FLAG MOV TMOD,#01H MOV TH0,#(
26、65536-500)/256 MOV TL0,#(65536-500)MOD 256 SETB TR0 SETB ET0 SETB EA SJMP$,INT_T0:MOV TH0,#(65536-500)/256 MOV TL0,#(65536-500)MOD 256 INC T02SA MOV A,T02SA CJNE A,#100,NEXT INC T02SB MOV A,T02SB CJNE A,#04H,NEXT MOV T02SA,#00H MOV T02SB,#00H CPL FLAG NEXT:JB FLAG,DONE CPL P1.0 DONE:RETI END,C语言源程序,#include unsigned int t02s;unsigned char t05ms;bit flag;void main(void)TMOD=0 x01;TH0=(65536-500)/256;TL0=(65536-500)%256;TR0=1;ET0=1;EA=1;while(1);,void t0(void)interrupt 1 using 0 TH0=(65536-500)/256;TL0=(65536-500)%256;t02s+;if(t02s=400)t02s=0;flag=flag;if(flag=0)P1_0=P1_0;,