Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1728751606)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 700, well_thread_format(array(25))
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1422, well_thread_read(1849072)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 22, well_thread_read_cache(1849072)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1728751606)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 700, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1422, well_thread_read(1849072)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 22, well_thread_read_cache(1849072)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
51单片机汇编语言及C语言经典实例解析-USB迷|专注于互联网分享
最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

51单片机汇编语言及C语言经典实例解析

IT圈 admin 73浏览 0评论

2024年10月13日发(作者:俟彗)

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

实验及课程设计

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

一、闪烁灯

如图1 所示为一简单单片机系统原理图:在 P1.0

端口上接一个发光二极管 L1,使 L1 在不停地

一亮一灭,一亮一灭的时间间隔为 0.2 秒。

延时程序的设计方法,作为单片机的指令的执行

DELAY: MOV R5,#20 ;延时子程序,延时 0.2 秒

D1: MOV R6,#20

D2: MOV R7,#248

DJNZ R7,$

DJNZ R6,D2

的时间是很短,数量大微秒级,因此,我们要

求的闪烁时间间隔为

说,相差太大,所以我们在执行某一指令时,

0.2 秒,相对于微秒来

插入延时程序,来达到我们的要求,但这样的

延时程

序是如何设计呢?下面具体介绍其原理:如图

4.1.1

机器周期为

所示的石英晶体为

1 微秒,机器周期

12MHz

微秒如图

,因此,

1

1

示,当 P1.0 端口输出高电平,即 P1.0=1 时,

根据发光二极管的单向导电性可知,这时发光

二极管

使用

P1.0

L1 熄灭;当 P1.0 端口输出低电平,

SETB P1.0

=0 时,发光二极管

指令使 P1.0

L1

端口输出高电

亮;我们可以

平,使用

电平。

CLR P1.0 指令使 P1.0 端口输出低

C 语言源程序

#include

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

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

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

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;

}

if(P1_6==0)

JMP LOOP

DELAY: MOV R4,#20

D1: MOV R5,#248

DJNZ R5,$

图6 程序流程图

DJNZ R4,D1

DJNZ R3,DELAY

R RET

T ABLE: DB 0FEH,0FDH,0FBH,0F7H

{

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,@A+DPTR 的指令,根据累加

器的值再加上

值,就可以使程序计数器

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

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

unsigned char code

table[]={0xfe,0xfd,0xfb,0xf7,

0xef,0xdf,0xbf,0x7f,0xfe,0xfd,0x

fb,0xf7,0xef,0xdf,0xbf,0x7f,

0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0

xfd,0xfe,0x7f,0xbf,0xdf,0xef,

0xf7,0xfb,0xfd,0xfe,0x00,0xff,0

x00,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

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

五、动态数码显示技术

如图 9 所示,P0 端口接动态数码管的字形码笔

段,P2 端口接动态数码管的数位选择端,P1.7 接

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

当开关接低电平时,显示“HELLO”字样。

动态扫描方法:动态接口采用各数码管循环轮流

显示的方法,当循环显示频率较高时,利用人眼

的暂留特性,看不出闪烁显示现象,这种显示需

要一个接口完成字形码的输出(字形选择),另

一接口完成各数码管的轮流点亮(数位选择)。

在进行数码显示的时候,要对显示单元开辟 8

个显示缓冲区,每个显示缓冲区装有显示的不同

数据即可。对于显示的字形码数据我们采用查表

方法来完成。

汇编源程序

ORG 0000H

C 语言源程序

START: JB P1.7,DIR1

图9 单片机原理图

#include

MOV DPTR,#TABLE1

Unsigned char code

SJMP DIR

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

DIR1: MOV DPTR,#TABLE2

Unsigned char code

DIR: MOV R0,#00H

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

Unsigned char i;

MOV R1,#01H

Unsigned char a,b;

NEXT: MOV A,R0

Unsigned char temp;

MOVC A,@A+DPTR

MOV P0,A

void main(void)

MOV A,R1

{

MOV P2,A

while(1)

LCALL DAY

{

INC R0

temp=0xfe;

RL A

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

MOV R1,A

{

CJNE R1,#0DFH,NEXT

if(P1_7==1)

SJMP START

{

DAY: MOV R6,#4

P0=table1[i];

D1: MOV R7,#248

}

DJNZ R7,$

else

DJNZ R6,D1

{

RET

P0=table2[i];

图10 单片机原理图

TABLE1: DB 06H,5BH,4FH,66H,6DH

}

TABLE2: DB 78H,79H,38H,38H,3FH

P2=temp;

END

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”实现的。键盘处理程序的任务是:确定有无键按下,判断哪一个键按

下,键的功能是什么;

还要消除按键在闭合或断开时的抖动。两个并行口中,一个输出扫描码,使按键逐行动态接地,另一

个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该

键的

功能。

汇编源程序

KEYBUF EQU 30H

ORG 00H

START: MOV KEYBUF,#2

WAIT:

MOV P3,#0FFH

CLR P3.4

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY1

DELY10MS

LCALL

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY1

MOV A,P3

ANL A,#0FH

CJNE A,#0EH,NK1

MOV KEYBUF,#0

LJMP DK1

NK1: CJNE A,#0DH,NK2

MOV KEYBUF,#1

LJMP DK1

NK2: CJNE A,#0BH,NK3

MOV KEYBUF,#2

LJMP DK1

NK3: CJNE A,#07H,NK4

MOV KEYBUF,#3

LJMP DK1

NK4: NOP

DK1:

MOV A,KEYBUF

MOV DPTR,#TABLE

MOVC A,@A+DPTR

MOV P0,A

DK1A: MOV A,P3

ANL A,#0FH

XRL A,#0FH

JNZ DK1A

NOKEY1:

MOV P3,#0FFH

CLR P3.5

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY2

LCALL DELY10MS

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY2

MOV A,P3

ANL A,#0FH

A,#0EH,NK5

CJNE

MOV KEYBUF,#4

LJMP DK2

NK5: CJNE A,#0DH,NK6

MOV KEYBUF,#5

LJMP DK2

NK6: CJNE A,#0BH,NK7

MOV KEYBUF,#6

LJMP DK2

NK7: CJNE A,#07H,NK8

MOV KEYBUF,#7

LJMP DK2

NK8: NOP

DK2:

MOV A,KEYBUF

MOV DPTR,#TABLE

MOVC A,@A+DPTR

MOV P0,A

DK2A: MOV A,P3

ANL A,#0FH

XRL A,#0FH

JNZ DK2A

NOKEY2:

MOV P3,#0FFH

CLR P3.6

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY3

LCALL DELY10MS

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY3

MOV A,P3

ANL A,#0FH

CJNE A,#0EH,NK9

MOV KEYBUF,#8

LJMP DK3

NK9: CJNE A,#0DH,NK10

MOV KEYBUF,#9

LJMP DK3

NK10: CJNE A,#0BH,NK11

MOV KEYBUF,#10

LJMP DK3

NK11: CJNE A,#07H,NK12

MOV KEYBUF,#11

LJMP DK3

NK12: NOP

DK3:

MOV A,KEYBUF

MOV DPTR,#TABLE

MOVC A,@A+DPTR

MOV P0,A

DK3A: MOV A,P3

ANL A,#0FH

XRL A,#0FH

JNZ DK3A

NOKEY3:

MOV P3,#0FFH

CLR P3.7

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY4

LCALL DELY10MS

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY4

MOV A,P3

ANL A,#0FH

CJNE A,#0EH,NK13

MOV KEYBUF,#12

LJMP DK4

NK13: CJNE A,#0DH,NK14

MOV KEYBUF,#13

LJMP DK4

NK14: CJNE A,#0BH,NK15

MOV KEYBUF,#14

LJMP DK4

NK15: CJNE A,#07H,NK16

MOV KEYBUF,#15

LJMP DK4

NK16: NOP

DK4:

MOV A,KEYBUF

MOV DPTR,#TABLE

MOVC A,@A+DPTR

MOV P0,A

DK4A: MOV A,P3

ANL A,#0FH

XRL A,#0FH

JNZ DK4A

NOKEY4:

LJMP WAIT

DELY10MS:

MOV R6,#10

D1: MOV R7,#248

DJNZ R7,$

DJNZ R6,D1

RET

TABLE: DB

3FH,06H,5BH,4FH,66H,6DH,7

DH,07H

DB

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

H,71H

END

C 语言源程序

#INClude

unsigned char code

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

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

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

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

unsigned char temp;

unsigned char key;

unsigned char i,j;

void main(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)

{

case 0x0e:

key=7;

break;

case 0x0d:

key=8;

break;

case 0x0b:

key=9;

break;

case 0x07:

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)

{

case 0x0e:

key=4;

break;

case 0x0d:

key=5;

break;

case 0x0b:

key=6;

break;

case 0x07:

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)

{

case 0x0e:

key=1;

break;

case 0x0d:

key=2;

break;

case 0x0b:

key=3;

break;

case 0x07:

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)

{

case 0x0e:

key=0;

break;

case 0x0d:

key=13;

break;

case 0x0b:

key=14;

break;

case 0x07:

key=15;

break;

}

temp=P3;

P1_0=~P1_0;

P0=table[key];

temp=temp & 0x0f;

while(temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

}

}

}

}

}

七、按键识别方法

每按下一次开关 SP1,计数值加 1,通过AT89S51 单片机的 P1 端口的 P1.0 到 P1.3

显示出其二进制计数值。

*

程序设计方法:作为一个按键从没有按下到按下以及释放是一个完整的过程,也就是说,当我们按

下一个按键时,总希望某个命令只执行一次,而在按键按下的 过程中,不要有干扰进来,因为,在

按下的过程中,一旦有干扰过来,可能造成误触发过程,这并不是我们所想要的。因此在按键按下的

时候,要把我们手上的干扰信号以及按键的机械接触等干扰信号给滤除掉,一般情况下,我们可以采

用电容来滤除掉这些干扰信号,但实际上,会增加硬件成本及硬件电路的体积,这是我们不希望,总

得有个办法解决这个问题,因此我们可以采用软件滤波的方法去除这些干扰信号,一般情况下,一个

按键按下的时候,总是在按下的时刻存在着一定的干扰信号,按下之后就基本上进入了稳定的状态。

具体的一个按键从按下到释放的全过程的信号图如上图所示:从图中可以看出,我们在程序设计时,

从按键被识别按下之后,延时 5ms 以上,从而避开了干扰信号区域,我们再来检测一次,看按键是

否真得已经按下,若真得已经按下,这时肯定输出为低电平,若这时检测到的是高电平,证明刚才是

由于干扰信号引起的误触发,CPU 就认为是误触发信号而舍弃这次的按键识别过程。从而提高了系

统的可靠性。

由于要求每按下一次,命令被执行一次,直到下一次再按下的时候,再执行一次命令,因此从按

键被识别出来之后,我们就可以执行这次的命令,所以要有一个等待按键释放的过程,显然释放的过

程,就是使其恢复成高电平状态。

1. 汇编源程序

ORG 0000H

START: MOV R1,#00H ;

初始化 R1 为 0,表示从 0 开始计数

MOV A, R1

;

CPL A ;取反指令

MOV P1,A ;送出 P1 端口由发光二极管显示

REL: JB P3.7,REL ;判断 SP1 是否按下

LCALL DELAY10MS ;若按下,则延时 10ms 左右

JB P3.7,REL ;再判断 SP1 是否真得按下

INC R1 ;若确实按下,则进行按键处理,使

MOV A,R1 ;计数内容加 1,并送出 P1 端口由

CPL A ;发光二极管显示

MOV P1,A ;

JNB P3.7,$ ;等待 SP1 释放

SJMP REL ;继续对 K1 按键扫描

DELAY10MS: MOV R6,#20 ;延时 10ms 子程序

L1: MOV R7,#248

DJNZ R7,$

DJNZ R6,L1

RET

END

2. C 语言源程序

#include

unsigned char count;

void delay10ms(void)

{

unsigned char i,j;

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

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

}

void main(void)

{

while(1)

{

if(P3_7==0)

{

delay10ms();

if(P3_7==0)

{

count++;

if(count==16)

{

count=0;

}

P1=~count;

while(P3_7==0);

}

}

}

}

八、数字钟

(1. 开机时,显示 12:00:

00

整,每按一次加

2

的时间开始计时;

. P0.0/AD0

控制

1 秒;

“秒

”的调

整,每按一次加

3. P0.1/AD1

控制

1 分;

“分

”的调

(4. P0.2/AD2 控制“时”的调

整,每按一次加 1 个小时

MOV MINITE,#00H

6. 汇编源程序

SECOND EQU 30H

MINITE EQU 31H

HOUR EQU 32H

HOURK BIT P0.0

MINITEK BIT P0.1

SECONDK BIT P0.2

DISPBUF EQU 40H

DISPBIT EQU 48H

T2SCNTA EQU 49H

T2SCNTB EQU 4AH

TEMP EQU 4BH

ORG 00H

LJMP START

ORG 0BH

LJMP INT_T0

START: MOV SECOND,#00H

MOV MINITE,#00H

MOV HOUR,#12

MOV DISPBIT,#00H

MOV T2SCNTA,#00H

MOV T2SCNTB,#00H

MOV TEMP,#0FEH

LCALL DISP

MOV TMOD,#01H

MOV TH0,#(65536-2000) / 256

MOV TL0,#(65536-2000) MOD

256

SETB TR0

SETB ET0

SETB EA

WT: JB SECONDK,NK1

LCALL DELY10MS

JB SECONDK,NK1

INC SECOND

MOV A,SECOND

CJNE A,#60,NS60

MOV SECOND,#00H

NS60: LCALL DISP

JNB SECONDK,$

NK1: JB MINITEK,NK2

LCALL DELY10MS

JB MINITEK,NK2

INC MINITE

MOV A,MINITE

CJNE A,#60,NM60

NM60: LCALL DISP

JNB MINITEK,$

NK2: JB HOURK,NK3

LCALL DELY10MS

JB HOURK,NK3

INC HOUR

MOV A,HOUR

CJNE A,#24,NH24

MOV HOUR,#00H

NH24: LCALL DISP

JNB HOURK,$

NK3: LJMP WT

DELY10MS:

MOV R6,#10

D1: MOV R7,#248

DJNZ R7,$

DJNZ R6,D1

RET

DISP:

MOV A,#DISPBUF

ADD A,#8

DEC A

MOV R1,A

MOV A,HOUR

MOV B,#10

DIV AB

MOV @R1,A

DEC R1

MOV A,B

MOV @R1,A

DEC R1

MOV A,#10

MOV@R1,A

DEC R1

MOV A,MINITE

MOV B,#10

DIV AB

MOV @R1,A

DEC R1

MOV A,B

MOV @R1,A

DEC R1

MOV A,#10

MOV@R1,A

DEC R1

MOV

A,SECOND

MOV B,#10

DIV AB

MOV @R1,A

DEC R1

MOV A,B

MOV @R1,A

DEC R1

RET

INT_T0:

MOV TH0,#(65536-2000) / 256

MOV TL0,#(65536-2000) MOD

256

MOV A,#DISPBUF

ADD A,DISPBIT

MOV R0,A

MOV A,@R0

MOV DPTR,#TABLE

MOVC A,@A+DPTR

MOV P1,A

MOV A,DISPBIT

MOV DPTR,#TAB

MOVC A,@A+DPTR

MOV P3,A

INC DISPBIT

MOV A,DISPBIT

CJNE A,#08H,KNA

MOV DISPBIT,#00H

KNA: INC T2SCNTA

MOV A,T2SCNTA

CJNE

A,#100,DONE

MOV

T2SCNTA,#0

0H

INC

T2SCNTB

MOV

A,T2SCNTB

CJNE

A,#05H,DON

E

MOV

T2SCNTB,#0

0H

INC SECOND

MOV A,SECOND

CJNE A,#60,NEXT

MOV SECOND,#00H

INC MINITE

MOV A,MINITE

CJNE A,#60,NEXT

MOV MINITE,#00H

INC HOUR

MOV A,HOUR

CJNE A,#24,NEXT

MOV HOUR,#00H

NEXT: LCALL DISP

DONE: RETI

TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,

7DH,07H,7FH,6FH,40H

TAB: DB 0FEH,0FDH,0FBH,0F7H,0EFH,

0DFH,0BFH,07FH

END

7. C 语言源程序

#INClude

unsigned char code

dispcode[]={0x3f,0x06,0x5b,0x4

f,0x66,0x6d,0x7d,0x07,0x7f,0x6

f,0x77,0x7c,0x39,0x5e,0x79,0x7

1,0x00};

unsigned char

dispbitcode[]={0xfe,0xfd,0xfb,0

xf7,0xef,0xdf,0xbf,0x7f};

unsigned char

dispbuf[8]={0,0,16,0,0,16,0,0};

unsigned char dispbitcnt;

unsigned char second;

unsigned char minite;

unsigned char hour;

unsigned int tcnt;

unsigned char mstcnt;

unsigned char i,j;

void main(void)

{

TMOD=0x02;

TH0=0x06;

TL0=0x06;

TR0=1;

ET0=1;

EA=1;

while(1)

{

if(P0_0==0)

{

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

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

tcnt=0;

second++;

if(second==60)

{

second=0;

minite++;

if(minite==60)

{

minite=0;

hour++;

if(hour==24)

{

hour=0;

if(P0_0==0)

{

second++;

if(second==60)

{

second=0;

}

dispbuf[0]=second%10;

dispbuf[1]=second/10;

while(P0_0==0);

}

}

if(P0_1==0)

{

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

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

if(P0_1==0)

{

minite++;

if(minite==60)

{

minite=0;

}

dispbuf[3]=minite%10;

dispbuf[4]=minite/10;

while(P0_1==0);

}

}

if(P0_2==0)

{

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

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

}

}

}

dispbuf[0]=second%10;

dispbuf[1]=second/10;

dispbuf[3]=minite%10;

dispbuf[4]=minite/10;

dispbuf[6]=hour%10;

dispbuf[7]=hour/10;

}

}

}

if(P0_2==0)

{

hour++;

if(hour==24)

{

hour=0;

}

dispbuf[6]=hour%10;

dispbuf[7]=hour/10;

while(P0_2==0);

}

}

}

}

