51单片机汇编语言及C语言经典实例.docx

上传人:b****0 文档编号:9038950 上传时间:2023-05-16 格式:DOCX 页数:101 大小:1.71MB
下载 相关 举报
51单片机汇编语言及C语言经典实例.docx_第1页
第1页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第2页
第2页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第3页
第3页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第4页
第4页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第5页
第5页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第6页
第6页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第7页
第7页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第8页
第8页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第9页
第9页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第10页
第10页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第11页
第11页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第12页
第12页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第13页
第13页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第14页
第14页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第15页
第15页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第16页
第16页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第17页
第17页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第18页
第18页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第19页
第19页 / 共101页
51单片机汇编语言及C语言经典实例.docx_第20页
第20页 / 共101页
亲,该文档总共101页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

51单片机汇编语言及C语言经典实例.docx

《51单片机汇编语言及C语言经典实例.docx》由会员分享,可在线阅读,更多相关《51单片机汇编语言及C语言经典实例.docx(101页珍藏版)》请在冰点文库上搜索。

51单片机汇编语言及C语言经典实例.docx

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亮;我们可以使用SETBP1.0指令使P1.0端口输出高电平,使用CLRP1.0指令使P1.0端口输出低电平。

C语言源程序

#include

sbitL1=P1^0;

voiddelay02s(void)//延时0.2秒子程序

{

图1单片机原理图

unsignedchari,j,k;

for(i=20;i>0;i--)

for(j=20;j>0;j--)

for(k=248;k>0;k--);

}

voidmain(void)

{

while

(1)

{

L1=0;

delay02s();

L1=1;

delay02s();

}

汇编源程序

ORG0

START:

CLRP1.0

LCALLDELAY

图2程序设计流程图

SETBP1.0

LCALLDELAY

LJMPSTART

DELAY:

MOVR5,#20;延时子程序,延时0.2秒

D1:

MOVR6,#20

D2:

MOVR7,#248

 

DJNZR7,$

DJNZR6,D2

DJNZR5,D1

RET

END

二、多路开关状态指示

如图3所示,AT89S51单片机的P1.0-P1.3接四个发光二极管L1-L4,

P1.4-P1.7接了四个开关K1-K4,编程将开关的状态反映到发光二极管上。

(开关闭合,对应的灯亮,开关断开,对应的灯灭)。

对于开关状态检测,相对单片机来说,是输入关系,我们可轮流检测每个开关状

态,根据每个开关的状态让相应的发光二极管指示,可以采用JBP1.X,REL

或JNBP1.X,REL指令来完成;也可以一次性检测四路开关状态,然后让其指

示,可以采用MOVA,P1指令一次把P1端口的状态全部读入,然后取高4位的状态来指示。

方法1(汇编源程序)

ORG00H

START:

MOVA,P1

ANLA,#0F0H

RRA

RRA

RRA

RRA

ORLA,#0F0H

MOVP1,A

SJMPSTART

END

方法1(C语言程序)

图4程序流程图

#INClude

unsignedchartemp;

voidmain(void)

{

while

(1)

{

temp=P1>>4;

temp=temp|0xf0;

P1=temp;

}

}

方法2(汇编源程序)

ORG00H

START:

JBP1.4,NEXT1

CLRP1.0

SJMPNEX1

 

图3单片机原理图

NEXT1:

SETBP1.0

NEX1:

JBP1.5,NEXT2

CLRP1.1

SJMPNEX2

NEXT2:

SETBP1.1

NEX2:

JBP1.6,NEXT3

CLRP1.2

SJMPNEX3

NEXT3:

SETBP1.2

NEX3:

JBP1.7,NEXT4

CLRP1.3

SJMPNEX4

NEXT4:

SETBP1.3

NEX4:

SJMPSTART

END

方法2(C语言源程序)

#INClude

voidmain(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;

}

if(P1_6==0)

{

P1_2=0;

}

else

{

P1_2=1;

}

if(P1_7==0)

{

P1_3=0;

}

else

图5单片机原理图

三、广告灯的设计

利用取表的方法,使端口P1做单一灯的变化:

左移2次,右移2次,闪烁2次

(延时的时间0.2秒)。

利用MOVDPTR,#DATA16的指令来使数据指针寄存器指到表的开

头。

利用MOVCA,@A+DPTR的指令,根据累加器的值再加上DPTR的

值,就可以使程序计数器PC指到表格内所要取出的数据。

因此,只要把控制码建成一个表,而利用MOVCA,@A+DPTR做取码的操作,

就可方便地处理一些复杂的控制动作,取表过程如下图所示:

汇编源程序

ORG0

START:

MOVDPTR,#TABLE

LOOP:

CLRA

MOVCA,@A+DPTR

CJNEA,#01H,LOOP1

JMPSTART

LOOP1:

MOVP1,A

MOVR3,#20

LCALLDELAY

INCDPTR

JMPLOOP

DELAY:

MOVR4,#20

D1:

MOVR5,#248

图6程序流程图

DJNZR5,$

DJNZR4,D1

DJNZR3,DELAY

RRET

TABLE:

DB0FEH,0FDH,0FBH,0F7H

DB0EFH,0DFH,0BFH,07FH

DB0FEH,0FDH,0FBH,0F7H

DB0EFH,0DFH,0BFH,07FH

DB07FH,0BFH,0DFH,0EFH

DB0F7H,0FBH,0FDH,0FEH

DB07FH,0BFH,0DFH,0EFH

DB0F7H,0FBH,0FDH,0FEH

DB00H,0FFH,00H,0FFH

DB01H

END

C语言源程序

#INClude

unsignedcharcodetable[]={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};

unsignedchari;

voiddelay(void)

{

unsignedcharm,n,s;

for(m=20;m>0;m--)

for(n=20;n>0;n--)

for(s=248;s>0;s--);

}

voidmain(void)

{

while

(1)

{

if(table[i]!

=0x01)

{

P1=table[i];

i++;

delay();

}

else

{

i=0;

}

}

}

 

四、00-59秒计时器

如下图8所示,在AT89S51单片机的P0和P2端口分别接有两个共阴数码管,P0口驱动显示秒的时间的十位,而P2口驱动显示秒的时间的个位。

在设计过程中我们用一个存储单元作为秒计数单元,当一秒钟到来时,就让秒计数单元加1,当秒计数达到60时,就自动返回到0,重新秒计数。

对于秒计数单元中的数据要把它十位数和个位数分开,方法仍采用对10整除和对10求余。

汇编源程序

SecondEQU30H

ORG0000H

START:

MOVSecond,#00H

NEXT:

MOVA,Second

MOVB,#10

DIVAB

MOVDPTR,#TABLE

MOVCA,@A+DPTR

MOVP0,A

MOVA,B

MOVCA,@A+DPTR

MOVP2,A

LCALLDELY1S

INCSecond

MOVA,Second

CJNEA,#60,NEXT

图7程序流程图

LJMPSTART

DELY1S:

MOVR5,#100

D2:

MOVR6,#20

D1:

MOVR7,#248

DJNZR7,$

DJNZR6,D1

DJNZR5,D2

RET

TABLE:

DB3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH

END

 

C语言源程序

#include

unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,

0x6d,0x7d,0x07,0x7f,0x6f};

