篇一:AT89S51单片机C语言程序范例
第四章实验及实践课题
1. 闪烁灯
1. 实验任务
如图4.1.1所示:在P1.0端口上接一个发光二极管L1,使L1在不停地一亮一灭,一亮一灭的时间间隔为0.2秒。
2. 电路原理图
图4.1.1
3. 系统板上硬件连线
把“单片机系统”区域中的P1.0端口用导线连接到“八路发光二极管指示模块”区域中的L1端口上。
4. 程序设计内容
(1). 延时程序的设计方法
作为单片机的指令的执行的时间是很短,数量大微秒级,因此,我们要求的闪烁时间间隔为0.2秒,相对于微秒来说,相差太大,所以我们在执行某一指令时,插入延时程序,来达到我们的要求,但这样的延时程序是如何设计呢?下面具体介绍其原理:
如图4.1.1所示的石英晶体为12MHz,因此,1个机器周期为1微秒
机器周期
2个 2个 2个 微秒
2 2+2×248=20× 2×248 (498 MOV R6,#20 MOV R7,#248 DJNZ R7,$ D1:
DJNZ R6,D12个2×20=10002
因此,上面的延时程序时间为10.002ms。
由以上可知,当R6=10、R7=248时,延时5ms,R6=20、R7=248时,延时10ms,以此为基本的计时单位。如本实验要求0.2秒=200ms,10ms×R5=200ms,则R5=20,延时子程序如下:
DELAY:
D1:
D2:
MOV R5,#20 MOV R6,#20 MOV R7,#248 DJNZ R7,$ DJNZ R6,D2 DJNZ R5,D1
RET
(2). 输出控制
如图1所示,当P1.0端口输出高电平,即P1.0=1时,根据发光二极管的单向导电性可知,这时发光二极管L1熄灭;当P1.0端口输出低电平,即P1.0=0时,发光二极管L1亮;我们可以使用SETB P1.0指令使P1.0端口输出高电平,使用CLR P1.0指令使P1.0端口输出低电平。
5.
程序框图 如图4.1.2所示
图4.1.2
6.
START:
DELAY: 汇编源程序 ORG 0 CLR P1.0 LCALL DELAY SETB P1.0 LCALL DELAY LJMP START MOV R5,#20;延时子程序,延时0.2秒
D1:MOV R6,#20
D2:MOV R7,#248
DJNZ R7,$
DJNZ R6,D2
DJNZ R5,D1
RET
END
7. C语言源程序
#include <AT89X51.H>
sbit L1=P1^0;
void delay02s(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)
{
while(1)
{
L1=0;
delay02s();
L1=1;
delay02s();
}
}
2.
1. 实验任务 模拟开关灯
如图4.2.1所示,监视开关K1(接在P3.0端口上),用发光二极管L1(接在单片机P1.0端口上)显示开关状态,如果开关合上,L1亮,开关打开,L1熄灭。
2. 电路原理图
图4.2.1
3. 系统板上硬件连线
区域中的L1端口上; (1). 把“单片机系统”区域中的P1.0端口用导线连接到“八路发光二极管指示模块”
(2). 把“单片机系统”区域中的P3.0端口用导线连接到“四路拨动开关”区域中的
K1端口上;
4. 程序设计内容
(1). 开关状态的检测过程
单片机对开关状态的检测相对于单片机来说,是从单片机的P3.0端口输入信号,而输入的信号只有高电平和低电平两种,当拨开开关K1拨上去,即输入高电平,相当开关断开,当拨动开关K1拨下去,即输入低
电平,相当开关闭合。单片机可以采用JB BIT,REL或者是JNB BIT,REL指令来完成对开关状态的检测即可。(2). 输出控制
如图3所示,当P1.0端口输出高电平,即P1.0=1时,根据发光二极管的单向导电性可知,这时发光二极管L1熄灭;当P1.0端口输出低电平,即P1.0=0时,
发光二极管L1亮;我们可以使用SETB P1.0指令使P1.0端口输出高电平,使用CLR P1.0指令使P1.0端口输出低电平。
5. 程序框图
图4.2.2
6. 汇编源程序
START:
LIG:
ORG 00H JB P3.0,LIG CLR P1.0 SJMP START SETB P1.0 SJMP START END
7. C语言源程序
#include <AT89X51.H>
sbit K1=P3^0;
sbit L1=P1^0;
void main(void)
{
while(1)
{
if(K1==0)
{
L1=0;
}
else
{
L1=1;
}
}
} //灯亮 //灯灭
篇二:AT89C51单片机液晶显示程序(c语言编写)
仿真图接线方式
C语言程序
#include<reg51.h>
#include<intrins.h>
sbit rs=P2^0;
sbit rw=P2^1;
sbit ep=P2^2;
unsigned char code dis1[]={""}; unsigned char code dis2[]={"0571-85956028"}; void delay(unsigned char ms)
{
unsigned char i;
while(ms--)
{for(i=0;i<250;i++)
{_nop_(); _nop_();_nop_();_nop_(); }
}
}
bit lcd_bz()
{bit result;
rs=0;
rw=1;
ep=1;
_nop_();
_nop_();
_nop_();
_nop_();
result=(bit)(P0&0x80);ep=0;
return result;
}
void lcd_wcmd(unsigned char cmd) { while(lcd_bz());
rs=0;
rw=0;
ep=0;
_nop_();
_nop_();
P0=cmd;
_nop_();
_nop_();
_nop_();
_nop_();
ep=1;
_nop_();
_nop_();
_nop_();
_nop_();
ep=0;
}
void lcd_pos(unsigned char pos) { lcd_wcmd(pos|0x80); }
void lcd_wdat(unsigned char dat) { while(lcd_bz());
rs=1;
rw=0;
ep=0;
P0=dat;
_nop_();
_nop_();
_nop_();
_nop_();
ep=1;
_nop_();
_nop_();
_nop_();
_nop_();
ep=0;
}
void lcd_init()
{ lcd_wcmd(0x38); delay(1);
lcd_wcmd(0x0c); delay(1);
lcd_wcmd(0x06); delay(1);
lcd_wcmd(0x01); delay(1);
}
void main(void)
{ unsigned char i; lcd_init();
delay(10);
lcd_pos(0x01); i=0;
while(dis1[i]!='\0') {lcd_wdat(dis1[i]);i++;
}
lcd_pos(0x42); i=0;
while(dis2[i]!='\0'){lcd_wdat(dis2[i]); i++;
}
while(1); }
篇三:51单片机汇编语言及C语言经典实例
51单片机汇编语言及C语言经典实例
实验及课程设计
51单片机汇编语言及C语言经典实例
一、闪烁灯
如图1 所示为一简单单片机系统原理图:在 P1.0 端口上接一个发光二极管 L1,使 L1 在不停地一亮一灭,一亮一灭的时间间隔为 0.2 秒。 延时程序的设计方法,作为单片机的指令的执行的时间是很短,数量大微秒级,因此,我们要求的闪烁时间间隔为 0.2 秒,相对于微秒来说,相差太大,所以我们在执行某一指令时,插入延时程序,来达到我们的要求,但这样的延时程
序是如何设计呢?下面具体介绍其原理:如图 4.1.1 所示的石英晶体为 12MHz,因此,1 个机器周期为 1 微秒,机器周期 微秒如图 1 所示,当 P1.0 端口输出高电平,即 P1.0=1 时,根据发光二极管的单向导电性可知,这时发光二极管 L1 熄灭;当 P1.0 端口输出低电平,即 P1.0=0 时,发光二极管 L1 亮;我们可以使用 SETB P1.0 指令使 P1.0端口输出高电平,使用 CLR P1.0 指令使 P1.0 端口输出低电平。
C 语言源程序
#include <AT89X51.H> sbit L1=P1^0;
void delay02s(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) {
while(1) { L1=0;
delay02s(); L1=1;
delay02s(); }
汇编源程序 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 DJNZ R5,D1
RET 图1 单片机原理图 END
图2 程序设计流程图
二、多路开关状态指示
如图 3 所示,AT89S51 单片机的 P1.0-P1.3 接四个发光二极管 L1-L4,
P1.4-P1.7 接了四个开关 K1-K4,编程将开关的状态反映到发光二极管上。
(开关闭合,对应的灯亮,开关断开,对应的灯灭)。
对于开关状态检测,相对单片机来说,是输入关系,我们可轮流检测每个开关状
态,根据每个开关的状态让相应的发光二极管指示,可以采用 JB P1.X,REL
或 JNB P1.X,REL 指令来完成;也可以一次性检测四路开关状态,然后让其指
示,可以采用 MOV A,P1 指令一次把 P1 端口的状态全部读入,然后取高 4 位的状态来指示。
方法1(汇编源程序) ORG 00H
START: MOV A,P1 ANL A,#0F0H RR A RR A RR A RR A
ORL A,#0F0H MOV P1,A SJMP START END
方法1(C语言程序) #INClude <AT89X51.H> unsigned char temp; 图4 程序流程图
void main(void) {
while(1) {
temp=P1>>4; temp=temp | 0xf0; P1=temp; } }
方法2(汇编源程序) ORG 00H
START: JB P1.4,NEXT1
CLR P1.0 SJMP NEX1 NEXT1: SETB P1.0 图3 单片机原理图 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
方法2(C 语言源程序) #INClude <AT89X51.H>
void main(void) {
while(1) {
if(P1_4==0) {
P1_0=0; } Else {
P1_0=1; }
if(P1_5==0) {
P1_1=0;
} else {
P1_1=1; }
DJNZ R5,$ DJNZ R4,D1
图6 程序流程图DJNZ R3,DELAY
R RET
T ABLE: DB 0FEH,0FDH,0FBH,0F7H
if(P1_6==0) {
P1_2=0; } else {
P1_2=1; }
if(P1_7==0) {
P1_3=0; } else
图5 单片机原理图三、广告灯的设计
利用取表的方法,使端口左移 2 次,右移 2 次,闪烁 P1 做单一灯的变化:2 次 (延时的时间 0.2 秒)。
利用 MOV DPTR,#DATA16 的指令来使数据指针寄存器指到表的开 头。
利用器的值再加上 MOVC A ,DPTR @A+的DPTR 的指令,根据累加值,就可以使程序计数器 PC 指到表格内所要取出的数据。因此,只要把控制码建成一个表,而利用 MOVC A,@A+DPTR 做取码的操作, 就可方便地处理一些复杂的控制动作,取表过程如下图所示: 汇编源程序 ORG 0
START: MOV DPTR,#TABLE LOOP: CLR A
MOVC A,@A+DPTR CJNE A,#01H,LOOP1 JMP START
LOOP1: MOV P1,A MOV R3,#20 LCALL DELAY INC DPTR JMP LOOP
DELAY: MOV R4,#20 D1: MOV R5,#248
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 END
C 语言源程序
#INClude <AT89X51.H> 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; }
}
}
C 语言源程序
#include <AT89X51.H> unsigned char code
table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; unsigned char Second; void delay1s(void) {
unsigned char i,j,k; for(k=100;k>0;k--) for(i=20;i>0;i--) for(j=248;j>0;j--); }
void main(void) {
Second=0;
P0=table[Second/10]; P2=table[Second%10]; while(1) {
delay1s(); Second++; if(Second==60) {
Second=0; }
P0=table[Second/10]; P2=table[Second%10]; } }
四、 00-59 秒计时器
如下图8所示,在 AT89S51 单片机的 P0 和 P2 端口分别接有两个共阴数码管,P0 口驱动显示秒的时间的十位,而 P2 口驱动显示秒的时间的个位。在设计过程中我们用一个存储单元作为秒计数单元,当一秒钟到来时,就让秒计数单元加 1,当秒计数达到 60 时,就自动返回到 0,重新秒计数。
对于秒计数单元中的数据要把它十位数和个位数分开,方法仍采用对 10 整除和对 10 求余。 汇编源程序
Second EQU 30H ORG 0000H
START: MOV Second, #00H NEXT: 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
LCALL DELY1S INC Second MOV A,Second CJNE A,#60,NEXT LJMP START
图7 程序流程图 DELY1S: MOV R5,#100
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
图8 单片机原理图