void t0(void) interrupt 1 using 0

{

mstcnt++;

if(mstcnt==8)

{

mstcnt=0;

P1=dispcode[dispbuf[dispbitcnt]

];

P3=dispbitcode[dispbitcnt];

dispbitcnt++;

if(dispbitcnt==8)

{

dispbitcnt=0;

}

}

tcnt++;

if(tcnt==4000)

{

九. ADC0809A/D 转换器基本应用技术

1 基本知识ADC0809 是带有 8 位 A/D 转换器、8 路多路开关以及微处理机兼容的控制逻辑的

CMOS 组件。它是逐次逼近式 A/D 转换器,可以和单片机

直接接口。

2 ADC0809 的内部逻辑结构图9-1

由上图可知,ADC0809 由一个 8 路模拟开关、一个地

址锁存与译码器、一个 A/D转换器和一个三态输出锁存器组

成。多路开关可选通 8 个模拟通道,允许 8 路模拟量分时

输入,共用 A/D 转换器进行转换。三态输出锁器用于锁存

A/D 转换完的数字量,当 OE 端为高电平时,才可以从三态

输出锁存器取走转换完的数据。

3 引脚结构

IN0-IN7:8 条模拟量输入通道

ADC0809 对输入模拟量要求:信号单极性,电压范围是

0-5V,若信号太小,必须进行放大;输入的模拟量在转换

过程中应该保持不变,如若模拟量变化太快,则需在输入前

增加采样保持电路。

地址输入和控制线:4 条

ALE 为地址锁存允许输入线,高电平有效。当 ALE 线为高电平时,地址锁存与译

码器将 A,B,C 三条地址线的地址信号进行锁存,经译码后被选中的通道的模拟

量进转换器进行转换。A,B 和 C 为地址输入线,用于选通 IN0-IN7 上的一路模

拟量输入。通道选择表如下表所示。

C B A 选择的通道

0 0 0 IN0

0 0 1 IN1

0 1 0 IN2

0 1 1 IN3

1 0 0 IN4

1 0 1 IN5

1 1 0 IN6

1 1 1 IN7

数字量输出及控制线:11 条

ST 为转换启动信号。当 ST 上跳沿时,所有内部寄存器清零;下跳沿时,开始进

行 A/D 转换;在转换期间,ST 应保持低电平。EOC 为转换结束信号。当 EOC 为高

电平时,表明转换结束;否则,表明正在进行 A/D 转换。OE 为输出允许信号,

用于控制三条输出锁存器向单片机输出转换得到的数据。OE=1,输出转换得到

的数据;OE=0,输出数据线呈高阻状态。D7-D0 为数字量输出线。

CLK 为时钟输入信号线。因 ADC0809 的内部没有时钟电路,所需时钟信号必须由

外界提供,通常使用频率为 500KHZ,VREF(+),VREF(-)为参考电压输入。

4 ADC0809 应用说明

(1). ADC0809 内部带有输出锁存器,可以与 AT89S51 单片机直接相连。

(2). 初始化时,使 ST 和 OE 信号全为低电平。

(3). 送要转换的哪一通道的地址到 A,B,C 端口上。

(4). 在 ST 端给出一个至少有 100ns 宽的正脉冲信号。

(5). 是否转换完毕,我们根据 EOC 信号来判断。

(6). 当 EOC 变为高电平时,这时给 OE 为高电平,转换的数据就输出给单片机了。

5 实验任务

如下图所示,从 ADC0809 的通道 IN3 输入 0-5V 之间的模拟量,通过 ADC0809

转换成数字量在数码管上以十进制形成显示出来。ADC0809 的 VREF 接+5V电压。

6 电路原理图

5. 系统板上硬件连线

(1). 把“单片机系统板”区域中的 P1 端口的 P1.0-P1.7 用 8 芯排线连接到“动态数码显示”区域

中的 A B C D E F G H 端口上,作为数码管的笔段驱动。

(2). 把“单片机系统板”区域中的 P2 端口的 P2.0-P2.7 用 8 芯排线连接到“动态数码显示”区域

中的 S1 S2 S3 S4 S5 S6 S7 S8 端口上,作为数码管的位段选择。

(3). 把“单片机系统板”区域中的 P0 端口的 P0.0-P0.7 用 8 芯排线连接到“模数转换模块”区域

中的 D0D1D2D3D4D5D6D7 端口上,A/D 转换完毕的数据输入到单片机的 P0 端口

(4). 把“模数转换模块”区域中的 VREF 端子用导线连接到“电源模块”区域中的 VCC 端子上;

(5). 把“模数转换模块”区域中的 A2A1A0 端子用导线连接到“单片机系统”区域中的 P3.4 P3.5

P3.6 端子上;

(6). 把“模数转换模块”区域中的 ST 端子用导线连接到“单片机系统”

区域中的 P3.0 端子上;

(7). 把“模数转换模块”区域中的 OE 端子用导线连接到“单片机系统”区域中的 P3.1 端子上;

(8).把“模数转换模块”区域中的 EOC 端子用导线连接到“单片机系统”区域中的 P3.2 端子上;

(9). 把“模数转换模块”区域中的 CLK 端子用导线连接到“分频模块”区域中的 /4 端子上;

(10). 把“分频模块”区域中的 CK IN 端子用导线连接到“单片机系统”区域中的 ALE 端子上;

(11). 把“模数转换模块”区域中的 IN3 端子用导线连接到“三路可调压模块”区域中的 VR1 端子

上;

6. 程序设计内容

(1). 进行 A/D 转换时,采用查询 EOC 的标志信号来检测 A/D 转换是否完毕,若完毕则把数

据通过 P0 端口读入,经过数据处理之后在数码管上显示。

(2). 进行 A/D 转换之前,要启动转换的方法:ABC=110 选择第三通道ST=0,ST=1,ST=0

产生启动转换的正脉冲信号

7. 汇编源程序

CH EQU 30H

DPCNT EQU 31H

DPBUF EQU 33H

GDATA EQU 32H

ST BIT P3.0

OE BIT P3.1

EOC BIT P3.2

ORG 00H

LJMP START

ORG 0BH

LJMP T0X

ORG 30H

START: MOV CH,#0BCH

MOV DPCNT,#00H

MOV R1,#DPCNT

MOV R7,#5

MOV A,#10

MOV R0,#DPBUF

LOP: MOV @R0,A

INC R0

DJNZ R7,LOP

MOV @R0,#00H

INC R0

MOV @R0,#00H

INC R0

MOV @R0,#00H

MOV TMOD,#01H

MOV TH0,#(65536-4000)/256

MOV TL0,#(65536-4000)

MOD 256

SETB TR0

SETB ET0

SETB EA

WT: CLR ST

SETB ST

CLR ST

WAIT: JNB EOC,WAIT

SETB OE

MOV GDATA,P0

CLR OE

MOV A,GDATA

MOV B,#100

DIV AB

MOV 33H,A

MOV A,B

MOV B,#10

DIV AB

MOV 34H,A

MOV 35H,B

SJMP WT

T0X: NOP

MOV TH0,#(65536-4000)/256

MOV TL0,#(65536-4000) MOD

256

MOV DPTR,#DPCD

MOV A,DPCNT

ADD A,#DPBUF

MOV R0,A

MOV A,@R0

MOVC A,@A+DPTR

MOV P1,A

MOV DPTR,#DPBT

MOV A,DPCNT

MOVC A,@A+DPTR

MOV P2,A

INC DPCNT

MOV A,DPCNT

CJNE A,#8,NEXT

MOV DPCNT,#00H

NEXT: RETI

DPCD: DB

3FH,06H,5BH,4FH,66H

DB

6DH,7DH,07H,7FH,6FH,00H

DPBT: DB

0FEH,0FDH,0FBH,0F7H

DB 0EFH,0DFH,0BFH,07FH

END

8. C 语言源程序

#INClude

unsigned char code

dispbitcode[]={0xfe,0xfd,0xfb,0

xf7,

0xef,0xdf,0xbf,0x7f};

unsigned char code

dispcode[]={0x3f,0x06,0x5b,0x4

f,0x66,

0x6d,0x7d,0x07,0x7f,0x6f,0x00

};

unsigned char

dispbuf[8]={10,10,10,10,10,0,0,

0};

unsigned char dispcount;

sbit ST=P3^0;

sbit OE=P3^1;

sbit EOC=P3^2;

unsigned char

channel=0xbc;//IN3

unsigned char getdata;

void main(void)

{

TMOD=0x01;

TH0=(65536-4000)/256;

TL0=(65536-4000)%256;

TR0=1;

ET0=1;

EA=1;

P3=channel;

while(1)

{

ST=0;

ST=1;

ST=0;

while(EOC==0);

OE=1;

getdata=P0;

OE=0;

dispbuf[2]=getdata/100;

getdata=getdata%10;

dispbuf[1]=getdata/10;

dispbuf[0]=getdata%10;

}

}

void t0(void) interrupt 1 using 0

{

TH0=(65536-4000)/256;

TL0=(65536-4000)%256;

P1=dispcode[dispbuf[dispcount]

];

P2=dispbitcode[dispcount];

dispcount++;

if(dispcount==8)

{

dispcount=0;

}

}

十、DS18B20 数字温度计使用

1.DS18B20 基本知识

DS18B20 数字温度计是 DALLAS 公司生产的 1-Wire,即单总线器件,具有线路简单,体积小的

特点。因此用它来组成一个测温系统,具有线路简单,在一根通信线,可以挂很多这样的数字温度计,

十分方便。

1、DS18B20 产品的特点

(1)、只要求一个端口即可实现通信。

(2)、在 DS18B20 中的每个器件上都有独一无二的序列号。

(3)、实际应用中不需要外部任何元器件即可实现测温。

(4)、测量温度范围在-55。C 到+125。C 之间。

(5)、数字温度计的分辨率用户可以从 9 位到 12 位选择。

(6)、内部有温度上、下限告警设置。

2、DS18B20 的引脚介绍

TO-92 封装的 DS18B20 的引脚排列见图 1,其引脚功能描述见表 1。(底视图)图 1

由于 DS18B20 采用的是 1-Wire 总线协议方式,即在一根数据线实现数据的双向传输,而对

AT89S51 单片机来说,硬件上并不支持单总线协议,因此,我们必须采用软件的方法来模拟单总线

的协议时序来完成对 DS18B20 芯片的访问。

由于 DS18B20 是在一根 I/O 线上读写数据,因此,对读写的数据位有着严格的时序要求。DS18B20

有严格的通信协议来保证各位数据传输的正确性和完整性。该协议定义了几种信号的时序:初始化时

序、读时序、写时序。所有时序都是将主机作为主设备,单总线器件作为从设备。而每一次命令和数

据的传输都是从主机主动启动写时序开始,如果要求单总线器件回送数据,在进行写命令后,主机需

启动读时序完成数据接收。数据和命令的传输都是低位在先。

DS18B20 的复位时序

DS18B20 的读时序对于 DS18B20

的读时序分为读 0 时序和读 1 时序两个过程。对于 DS18B20 的读时隙是从主机把单总线拉低之

后,在 15 秒之内就得释放单总线,以让 DS18B20 把数据传输到单总线上。DS18B20 在完成一个

读时序过程,至少需要 60us 才能

完成。

对于 DS18B20 的写时序仍然分为写 0 时序和写 1 时序两个过程。对于 DS18B20 写 0 时序和写

1 时序的要求不同,当要写 0 时序时,单总线要被拉低至少 60us,保证 DS18B20 能够在 15us 到

45us 之间能够正确地采样 IO 总线上的“0”电平,当要写 1 时序时,单总线被拉低之后,在 15us 之

内就得释放单总线。

4. 实验任务

用一片 DS18B20 构成测温系统,测量的温度精度达到 0.1 度,测量的温度的范围在-20 度到+100

度之间,用 8 位数码管显示出来。

5. 电路原理图

7. C 语言源程序

#INClude

#INClude

unsigned char code

displaybit[]={0xfe,0xfd,0xfb,0xf7,

0xef,0xdf,0xbf,0x7f};

unsigned char code

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

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

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

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

unsigned char code

dotcode[32]={0,3,6,9,12,16,19,22,

25,28,31,34,38,41,44,48,

50,53,56,59,63,66,69,72,

75,78,81,84,88,91,94,97};

unsigned char displaycount;

unsigned char

displaybuf[8]={16,16,16,16,16,16,16,16

};

unsigned char timecount;

unsigned char readdata[8];

{

sbit DQ=P3^7;

DQ=0;

bit sflag;

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

bit resetpulse(void)

DQ=1;

{

}

unsigned char i;

else

DQ=0;

{

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

DQ=0;

DQ=1;

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

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

DQ=1;

RETurn(DQ);

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

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

}

}

command=_cror_(command,1);

void writecommandtods18b20(unsigned char

}

command)

}