unsignedcharSecond;

voiddelay1s(void)

{

unsignedchari,j,k;

for(k=100;k>0;k--)

for(i=20;i>0;i--)

for(j=248;j>0;j--);

}

voidmain(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];

}

}

图8单片机原理图

五、动态数码显示技术

如图9所示,P0端口接动态数码管的字形码笔段,P2端口接动态数码管的数位选择端,P1.7接

一个开关,当开关接高电平时,显示“12345”字样;当开关接低电平时,显示“HELLO”字样。

动态扫描方法:

动态接口采用各数码管循环轮流显示的方法,当循环显示频率较高时,利用人眼的暂留特性,看不出闪烁显示现象,这种显示需要一个接口完成字形码的输出(字形选择),另一接口完成各数码管的轮流点亮(数位选择)。

在进行数码显示的时候,要对显示单元开辟8个显示缓冲区,每个显示缓冲区装有显示的不同数据即可。

对于显示的字形码数据我们采用查表方法来完成。

汇编源程序

图9单片机原理图

ORG0000H

START:

JBP1.7,DIR1

MOVDPTR,#TABLE1

SJMPDIR

DIR1:

MOVDPTR,#TABLE2

DIR:

MOVR0,#00H

MOVR1,#01H

NEXT:

MOVA,R0

MOVCA,@A+DPTR

MOVP0,A

MOVA,R1

MOVP2,A

LCALLDAY

INCR0

RLA

MOVR1,A

CJNER1,#0DFH,NEXT

SJMPSTART

DAY:

MOVR6,#4

D1:

MOVR7,#248

DJNZR7,$

DJNZR6,D1

图10单片机原理图

RET

TABLE1:

DB06H,5BH,4FH,66H,6DH

TABLE2:

DB78H,79H,38H,38H,3FH

END

 

C语言源程序

#include

Unsignedcharcodetable1[]={0x06,0x5b,0x4f,0x66,0x6d};

Unsignedcharcodetable2[]={0x78,0x79,0x38,0x38,0x3f};

Unsignedchari;

Unsignedchara,b;

Unsignedchartemp;

voidmain(void)

{

while

(1)

{

temp=0xfe;

for(i=0;i<5;i++)

{

if(P1_7==1)

{

P0=table1[i];

}

else

{

P0=table2[i];

}

P2=temp;

a=temp<<(i+1);

b=temp>>(7-i);

temp=a|b;

for(a=4;a>0;a--)

for(b=248;b>0;b--);

}

}

 

六、4×4矩阵式键盘识别技术

如图11所示,用AT89S51的并行口P1接4×4矩阵键盘,以P1.0-P1.3作输入线,以P1.4-P1.7作输出线;在数码管上显示每个按键的“0-F”序。

对应的按键的序号排列如图12所示每个按键有它的行值和列值,行值和列值的组合就是识别这个按键的编码。

矩阵的行线和列线分别通过两并行接口和CPU通信。

每个按键的状态同样需变成数字量“0”和“1”,开关的一端(列线)通过电阻接VCC,而接地是通过程序输出数字“0”实现的。

键盘处理程序的任务是:

确定有无键按下,判断哪一个键按下,键的功能是什么;

还要消除按键在闭合或断开时的抖动。

两个并行口中,一个输出扫描码,使按键逐行动态接地,另一个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的

功能。

 

汇编源程序

KEYBUFEQU30H

ORG00H

START:

MOVKEYBUF,#2

WAIT:

MOVP3,#0FFH

CLRP3.4

MOVA,P3

ANLA,#0FH

XRLA,#0FH

JZNOKEY1

LCALLDELY10MS

MOVA,P3

ANLA,#0FH

XRLA,#0FH

JZNOKEY1

MOVA,P3

ANLA,#0FH

CJNEA,#0EH,NK1

MOVKEYBUF,#0

LJMPDK1

NK1:

CJNEA,#0DH,NK2

MOVKEYBUF,#1

LJMPDK1

NK2:

CJNEA,#0BH,NK3

MOVKEYBUF,#2

LJMPDK1

NK3:

CJNEA,#07H,NK4

MOVKEYBUF,#3

LJMPDK1

NK4:

NOP

DK1:

MOVA,KEYBUF

MOVDPTR,#TABLE

MOVCA,@A+DPTR

MOVP0,A

DK1A:

MOVA,P3

ANLA,#0FH

XRLA,#0FH

JNZDK1A

NOKEY1:

MOVP3,#0FFH

CLRP3.5

MOVA,P3

ANLA,#0FH

XRLA,#0FH

JZNOKEY2

LCALLDELY10MS

MOVA,P3

ANLA,#0FH

XRLA,#0FH

JZNOKEY2

MOVA,P3

ANLA,#0FH

CJNEA,#0EH,NK5

MOVKEYBUF,#4

LJMPDK2

NK5:

CJNEA,#0DH,NK6

MOVKEYBUF,#5

LJMPDK2

NK6:

CJNEA,#0BH,NK7

MOVKEYBUF,#6

LJMPDK2

NK7:

CJNEA,#07H,NK8

MOVKEYBUF,#7

LJMPDK2

NK8:

NOP

DK2:

MOVA,KEYBUF

MOVDPTR,#TABLE

MOVCA,@A+DPTR

MOVP0,A

DK2A:

MOVA,P3

ANLA,#0FH

XRLA,#0FH

JNZDK2A

NOKEY2:

MOVP3,#0FFH

CLRP3.6

MOVA,P3

ANLA,#0FH

XRLA,#0FH

JZNOKEY3

LCALLDELY10MS

MOVA,P3

ANLA,#0FH

XRLA,#0FH

JZNOKEY3

MOVA,P3

ANLA,#0FH

CJNEA,#0EH,NK9

MOVKEYBUF,#8

LJMPDK3

NK9:

CJNEA,#0DH,NK10

MOVKEYBUF,#9

LJMPDK3

NK10:

CJNEA,#0BH,NK11

MOVKEYBUF,#10

 

LJMPDK3

NK11:

CJNEA,#07H,NK12

MOVKEYBUF,#11

LJMPDK3

NK12:

NOP

DK3:

MOVA,KEYBUF

MOVDPTR,#TABLE

MOVCA,@A+DPTR

MOVP0,A

DK3A:

MOVA,P3

ANLA,#0FH

XRLA,#0FH

JNZDK3A

NOKEY3:

MOVP3,#0FFH

CLRP3.7

MOVA,P3

ANLA,#0FH

XRLA,#0FH

JZNOKEY4

LCALLDELY10MS

MOVA,P3

ANLA,#0FH

XRLA,#0FH

JZNOKEY4

MOVA,P3

ANLA,#0FH

CJNEA,#0EH,NK13

MOVKEYBUF,#12

LJMPDK4

NK13:

CJNEA,#0DH,NK14

MOVKEYBUF,#13

LJMPDK4

NK14:

CJNEA,#0BH,NK15

MOVKEYBUF,#14

LJMPDK4

NK15:

CJNEA,#07H,NK16

MOVKEYBUF,#15

LJMPDK4

NK16:

NOP

DK4:

MOVA,KEYBUF

MOVDPTR,#TABLE

MOVCA,@A+DPTR

MOVP0,A

DK4A:

MOVA,P3

ANLA,#0FH

XRLA,#0FH

JNZDK4A

NOKEY4:

LJMPWAIT

DELY10MS:

MOVR6,#10

D1:

MOVR7,#248

DJNZR7,$

DJNZR6,D1

RET

TABLE:

DB3FH,06H,5BH,4FH,66H,6DH,7DH,07H

DB7FH,6FH,77H,7CH,39H,5EH,79H,71H

END

C语言源程序

#INClude

unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,

0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71};