{

Unsigned char readdatafromds18b20(void)

unsigned char i;

unsigned char j;

Unsigned char i;

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

Unsigned char j;

{

Unsigned char temp;

if((command & 0x01)==0)

temp=0;

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

{

temp=_cror_(temp,1);

DQ=0;

_nop_();

_nop_();

DQ=1;

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

if(DQ==1)

{

temp=temp | 0x80;

}

else

{

temp=temp | 0x00;

}

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

}

RETurn(temp);

}

void main(void)

{

TMOD=0x01;

TH0=(65536-4000)/256;

TL0=(65536-4000)%256;

ET0=1;

EA=1;

while(resetpulse());

writecommandtods18b20(0xcc);

writecommandtods18b20(0x44);

TR0=1;

while(1)

{

;

}

}

void t0(void) interrupt 1 using 0

{

unsigned char x;

unsigned int result;

TH0=(65536-4000)/256;

TL0=(65536-4000)%256;

if(displaycount==2)

{

P0=displaycode[displaybuf[displaycount]] | 0x80;

}

else

{

P0=displaycode[displaybuf[displaycount]];

}

P2=displaybit[displaycount];

displaycount++;

if(displaycount==8)

{

displaycount=0;

}

timecount++;

if(timecount==150)

{

timecount=0;

while(resetpulse());

writecommandtods18b20(0xcc);

writecommandtods18b20(0xbe);

readdata[0]=readdatafromds18b20();

readdata[1]=readdatafromds18b20();

for(x=0;x<8;x++)

{

displaybuf[x]=16;

}

sflag=0;

if((readdata[1] & 0xf8)!=0x00)

{

sflag=1;

readdata[1]=~readdata[1];

readdata[0]=~readdata[0];

result=readdata[0]+1;

readdata[0]=result;

if(result>255)

{

readdata[1]++;

}

}

readdata[1]=readdata[1]<<4;

readdata[1]=readdata[1] & 0x70;

x=readdata[0];

x=x>>4;

x=x & 0x0f;

readdata[1]=readdata[1] | x;

x=2;

result=readdata[1];

while(result/10)

{

displaybuf[x]=result%10;

result=result/10;

x++;

}

displaybuf[x]=result;

if(sflag==1)

{

displaybuf[x+1]=17;

}

x=readdata[0] & 0x0f;

x=x<<1;

displaybuf[0]=(dotcode[x])%10;

displaybuf[1]=(dotcode[x])/10;

while(resetpulse());

writecommandtods18b20(0xcc);

writecommandtods18b20(0x44);

}

}

11、 4×4 键盘及 8 位数码管显示构成的电子密码锁

用 4×4 组成 0-9 数字键及确认键。

用 8 位数码管组成显示电路提示信息,当输入密码时,只显示“8.”,当密码位数输入完毕按下确认

键时,对输入的密码与设定的密码进行比较,若密码正确,则门开,此处用 LED 发光二极管亮一秒

钟做为提示,同时发出“叮咚”声;若密码不正确,禁止按键输入 3 秒,同时发出“嘀、嘀”

报警声;若在 3 秒之内仍有按键按下,则禁止按键输入 3 秒被重新禁止。

4. 程序设计内容

(1). 4×4 行列式键盘识别技术:有关这方面内容前面已经讨论过,这里不再重复。

(2). 8 位数码显示,初始化时,显示“P ”,接着输入最大 6 位数的密码,当密码输入完

后,按下确认键,进行密码比较,然后给出相应的信息。在输入密码过程中,显示器只显示“8.”。当

数字输入超过 6个时,给出报警信息。在密码输入过程中,若输入错误,可以利用“DEL”键删除刚才

输入的错误的数字。

(3). 4×4 行列式键盘的按键功能分布图如图 4.33.2 所示:

5. C 语言源程序

#include

unsigned char ps[]={1,2,3,4,5};

unsigned char code dispbit[]={0xfe,0xfd,0xfb,0xf7,

0xef,0xdf,0xbf,0x7f};

unsigned char code

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

0x6d,0x7d,0x07,0x7f,0x6f,

0x77,0x7c,0x39,0x5e,0x79,0x71,

0x00,0x40,0x73,0xff};

unsigned char

dispbuf[8]={18,16,16,16,16,16,16,16};

unsigned char dispcount;

unsigned char flashcount;

unsigned char temp;

unsigned char key;

unsigned char keycount;

unsigned char pslen=5;

unsigned char getps[6];

bit keyoverflag;

bit errorflag;

bit rightflag;

unsigned int second3;

unsigned int aa,bb;

unsigned int cc;

bit okflag;

bit alarmflag;

bit hibitflag;

unsigned char oka,okb;

void main(void)

{

unsigned char i,j;

TMOD=0x01;

TH0=(65536-500)/256;

TL0=(65536-500)%256;

TR0=1;

ET0=1;

EA=1;

while(1)

{

P3=0xff;

P3_4=0;

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

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

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

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

switch(temp)

{

case 0x0e:

key=7;

break;

case 0x0d:

key=8;

break;

case 0x0b:

key=9;

break;

case 0x07:

key=10;

break;

}

temp=P3;

P1_1=~P1_1;

if((key>=0) && (key<10))

{

if(keycount<6)

{

getps[keycount]=key;

dispbuf[keycount+2]=19;

}

keycount++;

if(keycount==6)

{

keycount=6;

}

else if(keycount>6)

{

keycount=6;

keyoverflag=1;//key overflow

}

}

else if(key==12)//delete key

{

if(keycount>0)

{

keycount--;

getps[keycount]=0;

dispbuf[keycount+2]=16;

}

else

{

keyoverflag=1;

}

}

else if(key==15)//enter key

{

if(keycount!=pslen)

{

errorflag=1;

rightflag=0;

second3=0;

}

else

{

for(i=0;i

{

if(getps[i]!=ps[i])

{

i=keycount;

errorflag=1;

rightflag=0;

second3=0;

goto a;

}

}

errorflag=0;

rightflag=1;

a: i=keycount;

}

}

temp=temp & 0x0f;

while(temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

}

keyoverflag=0;//?????????

}

}

P3=0xff;

P3_5=0;

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

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

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

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

switch(temp)

{

case 0x0e:

key=4;

break;

case 0x0d:

key=5;

break;

case 0x0b:

key=6;

break;

case 0x07:

key=11;

break;

}

temp=P3;

P1_1=~P1_1;

if((key>=0) && (key<10))

{

if(keycount<6)

{

getps[keycount]=key;

dispbuf[keycount+2]=19;

}

keycount++;

if(keycount==6)

{

keycount=6;

}

else if(keycount>6)

{

keycount=6;

keyoverflag=1;//key overflow

}

}

else if(key==12)//delete key

{

if(keycount>0)

{

keycount--;

getps[keycount]=0;

dispbuf[keycount+2]=16;

}

else

{

keyoverflag=1;

}

}

else if(key==15)//enter key

{

if(keycount!=pslen)

{

errorflag=1;

rightflag=0;

second3=0;

}

else

{

for(i=0;i

{

if(getps[i]!=ps[i])

{

i=keycount;

errorflag=1;

rightflag=0;

second3=0;

goto a4;

}

}

errorflag=0;

rightflag=1;

a4: i=keycount;

}

}

temp=temp & 0x0f;

while(temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

}

keyoverflag=0;//?????????

}

}

P3=0xff;

P3_6=0;

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

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

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

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

switch(temp)

{

case 0x0e:

key=1;

break;

case 0x0d:

key=2;

break;

case 0x0b:

key=3;

break;

case 0x07:

key=12;

break;

}

temp=P3;

P1_1=~P1_1;

if((key>=0) && (key<10))

{

if(keycount<6)

{

getps[keycount]=key;

dispbuf[keycount+2]=19;

}

keycount++;

if(keycount==6)

{

keycount=6;

}

else if(keycount>6)

{

keycount=6;

keyoverflag=1;//key overflow

}

}

else if(key==12)//delete key

{

if(keycount>0)

{

keycount--;

getps[keycount]=0;

dispbuf[keycount+2]=16;

}

else

{

keyoverflag=1;

}

}

else if(key==15)//enter key

{

if(keycount!=pslen)

{

errorflag=1;

rightflag=0;

second3=0;

}

else

{

for(i=0;i

{

if(getps[i]!=ps[i])

{

i=keycount;

errorflag=1;

rightflag=0;

second3=0;

goto a3;

}

}

errorflag=0;

rightflag=1;

a3: i=keycount;

}

}

temp=temp & 0x0f;

while(temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

}

keyoverflag=0;//?????????

}

}