unsignedchartemp;

unsignedcharkey;

unsignedchari,j;

voidmain(void)

{

while

(1)

{

P3=0xff;

P3_4=0;

temp=P3;

temp=temp&0x0f;

if(temp!

=0x0f)

{

for(i=50;i>0;i--)

for(j=200;j>0;j--);

temp=P3;

temp=temp&0x0f;

if(temp!

=0x0f)

{

temp=P3;

temp=temp&0x0f;

switch(temp)

{

case0x0e:

key=7;

break;

case0x0d:

key=8;

break;

case0x0b:

key=9;

break;

case0x07:

key=10;

break;

}

temp=P3;

P1_0=~P1_0;

P0=table[key];

temp=temp&0x0f;

while(temp!

=0x0f)

{

temp=P3;

temp=temp&0x0f;

}

}

}

P3=0xff;

P3_5=0;

temp=P3;

temp=temp&0x0f;

if(temp!

=0x0f)

{

for(i=50;i>0;i--)

for(j=200;j>0;j--);

temp=P3;

temp=temp&0x0f;

if(temp!

=0x0f)

{

temp=P3;

temp=temp&0x0f;

switch(temp)

{

case0x0e:

key=4;

break;

case0x0d:

key=5;

break;

case0x0b:

key=6;

break;

case0x07:

key=11;

break;

}

temp=P3;

P1_0=~P1_0;

P0=table[key];

temp=temp&0x0f;

while(temp!

=0x0f)

{

temp=P3;

temp=temp&0x0f;

}

}

}

P3=0xff;

P3_6=0;

temp=P3;

temp=temp&0x0f;

if(temp!

=0x0f)

{

for(i=50;i>0;i--)

for(j=200;j>0;j--);

temp=P3;

temp=temp&0x0f;

if(temp!

=0x0f)

{

temp=P3;

temp=temp&0x0f;

switch(temp)

{

case0x0e:

key=1;

break;

case0x0d:

key=2;

break;

case0x0b:

key=3;

break;

case0x07:

key=12;

break;

}

temp=P3;

P1_0=~P1_0;

P0=table[key];

temp=temp&0x0f;

while(temp!

=0x0f)

{

temp=P3;

temp=temp&0x0f;

}

}

}

P3=0xff;

P3_7=0;

temp=P3;

temp=temp&0x0f;

if(temp!

=0x0f)

{

for(i=50;i>0;i--)

for(j=200;j>0;j--);

temp=P3;

temp=temp&0x0f;

if(temp!

=0x0f)

{

temp=P3;

temp=temp&0x0f;

switch(temp)

{

case0x0e:

key=0;

break;

case0x0d:

key=13;

break;

case0x0b:

key=14;

break;

case0x07:

key=15;

break;

}

temp=P3;

P1_0=~P1_0;

P0=table[key];

temp=temp&0x0f;

while(

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

当前位置:首页 > IT计算机 > 电脑基础知识

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2