P3=0xff;

P3_7=0;

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

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

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

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

switch(temp)

{

case 0x0e:

key=0;

break;

case 0x0d:

key=13;

break;

case 0x0b;

key=14;

break;

case 0x07:

key=15;

break;

}

temp=P3;

P1_1=~P1_1;

if((key>=0) && (key<10))

{

if(keycount<6)

{

getps[keycount]=key;

dispbuf[keycount+2]=19;

}

keycount++;

if(keycount==6)

{

keycount=6;

}

else if(keycount>6)

{

keycount=6;

keyoverflag=1;//key overflow

}

}

else if(key==12)//delete key

{

if(keycount>0)

{

keycount--;

getps[keycount]=0;

dispbuf[keycount+2]=16;

}

else

{

keyoverflag=1;

}

}

else if(key==15)//enter key

{

if(keycount!=pslen)

{

errorflag=1;

rightflag=0;

second3=0;

}

else

{

for(i=0;i

{

if(getps[i]!=ps[i])

{

i=keycount;

errorflag=1;

rightflag=0;

second3=0;

goto a2;

}

}

errorflag=0;

rightflag=1;

a2: i=keycount;

}

}

temp=temp & 0x0f;

while(temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

}

keyoverflag=0;//?????????

}

}

}

}

void t0(void) interrupt 1 using 0

{

TH0=(65536-500)/256;

TL0=(65536-500)%256;

flashcount++;

if(flashcount==8)

{

flashcount=0;

P0=dispcode[dispbuf[dispcount]];

P2=dispbit[dispcount];

dispcount++;

if(dispcount==8)

{

dispcount=0;

}

}

if((errorflag==1) && (rightflag==0))

{

bb++;

if(bb==800)

{

bb=0;

alarmflag=~alarmflag;

}

if(alarmflag==1)//sound alarm signal

{

P1_7=~P1_7;

}

aa++;

if(aa==800)//light alarm signal

{

aa=0;

P1_0=~P1_0;

}

second3++;

if(second3==6400)

{

second3=0;

errorflag=0;

rightflag=0;

alarmflag=0;

bb=0;

aa=0;

}

}

else if((errorflag==0) && (rightflag==1))

{

P1_0=0;

cc++;

if(cc<1000)

{

okflag=1;

}

else if(cc<2000)

{

okflag=0;

}

else

{

errorflag=0;

rightflag=0;

P1_7=1;

cc=0;

oka=0;

okb=0;

okflag=0;

P1_0=1;

}

if(okflag==1)

{

oka++;

if(oka==2)

{

oka=0;

P1_7=~P1_7;

}

}

else

{

okb++;

if(okb==3)

{

okb=0;

P1_7=~P1_7;

}

}

}

if(keyoverflag==1)

{

P1_7=~P1_7;

}

}

12. 6 位数显频率计数器

1. 实验任务

利用 AT89S51 单片机的 T0、T1 的定时计数器功能,来完成对输入的信号进行频率计数,计数的

频率结果通过 8 位动态数码管显示出来。要求能够对0-250KHZ 的信号频率进行准确计数,计数误

差不超过±1HZ。

3. 程序设计内容

(1). 定时/计数器 T0 和 T1 的工作方式设置,由图可知,T0 是工作在计数状态下,对输入的

频率信号进行计数,但对工作在计数状态下的 T0,最大计数值为 f

OSC

/24,由于 f

OSC

=12MHz,因

此:T0 的最大计数频率为250KHz。对于频率的概念就是在一秒只数脉冲的个数,即为频率值。

所以 T1 工作在定时状态下,每定时 1 秒中到,就停止 T0 的计数,而从 T0 的计数单元中读取计

数的数值,然后进行数据处理。送到数码管显示出来。

(2). T1 工作在定时状态下,最大定时时间为 65ms,达不到 1 秒的定时,所

以采用定时 50ms,共定时 20 次,即可完成 1 秒的定时功能。

. C 语言源程序

#include

unsigned char code

dispbit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f

};

unsigned char code

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

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

unsigned char dispbuf[8]={0,0,0,0,0,0,10,10};

unsigned char temp[8];

unsigned char dispcount;

unsigned char T0count;

unsigned char timecount;

bit flag;

unsigned long x;

void main(void)

{

unsigned char i;

TMOD=0x15;

TH0=0;

TL0=0;

TH1=(65536-4000)/256;

TL1=(65536-4000)%256;

TR1=1;

TR0=1;

ET0=1;

ET1=1;

EA=1;

while(1)

{

if(flag==1)

{

flag=0;

x=T0count*65536+TH0*256+TL0;

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

{

temp[i]=0;

}

i=0;

while(x/10)

{

temp[i]=x%10;

x=x/10;

i++;

}

temp[i]=x;

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

{

dispbuf[i]=temp[i];

}

timecount=0;

T0count=0;

TH0=0;

TL0=0;

TR0=1;

}

}

}

void t0(void) interrupt 1 using 0

{

T0count++;

}

void t1(void) interrupt 3 using 0

{

TH1=(65536-4000)/256;

TL1=(65536-4000)%256;

timecount++;

if(timecount==250)

{

TR0=0;

timecount=0;

flag=1;

}

P0=dispcode[dispbuf[dispcount]];

P2=dispbit[dispcount];

dispcount++;

if(dispcount==8)

{

dispcount=0;

}

}

13、LCD驱动程序

根据原理图设计LCD1602液晶显示电路的驱动程

序:

/********************************

FILE NAME: LCD1602.c

CHIP TYPE: AT89C51

CLOCK FREQUENCY: 12MHZ

IDE: VSMStudio

COMPILER: IAR for 8051

TIME: 7/ 2012

********************************/

#include "ioAT89C51.h"

#include "intrinsics.h"

// Define P3 pins

#define DATA_BUS (P0);数据总线P0

#define RS (P2_bit.P2_0);P2.0

#define RW (P2_bit.P2_1) ;P2.1

#define E (P2_bit.P2_2);P2.2

// Define new types

typedef unsigned char uchar;无符号字符型

typedef unsigned int uint;无符号整型

// Function Prototypes

void check_busy(void);检查忙信号

void write_command(uchar com);写指令

void write_data(uchar data);写数据

void LCD_init(void);LCD初始化

void string(uchar ad ,uchar *s);

void lcd_test(void);测试函数

void delay(uint);延时函数

void main(void);主函数

{ LCD_init();

while(1)

{ string(0x80,"Have a nice day!");

string(0xC0," Proteus VSM");

delay(100);

write_command(0x01);

delay(100);

}

}

/*******************************************

LCD1602 Driver mapped as IO peripheral

*******************************************/

// Delay,延时

void delay(uint j)

{ uchar i = 60;

for(; j>0; j--)

{ while(--i);

i = 59;

while(--i);

i = 60;

}

}

// Test the Busy bit,测试忙位BF

void check_busy(void)

{ do

{ DATA_BUS = 0xff;

E = 0;

RS = 0;

RW = 1;

E = 1;高电平

__no_operation();

} while(DATA_BUS & 0x80);

E = 0;

}

// Write a command,写指令

void write_command(uchar com)

{ check_busy();

E = 0;

RS = 0;

RW = 0;

DATA_BUS = com;

E = 1;

__no_operation();

E = 0;下降沿

delay(1);

}

// Write Data,写数据

void write_data(uchar data)

{ check_busy();

E = 0;

RS = 1;

RW = 0;

DATA_BUS = data;

E = 1;

__no_operation();

E = 0;

delay(1);

}

// Initialize LCD controller

void LCD_init(void)

{ write_command(0x38); // 8-bits, 2 lines, 7x5 dots

write_command(0x0C); // no cursor, no blink,

//enable display

write_command(0x06); // auto-INCrement on

write_command(0x01); // clear screen

delay(1);

}

// Display a string

void string(uchar ad, uchar *s)

{ write_command(ad);

while(*s>0)

{ write_data(*s++);

delay(100);

}

}

; LCD Display Driver Demo.

; Timing code assumes 1.2MHz Clock

;LCD Registers addresses

LCD_CMD_WR EQU 00H

LCD_DATA_WR EQU 01H

LCD_BUSY_RD EQU 02H

LCD_DATA_RD EQU 03H

;LCD Commands

LCD_CLS EQU 01

LCD_HOME EQU 02

LCD_SETMODE EQU 04

LCD_SETVISIBLE EQU 08

LCD_SHIFT EQU 16

LCD_SETFUNCTION EQU 32

LCD_SETCGADDR EQU 64

LCD_SETDDADDR EQU 128

;Reset vector

ORG 0000h

JMP start;//Start of the program

ORG 0100h

string1a:DB ' !! A M A Z I N G !! '

DB 0

string1b:DB '!! A M A Z I N G !! '

DB 0

string2:DB ' A '

DB 0

string3:DB ' driven by a virtual '

DB 0

string4:DB ' 8051 processor!'

DB 0

start:MOV A,#038h; 8位2行,5*7点阵

CALL wrcmd

loop: MOV A,#LCD_SETVISIBLE+6 ;Make the

display & blink visible:开显示,光标不闪烁

CALL wrcmd

MOV R7,#2

loop2: MOV DPTR,#string1a

CALL wrstr

MOV DPTR,#200

CALL wtms

MOV A,#LCD_CLS ;Clear screen

CALL wrcmd

MOV DPTR,#string1b

CALL wrstr

MOV DPTR,#200

CALL wtms

MOV A, #LCD_CLS ;Clear screen

CALL wrcmd

DJNZ R7,loop2

MOV DPTR,#string1a

CALL wrstr

MOV DPTR,#400

CALL wtms

MOV A,#LCD_SETDDADDR+64

CALL wrcmd

MOV DPTR,#string2

CALL wrslow

MOV DPTR,#200

CALL wtms

MOV A,#LCD_CLS ;Clear screen

CALL wrcmd

MOV DPTR,#string3

CALL wrslow

MOV A,#LCD_SETDDADDR+64

CALL wrcmd

MOV DPTR,#string4

CALL wrslow

MOV A,#LCD_SETVISIBLE+7 ;Show the

//blink cursor as well.

CALL wrcmd

MOV DPTR,#2000

CALL wtms

MOV A,#LCD_CLS ;Clear screen

CALL wrcmd

JMP loop

;Sub routine to write null terminated string at DPTR

in program ram.

wrstr: MOV R0,#LCD_DATA_WR

wrstr1: CLR A

MOVC A,@A+DPTR

JZ wrstr2

MOVX @R0,A

CALL wtbusy

INC DPTR

;Wait for number of milliseconds in DPTR

wtms: XRL DPL,#0FFh ;Can't do DEC

DPTR, so do the loop by forming 2's complement

PUSH DPL

PUSH DPH

POP DPH

POP DPL

JMP wrstr1

wrstr2: RET

;Sub routine to write null terminated string at DPTR

in program ram. Slowly

wrslow: MOV R0,#LCD_DATA_WR

wrslw1: CLR A

MOVc A,@A+DPTR

JZ wrslw2

MOVX @R0,A

CALL wtbusy

INC DPTR

PUSH DPL

PUSH DPH

MOV DPTR,#100

CALL wtms

POP DPH

POP DPL

JMP wrslw1

wrslw2: RET

;Sub routine to write command:

wrcmd: MOV R0,#LCD_CMD_WR

MOVX @R0,A

JMP wtbusy

;Sub routine to write character:

wrchar: MOV R0,#LCD_DATA_WR

MOVX @R0,A

;Subroutine to wait for busy clear

wtbusy: MOV R1,#LCD_BUSY_RD

MOVX A,@r1

JB ACC.7,wtbusy

RET

;Wait for number of seconds in A

wtsec: PUSH ACC

CALL wtms

POP ACC

DEC A

JNZ wtsec

RET

XRL DPH,#0FFh;and INCrementing instead.

INC DPTR

wtms1:MOV TL0,#09Ch ;100 ticks before

overflow = 1ms at 1.2MHz Clock

MOV TH0,#0FFh

MOV TMOD,#1 ;Timer 0 mode 1

SETB TCON.4 ;Timer 0 runs

wtms2: JNB TCON.5,wtms2

CLR TCON.4 ;Timer 0 stops

CLR TCON.5

INC DPTR

MOV A,DPL

ORL A,DPH

JNZ wtms1

RET

END

2024年10月13日发(作者:俟彗)

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

实验及课程设计

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

一、闪烁灯

如图1 所示为一简单单片机系统原理图:在 P1.0

端口上接一个发光二极管 L1,使 L1 在不停地

一亮一灭,一亮一灭的时间间隔为 0.2 秒。

延时程序的设计方法,作为单片机的指令的执行

DELAY: MOV R5,#20 ;延时子程序,延时 0.2 秒

D1: MOV R6,#20

D2: MOV R7,#248

DJNZ R7,$

DJNZ R6,D2

的时间是很短,数量大微秒级,因此,我们要

求的闪烁时间间隔为

说,相差太大,所以我们在执行某一指令时,

0.2 秒,相对于微秒来

插入延时程序,来达到我们的要求,但这样的

延时程

序是如何设计呢?下面具体介绍其原理:如图

4.1.1

机器周期为

所示的石英晶体为

1 微秒,机器周期

12MHz

微秒如图

,因此,

1

1

示,当 P1.0 端口输出高电平,即 P1.0=1 时,

根据发光二极管的单向导电性可知,这时发光

二极管

使用

P1.0

L1 熄灭;当 P1.0 端口输出低电平,

SETB P1.0

=0 时,发光二极管

指令使 P1.0

L1

端口输出高电

亮;我们可以

平,使用

电平。

CLR P1.0 指令使 P1.0 端口输出低

C 语言源程序

#include

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

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

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

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;

}

if(P1_6==0)

JMP LOOP

DELAY: MOV R4,#20

D1: MOV R5,#248

DJNZ R5,$

图6 程序流程图

DJNZ R4,D1

DJNZ R3,DELAY

R RET

T ABLE: DB 0FEH,0FDH,0FBH,0F7H

{

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,@A+DPTR 的指令,根据累加

器的值再加上

值,就可以使程序计数器

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

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

unsigned char code

table[]={0xfe,0xfd,0xfb,0xf7,

0xef,0xdf,0xbf,0x7f,0xfe,0xfd,0x

fb,0xf7,0xef,0xdf,0xbf,0x7f,

0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0

xfd,0xfe,0x7f,0xbf,0xdf,0xef,

0xf7,0xfb,0xfd,0xfe,0x00,0xff,0

x00,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

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

五、动态数码显示技术

如图 9 所示,P0 端口接动态数码管的字形码笔

段,P2 端口接动态数码管的数位选择端,P1.7 接

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

当开关接低电平时,显示“HELLO”字样。

动态扫描方法:动态接口采用各数码管循环轮流

显示的方法,当循环显示频率较高时,利用人眼

的暂留特性,看不出闪烁显示现象,这种显示需

要一个接口完成字形码的输出(字形选择),另

一接口完成各数码管的轮流点亮(数位选择)。

在进行数码显示的时候,要对显示单元开辟 8

个显示缓冲区,每个显示缓冲区装有显示的不同

数据即可。对于显示的字形码数据我们采用查表

方法来完成。

汇编源程序

ORG 0000H

C 语言源程序

START: JB P1.7,DIR1

图9 单片机原理图

#include

MOV DPTR,#TABLE1

Unsigned char code

SJMP DIR

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

DIR1: MOV DPTR,#TABLE2

Unsigned char code

DIR: MOV R0,#00H

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

Unsigned char i;

MOV R1,#01H

Unsigned char a,b;

NEXT: MOV A,R0

Unsigned char temp;

MOVC A,@A+DPTR

MOV P0,A

void main(void)

MOV A,R1

{

MOV P2,A

while(1)

LCALL DAY

{

INC R0

temp=0xfe;

RL A

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

MOV R1,A

{

CJNE R1,#0DFH,NEXT

if(P1_7==1)

SJMP START

{

DAY: MOV R6,#4

P0=table1[i];

D1: MOV R7,#248

}

DJNZ R7,$

else

DJNZ R6,D1

{

RET

P0=table2[i];

图10 单片机原理图

TABLE1: DB 06H,5BH,4FH,66H,6DH

}

TABLE2: DB 78H,79H,38H,38H,3FH

P2=temp;

END

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”实现的。键盘处理程序的任务是:确定有无键按下,判断哪一个键按

下,键的功能是什么;

还要消除按键在闭合或断开时的抖动。两个并行口中,一个输出扫描码,使按键逐行动态接地,另一

个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该

键的

功能。

汇编源程序

KEYBUF EQU 30H

ORG 00H

START: MOV KEYBUF,#2

WAIT:

MOV P3,#0FFH

CLR P3.4

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY1

DELY10MS

LCALL

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY1

MOV A,P3

ANL A,#0FH

CJNE A,#0EH,NK1

MOV KEYBUF,#0

LJMP DK1

NK1: CJNE A,#0DH,NK2

MOV KEYBUF,#1

LJMP DK1

NK2: CJNE A,#0BH,NK3

MOV KEYBUF,#2

LJMP DK1

NK3: CJNE A,#07H,NK4

MOV KEYBUF,#3

LJMP DK1

NK4: NOP

DK1:

MOV A,KEYBUF

MOV DPTR,#TABLE

MOVC A,@A+DPTR

MOV P0,A

DK1A: MOV A,P3

ANL A,#0FH

XRL A,#0FH

JNZ DK1A

NOKEY1:

MOV P3,#0FFH

CLR P3.5

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY2

LCALL DELY10MS

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY2

MOV A,P3

ANL A,#0FH

A,#0EH,NK5

CJNE

MOV KEYBUF,#4

LJMP DK2

NK5: CJNE A,#0DH,NK6

MOV KEYBUF,#5

LJMP DK2

NK6: CJNE A,#0BH,NK7

MOV KEYBUF,#6

LJMP DK2

NK7: CJNE A,#07H,NK8

MOV KEYBUF,#7

LJMP DK2

NK8: NOP

DK2:

MOV A,KEYBUF

MOV DPTR,#TABLE

MOVC A,@A+DPTR

MOV P0,A

DK2A: MOV A,P3

ANL A,#0FH

XRL A,#0FH

JNZ DK2A

NOKEY2:

MOV P3,#0FFH

CLR P3.6

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY3

LCALL DELY10MS

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY3

MOV A,P3

ANL A,#0FH

CJNE A,#0EH,NK9

MOV KEYBUF,#8

LJMP DK3

NK9: CJNE A,#0DH,NK10

MOV KEYBUF,#9

LJMP DK3

NK10: CJNE A,#0BH,NK11

MOV KEYBUF,#10

LJMP DK3

NK11: CJNE A,#07H,NK12

MOV KEYBUF,#11

LJMP DK3

NK12: NOP

DK3:

MOV A,KEYBUF

MOV DPTR,#TABLE

MOVC A,@A+DPTR

MOV P0,A

DK3A: MOV A,P3

ANL A,#0FH

XRL A,#0FH

JNZ DK3A

NOKEY3:

MOV P3,#0FFH

CLR P3.7

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY4

LCALL DELY10MS

MOV A,P3

ANL A,#0FH

XRL A,#0FH

JZ NOKEY4

MOV A,P3

ANL A,#0FH

CJNE A,#0EH,NK13

MOV KEYBUF,#12

LJMP DK4

NK13: CJNE A,#0DH,NK14

MOV KEYBUF,#13

LJMP DK4

NK14: CJNE A,#0BH,NK15

MOV KEYBUF,#14

LJMP DK4

NK15: CJNE A,#07H,NK16

MOV KEYBUF,#15

LJMP DK4

NK16: NOP

DK4:

MOV A,KEYBUF

MOV DPTR,#TABLE

MOVC A,@A+DPTR

MOV P0,A

DK4A: MOV A,P3

ANL A,#0FH

XRL A,#0FH

JNZ DK4A

NOKEY4:

LJMP WAIT

DELY10MS:

MOV R6,#10

D1: MOV R7,#248

DJNZ R7,$

DJNZ R6,D1

RET

TABLE: DB

3FH,06H,5BH,4FH,66H,6DH,7

DH,07H

DB

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

H,71H

END

C 语言源程序

#INClude

unsigned char code

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

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

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

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

unsigned char temp;

unsigned char key;

unsigned char i,j;

void main(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)

{

case 0x0e:

key=7;

break;

case 0x0d:

key=8;

break;

case 0x0b:

key=9;

break;

case 0x07:

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)

{

case 0x0e:

key=4;

break;

case 0x0d:

key=5;

break;

case 0x0b:

key=6;

break;

case 0x07:

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)

{

case 0x0e:

key=1;

break;

case 0x0d:

key=2;

break;

case 0x0b:

key=3;

break;

case 0x07:

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)

{

case 0x0e:

key=0;

break;

case 0x0d:

key=13;

break;

case 0x0b:

key=14;

break;

case 0x07:

key=15;

break;

}

temp=P3;

P1_0=~P1_0;

P0=table[key];

temp=temp & 0x0f;

while(temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

}

}

}

}

}

七、按键识别方法

每按下一次开关 SP1,计数值加 1,通过AT89S51 单片机的 P1 端口的 P1.0 到 P1.3

显示出其二进制计数值。

*

程序设计方法:作为一个按键从没有按下到按下以及释放是一个完整的过程,也就是说,当我们按

下一个按键时,总希望某个命令只执行一次,而在按键按下的 过程中,不要有干扰进来,因为,在

按下的过程中,一旦有干扰过来,可能造成误触发过程,这并不是我们所想要的。因此在按键按下的

时候,要把我们手上的干扰信号以及按键的机械接触等干扰信号给滤除掉,一般情况下,我们可以采

用电容来滤除掉这些干扰信号,但实际上,会增加硬件成本及硬件电路的体积,这是我们不希望,总

得有个办法解决这个问题,因此我们可以采用软件滤波的方法去除这些干扰信号,一般情况下,一个

按键按下的时候,总是在按下的时刻存在着一定的干扰信号,按下之后就基本上进入了稳定的状态。

具体的一个按键从按下到释放的全过程的信号图如上图所示:从图中可以看出,我们在程序设计时,

从按键被识别按下之后,延时 5ms 以上,从而避开了干扰信号区域,我们再来检测一次,看按键是

否真得已经按下,若真得已经按下,这时肯定输出为低电平,若这时检测到的是高电平,证明刚才是

由于干扰信号引起的误触发,CPU 就认为是误触发信号而舍弃这次的按键识别过程。从而提高了系

统的可靠性。

由于要求每按下一次,命令被执行一次,直到下一次再按下的时候,再执行一次命令,因此从按

键被识别出来之后,我们就可以执行这次的命令,所以要有一个等待按键释放的过程,显然释放的过

程,就是使其恢复成高电平状态。

1. 汇编源程序

ORG 0000H

START: MOV R1,#00H ;

初始化 R1 为 0,表示从 0 开始计数

MOV A, R1

;

CPL A ;取反指令

MOV P1,A ;送出 P1 端口由发光二极管显示

REL: JB P3.7,REL ;判断 SP1 是否按下

LCALL DELAY10MS ;若按下,则延时 10ms 左右

JB P3.7,REL ;再判断 SP1 是否真得按下

INC R1 ;若确实按下,则进行按键处理,使

MOV A,R1 ;计数内容加 1,并送出 P1 端口由

CPL A ;发光二极管显示

MOV P1,A ;

JNB P3.7,$ ;等待 SP1 释放

SJMP REL ;继续对 K1 按键扫描

DELAY10MS: MOV R6,#20 ;延时 10ms 子程序

L1: MOV R7,#248

DJNZ R7,$

DJNZ R6,L1

RET

END

2. C 语言源程序

#include

unsigned char count;

void delay10ms(void)

{

unsigned char i,j;

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

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

}

void main(void)

{

while(1)

{

if(P3_7==0)

{

delay10ms();

if(P3_7==0)

{

count++;

if(count==16)

{

count=0;

}

P1=~count;

while(P3_7==0);

}

}

}

}

八、数字钟

(1. 开机时,显示 12:00:

00

整,每按一次加

2

的时间开始计时;

. P0.0/AD0

控制

1 秒;

“秒

”的调

整,每按一次加

3. P0.1/AD1

控制

1 分;

“分

”的调

(4. P0.2/AD2 控制“时”的调

整,每按一次加 1 个小时

MOV MINITE,#00H

6. 汇编源程序

SECOND EQU 30H

MINITE EQU 31H

HOUR EQU 32H

HOURK BIT P0.0

MINITEK BIT P0.1

SECONDK BIT P0.2

DISPBUF EQU 40H

DISPBIT EQU 48H

T2SCNTA EQU 49H

T2SCNTB EQU 4AH

TEMP EQU 4BH

ORG 00H

LJMP START

ORG 0BH

LJMP INT_T0

START: MOV SECOND,#00H

MOV MINITE,#00H

MOV HOUR,#12

MOV DISPBIT,#00H

MOV T2SCNTA,#00H

MOV T2SCNTB,#00H

MOV TEMP,#0FEH

LCALL DISP

MOV TMOD,#01H

MOV TH0,#(65536-2000) / 256

MOV TL0,#(65536-2000) MOD

256

SETB TR0

SETB ET0

SETB EA

WT: JB SECONDK,NK1

LCALL DELY10MS

JB SECONDK,NK1

INC SECOND

MOV A,SECOND

CJNE A,#60,NS60

MOV SECOND,#00H

NS60: LCALL DISP

JNB SECONDK,$

NK1: JB MINITEK,NK2

LCALL DELY10MS

JB MINITEK,NK2

INC MINITE

MOV A,MINITE

CJNE A,#60,NM60

NM60: LCALL DISP

JNB MINITEK,$

NK2: JB HOURK,NK3

LCALL DELY10MS

JB HOURK,NK3

INC HOUR

MOV A,HOUR

CJNE A,#24,NH24

MOV HOUR,#00H

NH24: LCALL DISP

JNB HOURK,$

NK3: LJMP WT

DELY10MS:

MOV R6,#10

D1: MOV R7,#248

DJNZ R7,$

DJNZ R6,D1

RET

DISP:

MOV A,#DISPBUF

ADD A,#8

DEC A

MOV R1,A

MOV A,HOUR

MOV B,#10

DIV AB

MOV @R1,A

DEC R1

MOV A,B

MOV @R1,A

DEC R1

MOV A,#10

MOV@R1,A

DEC R1

MOV A,MINITE

MOV B,#10

DIV AB

MOV @R1,A

DEC R1

MOV A,B

MOV @R1,A

DEC R1

MOV A,#10

MOV@R1,A

DEC R1

MOV

A,SECOND

MOV B,#10

DIV AB

MOV @R1,A

DEC R1

MOV A,B

MOV @R1,A

DEC R1

RET

INT_T0:

MOV TH0,#(65536-2000) / 256

MOV TL0,#(65536-2000) MOD

256

MOV A,#DISPBUF

ADD A,DISPBIT

MOV R0,A

MOV A,@R0

MOV DPTR,#TABLE

MOVC A,@A+DPTR

MOV P1,A

MOV A,DISPBIT

MOV DPTR,#TAB

MOVC A,@A+DPTR

MOV P3,A

INC DISPBIT

MOV A,DISPBIT

CJNE A,#08H,KNA

MOV DISPBIT,#00H

KNA: INC T2SCNTA

MOV A,T2SCNTA

CJNE

A,#100,DONE

MOV

T2SCNTA,#0

0H

INC

T2SCNTB

MOV

A,T2SCNTB

CJNE

A,#05H,DON

E

MOV

T2SCNTB,#0

0H

INC SECOND

MOV A,SECOND

CJNE A,#60,NEXT

MOV SECOND,#00H

INC MINITE

MOV A,MINITE

CJNE A,#60,NEXT

MOV MINITE,#00H

INC HOUR

MOV A,HOUR

CJNE A,#24,NEXT

MOV HOUR,#00H

NEXT: LCALL DISP

DONE: RETI

TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,

7DH,07H,7FH,6FH,40H

TAB: DB 0FEH,0FDH,0FBH,0F7H,0EFH,

0DFH,0BFH,07FH

END

7. C 语言源程序

#INClude

unsigned char code

dispcode[]={0x3f,0x06,0x5b,0x4

f,0x66,0x6d,0x7d,0x07,0x7f,0x6

f,0x77,0x7c,0x39,0x5e,0x79,0x7

1,0x00};

unsigned char

dispbitcode[]={0xfe,0xfd,0xfb,0

xf7,0xef,0xdf,0xbf,0x7f};

unsigned char

dispbuf[8]={0,0,16,0,0,16,0,0};

unsigned char dispbitcnt;

unsigned char second;

unsigned char minite;

unsigned char hour;

unsigned int tcnt;

unsigned char mstcnt;

unsigned char i,j;

void main(void)

{

TMOD=0x02;

TH0=0x06;

TL0=0x06;

TR0=1;

ET0=1;

EA=1;

while(1)

{

if(P0_0==0)

{

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

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

tcnt=0;

second++;

if(second==60)

{

second=0;

minite++;

if(minite==60)

{

minite=0;

hour++;

if(hour==24)

{

hour=0;

if(P0_0==0)

{

second++;

if(second==60)

{

second=0;

}

dispbuf[0]=second%10;

dispbuf[1]=second/10;

while(P0_0==0);

}

}

if(P0_1==0)

{

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

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

if(P0_1==0)

{

minite++;

if(minite==60)

{

minite=0;

}

dispbuf[3]=minite%10;

dispbuf[4]=minite/10;

while(P0_1==0);

}

}

if(P0_2==0)

{

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

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

}

}

}

dispbuf[0]=second%10;

dispbuf[1]=second/10;

dispbuf[3]=minite%10;

dispbuf[4]=minite/10;

dispbuf[6]=hour%10;

dispbuf[7]=hour/10;

}

}

}

if(P0_2==0)

{

hour++;

if(hour==24)

{

hour=0;

}

dispbuf[6]=hour%10;

dispbuf[7]=hour/10;

while(P0_2==0);

}

}

}

}

void t0(void) interrupt 1 using 0

{

mstcnt++;

if(mstcnt==8)

{

mstcnt=0;

P1=dispcode[dispbuf[dispbitcnt]

];

P3=dispbitcode[dispbitcnt];

dispbitcnt++;

if(dispbitcnt==8)

{

dispbitcnt=0;

}

}

tcnt++;

if(tcnt==4000)

{

九. ADC0809A/D 转换器基本应用技术

1 基本知识ADC0809 是带有 8 位 A/D 转换器、8 路多路开关以及微处理机兼容的控制逻辑的

CMOS 组件。它是逐次逼近式 A/D 转换器,可以和单片机

直接接口。

2 ADC0809 的内部逻辑结构图9-1

由上图可知,ADC0809 由一个 8 路模拟开关、一个地

址锁存与译码器、一个 A/D转换器和一个三态输出锁存器组

成。多路开关可选通 8 个模拟通道,允许 8 路模拟量分时

输入,共用 A/D 转换器进行转换。三态输出锁器用于锁存

A/D 转换完的数字量,当 OE 端为高电平时,才可以从三态

输出锁存器取走转换完的数据。

3 引脚结构

IN0-IN7:8 条模拟量输入通道

ADC0809 对输入模拟量要求:信号单极性,电压范围是

0-5V,若信号太小,必须进行放大;输入的模拟量在转换

过程中应该保持不变,如若模拟量变化太快,则需在输入前

增加采样保持电路。

地址输入和控制线:4 条

ALE 为地址锁存允许输入线,高电平有效。当 ALE 线为高电平时,地址锁存与译

码器将 A,B,C 三条地址线的地址信号进行锁存,经译码后被选中的通道的模拟

量进转换器进行转换。A,B 和 C 为地址输入线,用于选通 IN0-IN7 上的一路模

拟量输入。通道选择表如下表所示。

C B A 选择的通道

0 0 0 IN0

0 0 1 IN1

0 1 0 IN2

0 1 1 IN3

1 0 0 IN4

1 0 1 IN5

1 1 0 IN6

1 1 1 IN7

数字量输出及控制线:11 条

ST 为转换启动信号。当 ST 上跳沿时,所有内部寄存器清零;下跳沿时,开始进

行 A/D 转换;在转换期间,ST 应保持低电平。EOC 为转换结束信号。当 EOC 为高

电平时,表明转换结束;否则,表明正在进行 A/D 转换。OE 为输出允许信号,

用于控制三条输出锁存器向单片机输出转换得到的数据。OE=1,输出转换得到

的数据;OE=0,输出数据线呈高阻状态。D7-D0 为数字量输出线。

CLK 为时钟输入信号线。因 ADC0809 的内部没有时钟电路,所需时钟信号必须由

外界提供,通常使用频率为 500KHZ,VREF(+),VREF(-)为参考电压输入。

4 ADC0809 应用说明

(1). ADC0809 内部带有输出锁存器,可以与 AT89S51 单片机直接相连。

(2). 初始化时,使 ST 和 OE 信号全为低电平。

(3). 送要转换的哪一通道的地址到 A,B,C 端口上。

(4). 在 ST 端给出一个至少有 100ns 宽的正脉冲信号。

(5). 是否转换完毕,我们根据 EOC 信号来判断。

(6). 当 EOC 变为高电平时,这时给 OE 为高电平,转换的数据就输出给单片机了。

5 实验任务

如下图所示,从 ADC0809 的通道 IN3 输入 0-5V 之间的模拟量,通过 ADC0809

转换成数字量在数码管上以十进制形成显示出来。ADC0809 的 VREF 接+5V电压。

6 电路原理图

5. 系统板上硬件连线

(1). 把“单片机系统板”区域中的 P1 端口的 P1.0-P1.7 用 8 芯排线连接到“动态数码显示”区域

中的 A B C D E F G H 端口上,作为数码管的笔段驱动。

(2). 把“单片机系统板”区域中的 P2 端口的 P2.0-P2.7 用 8 芯排线连接到“动态数码显示”区域

中的 S1 S2 S3 S4 S5 S6 S7 S8 端口上,作为数码管的位段选择。

(3). 把“单片机系统板”区域中的 P0 端口的 P0.0-P0.7 用 8 芯排线连接到“模数转换模块”区域

中的 D0D1D2D3D4D5D6D7 端口上,A/D 转换完毕的数据输入到单片机的 P0 端口

(4). 把“模数转换模块”区域中的 VREF 端子用导线连接到“电源模块”区域中的 VCC 端子上;

(5). 把“模数转换模块”区域中的 A2A1A0 端子用导线连接到“单片机系统”区域中的 P3.4 P3.5

P3.6 端子上;

(6). 把“模数转换模块”区域中的 ST 端子用导线连接到“单片机系统”

区域中的 P3.0 端子上;

(7). 把“模数转换模块”区域中的 OE 端子用导线连接到“单片机系统”区域中的 P3.1 端子上;

(8).把“模数转换模块”区域中的 EOC 端子用导线连接到“单片机系统”区域中的 P3.2 端子上;

(9). 把“模数转换模块”区域中的 CLK 端子用导线连接到“分频模块”区域中的 /4 端子上;

(10). 把“分频模块”区域中的 CK IN 端子用导线连接到“单片机系统”区域中的 ALE 端子上;

(11). 把“模数转换模块”区域中的 IN3 端子用导线连接到“三路可调压模块”区域中的 VR1 端子

上;

6. 程序设计内容

(1). 进行 A/D 转换时,采用查询 EOC 的标志信号来检测 A/D 转换是否完毕,若完毕则把数

据通过 P0 端口读入,经过数据处理之后在数码管上显示。

(2). 进行 A/D 转换之前,要启动转换的方法:ABC=110 选择第三通道ST=0,ST=1,ST=0

产生启动转换的正脉冲信号

7. 汇编源程序

CH EQU 30H

DPCNT EQU 31H

DPBUF EQU 33H

GDATA EQU 32H

ST BIT P3.0

OE BIT P3.1

EOC BIT P3.2

ORG 00H

LJMP START

ORG 0BH

LJMP T0X

ORG 30H

START: MOV CH,#0BCH

MOV DPCNT,#00H

MOV R1,#DPCNT

MOV R7,#5

MOV A,#10

MOV R0,#DPBUF

LOP: MOV @R0,A

INC R0

DJNZ R7,LOP

MOV @R0,#00H

INC R0

MOV @R0,#00H

INC R0

MOV @R0,#00H

MOV TMOD,#01H

MOV TH0,#(65536-4000)/256

MOV TL0,#(65536-4000)

MOD 256

SETB TR0

SETB ET0

SETB EA

WT: CLR ST

SETB ST

CLR ST

WAIT: JNB EOC,WAIT

SETB OE

MOV GDATA,P0

CLR OE

MOV A,GDATA

MOV B,#100

DIV AB

MOV 33H,A

MOV A,B

MOV B,#10

DIV AB

MOV 34H,A

MOV 35H,B

SJMP WT

T0X: NOP

MOV TH0,#(65536-4000)/256

MOV TL0,#(65536-4000) MOD

256

MOV DPTR,#DPCD

MOV A,DPCNT

ADD A,#DPBUF

MOV R0,A

MOV A,@R0

MOVC A,@A+DPTR

MOV P1,A

MOV DPTR,#DPBT

MOV A,DPCNT

MOVC A,@A+DPTR

MOV P2,A

INC DPCNT

MOV A,DPCNT

CJNE A,#8,NEXT

MOV DPCNT,#00H

NEXT: RETI

DPCD: DB

3FH,06H,5BH,4FH,66H

DB

6DH,7DH,07H,7FH,6FH,00H

DPBT: DB

0FEH,0FDH,0FBH,0F7H

DB 0EFH,0DFH,0BFH,07FH

END

8. C 语言源程序

#INClude

unsigned char code

dispbitcode[]={0xfe,0xfd,0xfb,0

xf7,

0xef,0xdf,0xbf,0x7f};

unsigned char code

dispcode[]={0x3f,0x06,0x5b,0x4

f,0x66,

0x6d,0x7d,0x07,0x7f,0x6f,0x00

};

unsigned char

dispbuf[8]={10,10,10,10,10,0,0,

0};

unsigned char dispcount;

sbit ST=P3^0;

sbit OE=P3^1;

sbit EOC=P3^2;

unsigned char

channel=0xbc;//IN3

unsigned char getdata;

void main(void)

{

TMOD=0x01;

TH0=(65536-4000)/256;

TL0=(65536-4000)%256;

TR0=1;

ET0=1;

EA=1;

P3=channel;

while(1)

{

ST=0;

ST=1;

ST=0;

while(EOC==0);

OE=1;

getdata=P0;

OE=0;

dispbuf[2]=getdata/100;

getdata=getdata%10;

dispbuf[1]=getdata/10;

dispbuf[0]=getdata%10;

}

}

void t0(void) interrupt 1 using 0

{

TH0=(65536-4000)/256;

TL0=(65536-4000)%256;

P1=dispcode[dispbuf[dispcount]

];

P2=dispbitcode[dispcount];

dispcount++;

if(dispcount==8)

{

dispcount=0;

}

}

十、DS18B20 数字温度计使用

1.DS18B20 基本知识

DS18B20 数字温度计是 DALLAS 公司生产的 1-Wire,即单总线器件,具有线路简单,体积小的

特点。因此用它来组成一个测温系统,具有线路简单,在一根通信线,可以挂很多这样的数字温度计,

十分方便。

1、DS18B20 产品的特点

(1)、只要求一个端口即可实现通信。

(2)、在 DS18B20 中的每个器件上都有独一无二的序列号。

(3)、实际应用中不需要外部任何元器件即可实现测温。

(4)、测量温度范围在-55。C 到+125。C 之间。

(5)、数字温度计的分辨率用户可以从 9 位到 12 位选择。

(6)、内部有温度上、下限告警设置。

2、DS18B20 的引脚介绍

TO-92 封装的 DS18B20 的引脚排列见图 1,其引脚功能描述见表 1。(底视图)图 1

由于 DS18B20 采用的是 1-Wire 总线协议方式,即在一根数据线实现数据的双向传输,而对

AT89S51 单片机来说,硬件上并不支持单总线协议,因此,我们必须采用软件的方法来模拟单总线

的协议时序来完成对 DS18B20 芯片的访问。

由于 DS18B20 是在一根 I/O 线上读写数据,因此,对读写的数据位有着严格的时序要求。DS18B20

有严格的通信协议来保证各位数据传输的正确性和完整性。该协议定义了几种信号的时序:初始化时

序、读时序、写时序。所有时序都是将主机作为主设备,单总线器件作为从设备。而每一次命令和数

据的传输都是从主机主动启动写时序开始,如果要求单总线器件回送数据,在进行写命令后,主机需

启动读时序完成数据接收。数据和命令的传输都是低位在先。

DS18B20 的复位时序

DS18B20 的读时序对于 DS18B20

的读时序分为读 0 时序和读 1 时序两个过程。对于 DS18B20 的读时隙是从主机把单总线拉低之

后,在 15 秒之内就得释放单总线,以让 DS18B20 把数据传输到单总线上。DS18B20 在完成一个

读时序过程,至少需要 60us 才能

完成。

对于 DS18B20 的写时序仍然分为写 0 时序和写 1 时序两个过程。对于 DS18B20 写 0 时序和写

1 时序的要求不同,当要写 0 时序时,单总线要被拉低至少 60us,保证 DS18B20 能够在 15us 到

45us 之间能够正确地采样 IO 总线上的“0”电平,当要写 1 时序时,单总线被拉低之后,在 15us 之

内就得释放单总线。

4. 实验任务

用一片 DS18B20 构成测温系统,测量的温度精度达到 0.1 度,测量的温度的范围在-20 度到+100

度之间,用 8 位数码管显示出来。

5. 电路原理图

7. C 语言源程序

#INClude

#INClude

unsigned char code

displaybit[]={0xfe,0xfd,0xfb,0xf7,

0xef,0xdf,0xbf,0x7f};

unsigned char code

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

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

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

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

unsigned char code

dotcode[32]={0,3,6,9,12,16,19,22,

25,28,31,34,38,41,44,48,

50,53,56,59,63,66,69,72,

75,78,81,84,88,91,94,97};

unsigned char displaycount;

unsigned char

displaybuf[8]={16,16,16,16,16,16,16,16

};

unsigned char timecount;

unsigned char readdata[8];

{

sbit DQ=P3^7;

DQ=0;

bit sflag;

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

bit resetpulse(void)

DQ=1;

{

}

unsigned char i;

else

DQ=0;

{

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

DQ=0;

DQ=1;

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

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

DQ=1;

RETurn(DQ);

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

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

}

}

command=_cror_(command,1);

void writecommandtods18b20(unsigned char

}

command)

}

{

Unsigned char readdatafromds18b20(void)

unsigned char i;

unsigned char j;

Unsigned char i;

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

Unsigned char j;

{

Unsigned char temp;

if((command & 0x01)==0)

temp=0;

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

{

temp=_cror_(temp,1);

DQ=0;

_nop_();

_nop_();

DQ=1;

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

if(DQ==1)

{

temp=temp | 0x80;

}

else

{

temp=temp | 0x00;

}

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

}

RETurn(temp);

}

void main(void)

{

TMOD=0x01;

TH0=(65536-4000)/256;

TL0=(65536-4000)%256;

ET0=1;

EA=1;

while(resetpulse());

writecommandtods18b20(0xcc);

writecommandtods18b20(0x44);

TR0=1;

while(1)

{

;

}

}

void t0(void) interrupt 1 using 0

{

unsigned char x;

unsigned int result;

TH0=(65536-4000)/256;

TL0=(65536-4000)%256;

if(displaycount==2)

{

P0=displaycode[displaybuf[displaycount]] | 0x80;

}

else

{

P0=displaycode[displaybuf[displaycount]];

}

P2=displaybit[displaycount];

displaycount++;

if(displaycount==8)

{

displaycount=0;

}

timecount++;

if(timecount==150)

{

timecount=0;

while(resetpulse());

writecommandtods18b20(0xcc);

writecommandtods18b20(0xbe);

readdata[0]=readdatafromds18b20();

readdata[1]=readdatafromds18b20();

for(x=0;x<8;x++)

{

displaybuf[x]=16;

}

sflag=0;

if((readdata[1] & 0xf8)!=0x00)

{

sflag=1;

readdata[1]=~readdata[1];

readdata[0]=~readdata[0];

result=readdata[0]+1;

readdata[0]=result;

if(result>255)

{

readdata[1]++;

}

}

readdata[1]=readdata[1]<<4;

readdata[1]=readdata[1] & 0x70;

x=readdata[0];

x=x>>4;

x=x & 0x0f;

readdata[1]=readdata[1] | x;

x=2;

result=readdata[1];

while(result/10)

{

displaybuf[x]=result%10;

result=result/10;

x++;

}

displaybuf[x]=result;

if(sflag==1)

{

displaybuf[x+1]=17;

}

x=readdata[0] & 0x0f;

x=x<<1;

displaybuf[0]=(dotcode[x])%10;

displaybuf[1]=(dotcode[x])/10;

while(resetpulse());

writecommandtods18b20(0xcc);

writecommandtods18b20(0x44);

}

}

11、 4×4 键盘及 8 位数码管显示构成的电子密码锁

用 4×4 组成 0-9 数字键及确认键。

用 8 位数码管组成显示电路提示信息,当输入密码时,只显示“8.”,当密码位数输入完毕按下确认

键时,对输入的密码与设定的密码进行比较,若密码正确,则门开,此处用 LED 发光二极管亮一秒

钟做为提示,同时发出“叮咚”声;若密码不正确,禁止按键输入 3 秒,同时发出“嘀、嘀”

报警声;若在 3 秒之内仍有按键按下,则禁止按键输入 3 秒被重新禁止。

4. 程序设计内容

(1). 4×4 行列式键盘识别技术:有关这方面内容前面已经讨论过,这里不再重复。

(2). 8 位数码显示,初始化时,显示“P ”,接着输入最大 6 位数的密码,当密码输入完

后,按下确认键,进行密码比较,然后给出相应的信息。在输入密码过程中,显示器只显示“8.”。当

数字输入超过 6个时,给出报警信息。在密码输入过程中,若输入错误,可以利用“DEL”键删除刚才

输入的错误的数字。

(3). 4×4 行列式键盘的按键功能分布图如图 4.33.2 所示:

5. C 语言源程序

#include

unsigned char ps[]={1,2,3,4,5};

unsigned char code dispbit[]={0xfe,0xfd,0xfb,0xf7,

0xef,0xdf,0xbf,0x7f};

unsigned char code

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

0x6d,0x7d,0x07,0x7f,0x6f,

0x77,0x7c,0x39,0x5e,0x79,0x71,

0x00,0x40,0x73,0xff};

unsigned char

dispbuf[8]={18,16,16,16,16,16,16,16};

unsigned char dispcount;

unsigned char flashcount;

unsigned char temp;

unsigned char key;

unsigned char keycount;

unsigned char pslen=5;

unsigned char getps[6];

bit keyoverflag;

bit errorflag;

bit rightflag;

unsigned int second3;

unsigned int aa,bb;

unsigned int cc;

bit okflag;

bit alarmflag;

bit hibitflag;

unsigned char oka,okb;

void main(void)

{

unsigned char i,j;

TMOD=0x01;

TH0=(65536-500)/256;

TL0=(65536-500)%256;

TR0=1;

ET0=1;

EA=1;

while(1)

{

P3=0xff;

P3_4=0;

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

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

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

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

switch(temp)

{

case 0x0e:

key=7;

break;

case 0x0d:

key=8;

break;

case 0x0b:

key=9;

break;

case 0x07:

key=10;

break;

}

temp=P3;

P1_1=~P1_1;

if((key>=0) && (key<10))

{

if(keycount<6)

{

getps[keycount]=key;

dispbuf[keycount+2]=19;

}

keycount++;

if(keycount==6)

{

keycount=6;

}

else if(keycount>6)

{

keycount=6;

keyoverflag=1;//key overflow

}

}

else if(key==12)//delete key

{

if(keycount>0)

{

keycount--;

getps[keycount]=0;

dispbuf[keycount+2]=16;

}

else

{

keyoverflag=1;

}

}

else if(key==15)//enter key

{

if(keycount!=pslen)

{

errorflag=1;

rightflag=0;

second3=0;

}

else

{

for(i=0;i

{

if(getps[i]!=ps[i])

{

i=keycount;

errorflag=1;

rightflag=0;

second3=0;

goto a;

}

}

errorflag=0;

rightflag=1;

a: i=keycount;

}

}

temp=temp & 0x0f;

while(temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

}

keyoverflag=0;//?????????

}

}

P3=0xff;

P3_5=0;

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

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

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

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

switch(temp)

{

case 0x0e:

key=4;

break;

case 0x0d:

key=5;

break;

case 0x0b:

key=6;

break;

case 0x07:

key=11;

break;

}

temp=P3;

P1_1=~P1_1;

if((key>=0) && (key<10))

{

if(keycount<6)

{

getps[keycount]=key;

dispbuf[keycount+2]=19;

}

keycount++;

if(keycount==6)

{

keycount=6;

}

else if(keycount>6)

{

keycount=6;

keyoverflag=1;//key overflow

}

}

else if(key==12)//delete key

{

if(keycount>0)

{

keycount--;

getps[keycount]=0;

dispbuf[keycount+2]=16;

}

else

{

keyoverflag=1;

}

}

else if(key==15)//enter key

{

if(keycount!=pslen)

{

errorflag=1;

rightflag=0;

second3=0;

}

else

{

for(i=0;i

{

if(getps[i]!=ps[i])

{

i=keycount;

errorflag=1;

rightflag=0;

second3=0;

goto a4;

}

}

errorflag=0;

rightflag=1;

a4: i=keycount;

}

}

temp=temp & 0x0f;

while(temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

}

keyoverflag=0;//?????????

}

}

P3=0xff;

P3_6=0;

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

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

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

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

switch(temp)

{

case 0x0e:

key=1;

break;

case 0x0d:

key=2;

break;

case 0x0b:

key=3;

break;

case 0x07:

key=12;

break;

}

temp=P3;

P1_1=~P1_1;

if((key>=0) && (key<10))

{

if(keycount<6)

{

getps[keycount]=key;

dispbuf[keycount+2]=19;

}

keycount++;

if(keycount==6)

{

keycount=6;

}

else if(keycount>6)

{

keycount=6;

keyoverflag=1;//key overflow

}

}

else if(key==12)//delete key

{

if(keycount>0)

{

keycount--;

getps[keycount]=0;

dispbuf[keycount+2]=16;

}

else

{

keyoverflag=1;

}

}

else if(key==15)//enter key

{

if(keycount!=pslen)

{

errorflag=1;

rightflag=0;

second3=0;

}

else

{

for(i=0;i

{

if(getps[i]!=ps[i])

{

i=keycount;

errorflag=1;

rightflag=0;

second3=0;

goto a3;

}

}

errorflag=0;

rightflag=1;

a3: i=keycount;

}

}

temp=temp & 0x0f;

while(temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

}

keyoverflag=0;//?????????

}

}

P3=0xff;

P3_7=0;

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

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

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

temp=P3;

temp=temp & 0x0f;

if (temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

switch(temp)

{

case 0x0e:

key=0;

break;

case 0x0d:

key=13;

break;

case 0x0b;

key=14;

break;

case 0x07:

key=15;

break;

}

temp=P3;

P1_1=~P1_1;

if((key>=0) && (key<10))

{

if(keycount<6)

{

getps[keycount]=key;

dispbuf[keycount+2]=19;

}

keycount++;

if(keycount==6)

{

keycount=6;

}

else if(keycount>6)

{

keycount=6;

keyoverflag=1;//key overflow

}

}

else if(key==12)//delete key

{

if(keycount>0)

{

keycount--;

getps[keycount]=0;

dispbuf[keycount+2]=16;

}

else

{

keyoverflag=1;

}

}

else if(key==15)//enter key

{

if(keycount!=pslen)

{

errorflag=1;

rightflag=0;

second3=0;

}

else

{

for(i=0;i

{

if(getps[i]!=ps[i])

{

i=keycount;

errorflag=1;

rightflag=0;

second3=0;

goto a2;

}

}

errorflag=0;

rightflag=1;

a2: i=keycount;

}

}

temp=temp & 0x0f;

while(temp!=0x0f)

{

temp=P3;

temp=temp & 0x0f;

}

keyoverflag=0;//?????????

}

}

}

}

void t0(void) interrupt 1 using 0

{

TH0=(65536-500)/256;

TL0=(65536-500)%256;

flashcount++;

if(flashcount==8)

{

flashcount=0;

P0=dispcode[dispbuf[dispcount]];

P2=dispbit[dispcount];

dispcount++;

if(dispcount==8)

{

dispcount=0;

}

}

if((errorflag==1) && (rightflag==0))

{

bb++;

if(bb==800)

{

bb=0;

alarmflag=~alarmflag;

}

if(alarmflag==1)//sound alarm signal

{

P1_7=~P1_7;

}

aa++;

if(aa==800)//light alarm signal

{

aa=0;

P1_0=~P1_0;

}

second3++;

if(second3==6400)

{

second3=0;

errorflag=0;

rightflag=0;

alarmflag=0;

bb=0;

aa=0;

}

}

else if((errorflag==0) && (rightflag==1))

{

P1_0=0;

cc++;

if(cc<1000)

{

okflag=1;

}

else if(cc<2000)

{

okflag=0;

}

else

{

errorflag=0;

rightflag=0;

P1_7=1;

cc=0;

oka=0;

okb=0;

okflag=0;

P1_0=1;

}

if(okflag==1)

{

oka++;

if(oka==2)

{

oka=0;

P1_7=~P1_7;

}

}

else

{

okb++;

if(okb==3)

{

okb=0;

P1_7=~P1_7;

}

}

}

if(keyoverflag==1)

{

P1_7=~P1_7;

}

}

12. 6 位数显频率计数器

1. 实验任务

利用 AT89S51 单片机的 T0、T1 的定时计数器功能,来完成对输入的信号进行频率计数,计数的

频率结果通过 8 位动态数码管显示出来。要求能够对0-250KHZ 的信号频率进行准确计数,计数误

差不超过±1HZ。

3. 程序设计内容

(1). 定时/计数器 T0 和 T1 的工作方式设置,由图可知,T0 是工作在计数状态下,对输入的

频率信号进行计数,但对工作在计数状态下的 T0,最大计数值为 f

OSC

/24,由于 f

OSC

=12MHz,因

此:T0 的最大计数频率为250KHz。对于频率的概念就是在一秒只数脉冲的个数,即为频率值。

所以 T1 工作在定时状态下,每定时 1 秒中到,就停止 T0 的计数,而从 T0 的计数单元中读取计

数的数值,然后进行数据处理。送到数码管显示出来。

(2). T1 工作在定时状态下,最大定时时间为 65ms,达不到 1 秒的定时,所

以采用定时 50ms,共定时 20 次,即可完成 1 秒的定时功能。

. C 语言源程序

#include

unsigned char code

dispbit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f

};

unsigned char code

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

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

unsigned char dispbuf[8]={0,0,0,0,0,0,10,10};

unsigned char temp[8];

unsigned char dispcount;

unsigned char T0count;

unsigned char timecount;

bit flag;

unsigned long x;

void main(void)

{

unsigned char i;

TMOD=0x15;

TH0=0;

TL0=0;

TH1=(65536-4000)/256;

TL1=(65536-4000)%256;

TR1=1;

TR0=1;

ET0=1;

ET1=1;

EA=1;

while(1)

{

if(flag==1)

{

flag=0;

x=T0count*65536+TH0*256+TL0;

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

{

temp[i]=0;

}

i=0;

while(x/10)

{

temp[i]=x%10;

x=x/10;

i++;

}

temp[i]=x;

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

{

dispbuf[i]=temp[i];

}

timecount=0;

T0count=0;

TH0=0;

TL0=0;

TR0=1;

}

}

}

void t0(void) interrupt 1 using 0

{

T0count++;

}

void t1(void) interrupt 3 using 0

{

TH1=(65536-4000)/256;

TL1=(65536-4000)%256;

timecount++;

if(timecount==250)

{

TR0=0;

timecount=0;

flag=1;

}

P0=dispcode[dispbuf[dispcount]];

P2=dispbit[dispcount];

dispcount++;

if(dispcount==8)

{

dispcount=0;

}

}

13、LCD驱动程序

根据原理图设计LCD1602液晶显示电路的驱动程

序:

/********************************

FILE NAME: LCD1602.c

CHIP TYPE: AT89C51

CLOCK FREQUENCY: 12MHZ

IDE: VSMStudio

COMPILER: IAR for 8051

TIME: 7/ 2012

********************************/

#include "ioAT89C51.h"

#include "intrinsics.h"

// Define P3 pins

#define DATA_BUS (P0);数据总线P0

#define RS (P2_bit.P2_0);P2.0

#define RW (P2_bit.P2_1) ;P2.1

#define E (P2_bit.P2_2);P2.2

// Define new types

typedef unsigned char uchar;无符号字符型

typedef unsigned int uint;无符号整型

// Function Prototypes

void check_busy(void);检查忙信号

void write_command(uchar com);写指令

void write_data(uchar data);写数据

void LCD_init(void);LCD初始化

void string(uchar ad ,uchar *s);

void lcd_test(void);测试函数

void delay(uint);延时函数

void main(void);主函数

{ LCD_init();

while(1)

{ string(0x80,"Have a nice day!");

string(0xC0," Proteus VSM");

delay(100);

write_command(0x01);

delay(100);

}

}

/*******************************************

LCD1602 Driver mapped as IO peripheral

*******************************************/

// Delay,延时

void delay(uint j)

{ uchar i = 60;

for(; j>0; j--)

{ while(--i);

i = 59;

while(--i);

i = 60;

}

}

// Test the Busy bit,测试忙位BF

void check_busy(void)

{ do

{ DATA_BUS = 0xff;

E = 0;

RS = 0;

RW = 1;

E = 1;高电平

__no_operation();

} while(DATA_BUS & 0x80);

E = 0;

}

// Write a command,写指令

void write_command(uchar com)

{ check_busy();

E = 0;

RS = 0;

RW = 0;

DATA_BUS = com;

E = 1;

__no_operation();

E = 0;下降沿

delay(1);

}

// Write Data,写数据

void write_data(uchar data)

{ check_busy();

E = 0;

RS = 1;

RW = 0;

DATA_BUS = data;

E = 1;

__no_operation();

E = 0;

delay(1);

}

// Initialize LCD controller

void LCD_init(void)

{ write_command(0x38); // 8-bits, 2 lines, 7x5 dots

write_command(0x0C); // no cursor, no blink,

//enable display

write_command(0x06); // auto-INCrement on

write_command(0x01); // clear screen

delay(1);

}

// Display a string

void string(uchar ad, uchar *s)

{ write_command(ad);

while(*s>0)

{ write_data(*s++);

delay(100);

}

}

; LCD Display Driver Demo.

; Timing code assumes 1.2MHz Clock

;LCD Registers addresses

LCD_CMD_WR EQU 00H

LCD_DATA_WR EQU 01H

LCD_BUSY_RD EQU 02H

LCD_DATA_RD EQU 03H

;LCD Commands

LCD_CLS EQU 01

LCD_HOME EQU 02

LCD_SETMODE EQU 04

LCD_SETVISIBLE EQU 08

LCD_SHIFT EQU 16

LCD_SETFUNCTION EQU 32

LCD_SETCGADDR EQU 64

LCD_SETDDADDR EQU 128

;Reset vector

ORG 0000h

JMP start;//Start of the program

ORG 0100h

string1a:DB ' !! A M A Z I N G !! '

DB 0

string1b:DB '!! A M A Z I N G !! '

DB 0

string2:DB ' A '

DB 0

string3:DB ' driven by a virtual '

DB 0

string4:DB ' 8051 processor!'

DB 0

start:MOV A,#038h; 8位2行,5*7点阵

CALL wrcmd

loop: MOV A,#LCD_SETVISIBLE+6 ;Make the

display & blink visible:开显示,光标不闪烁

CALL wrcmd

MOV R7,#2

loop2: MOV DPTR,#string1a

CALL wrstr

MOV DPTR,#200

CALL wtms

MOV A,#LCD_CLS ;Clear screen

CALL wrcmd

MOV DPTR,#string1b

CALL wrstr

MOV DPTR,#200

CALL wtms

MOV A, #LCD_CLS ;Clear screen

CALL wrcmd

DJNZ R7,loop2

MOV DPTR,#string1a

CALL wrstr

MOV DPTR,#400

CALL wtms

MOV A,#LCD_SETDDADDR+64

CALL wrcmd

MOV DPTR,#string2

CALL wrslow

MOV DPTR,#200

CALL wtms

MOV A,#LCD_CLS ;Clear screen

CALL wrcmd

MOV DPTR,#string3

CALL wrslow

MOV A,#LCD_SETDDADDR+64

CALL wrcmd

MOV DPTR,#string4

CALL wrslow

MOV A,#LCD_SETVISIBLE+7 ;Show the

//blink cursor as well.

CALL wrcmd

MOV DPTR,#2000

CALL wtms

MOV A,#LCD_CLS ;Clear screen

CALL wrcmd

JMP loop

;Sub routine to write null terminated string at DPTR

in program ram.

wrstr: MOV R0,#LCD_DATA_WR

wrstr1: CLR A

MOVC A,@A+DPTR

JZ wrstr2

MOVX @R0,A

CALL wtbusy

INC DPTR

;Wait for number of milliseconds in DPTR

wtms: XRL DPL,#0FFh ;Can't do DEC

DPTR, so do the loop by forming 2's complement

PUSH DPL

PUSH DPH

POP DPH

POP DPL

JMP wrstr1

wrstr2: RET

;Sub routine to write null terminated string at DPTR

in program ram. Slowly

wrslow: MOV R0,#LCD_DATA_WR

wrslw1: CLR A

MOVc A,@A+DPTR

JZ wrslw2

MOVX @R0,A

CALL wtbusy

INC DPTR

PUSH DPL

PUSH DPH

MOV DPTR,#100

CALL wtms

POP DPH

POP DPL

JMP wrslw1

wrslw2: RET

;Sub routine to write command:

wrcmd: MOV R0,#LCD_CMD_WR

MOVX @R0,A

JMP wtbusy

;Sub routine to write character:

wrchar: MOV R0,#LCD_DATA_WR

MOVX @R0,A

;Subroutine to wait for busy clear

wtbusy: MOV R1,#LCD_BUSY_RD

MOVX A,@r1

JB ACC.7,wtbusy

RET

;Wait for number of seconds in A

wtsec: PUSH ACC

CALL wtms

POP ACC

DEC A

JNZ wtsec

RET

XRL DPH,#0FFh;and INCrementing instead.

INC DPTR

wtms1:MOV TL0,#09Ch ;100 ticks before

overflow = 1ms at 1.2MHz Clock

MOV TH0,#0FFh

MOV TMOD,#1 ;Timer 0 mode 1

SETB TCON.4 ;Timer 0 runs

wtms2: JNB TCON.5,wtms2

CLR TCON.4 ;Timer 0 stops

CLR TCON.5

INC DPTR

MOV A,DPL

ORL A,DPH

JNZ wtms1

RET

END

Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1730681408)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1730681408)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1730747579)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1730747579)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1730769963)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1730769963)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1730790735)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1730790735)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1730810435)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1730810435)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1730810744)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1730810744)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1730811204)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1730811204)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1730843292)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1730843292)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1730850453)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1730850453)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1730851983)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1730851983)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1730870058)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1730870058)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1730904272)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1730904272)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1734801897)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1734801897)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1734830888)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1734830888)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1734942058)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1734942058)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1735074667)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1735074667)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1737972445)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1737972445)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1741147359)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1741147359)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1741179628)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1741179628)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1095, humandate(1743990284)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(26))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
Error[2]: Trying to access array offset on value of type int, File: /www/wwwroot/www.usbmi.com/xiunophp/xiunophp.min.php, Line: 54
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 1096, humandate(1743990284)
File: /www/wwwroot/www.usbmi.com/tmp/model_thread.func.php, Line: 662, well_thread_format(array(27))
File: /www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm, Line: 249, well_thread_find_asc(array(20) , 20)
File: /www/wwwroot/www.usbmi.com/tmp/route_read.php, Line: 204, include(/www/wwwroot/www.usbmi.com/tmp/view_template_d8_htm_read.htm)
File: /www/wwwroot/www.usbmi.com/tmp/index.inc.php, Line: 129, include(/www/wwwroot/www.usbmi.com/tmp/route_read.php)
File: /www/wwwroot/www.usbmi.com/index.php, Line: 29, include(/www/wwwroot/www.usbmi.com/tmp/index.inc.php)
发布评论

评论列表 (0)

  1. 暂无评论