at89s51.c
来自「35个51单片机使用的c51程序」· C语言 代码 · 共 3,134 行 · 第 1/5 页
C
3,134 行
t02s=0;
flag=~flag;
}
if(flag==0)
{
P1_0=~P1_0;
}
}
19 nK…J
U O *―
' GSP1¨AT89S51)({*ó n~ P1.00^ Eg LM386¨4 E E 9[
`~
U *dC )5-
4.19.1
U 2*4fi9- %E3
~ ^)(2ˇ4 ,XP1.00^ *ü―4 E yM Ne + ,XSPK IN0^ ×
~ üM Ne + ,XSPK OUT0^ y 8 5 16 ,X[`×
~ ^)(2ˇ4 ,XP3.7/RD0^ *ü―4 E y( 0 K, ,XSP10^ ×
U /: @í@― "
~ *ü)(rn /AuD5. 程序框图
开 始
计数单元清零
TH0,TL0装入初值
开中断,并允许T0中断
秒按键识别成功否
SECOND加1
SECOND=60吗
SECOND=0
AT89S51单片机实验及实践教程 www.supermcu.com
- 93 -
显示数据处理
分按键识别成功否
MINITE加1
MINITE=60吗
MINITE=0
显示数据处理
时按键识别成功否
HOUR加1
HOUR=24吗
HOUR=0
显示数据处理
T0中断入口
通过查表方式显示数据
数码位选加1
位选数值=8吗
位选数值=0
秒计数=500吗
秒计数加1
秒计数=0
SECOND加1
AT89S51单片机实验及实践教程 www.supermcu.com
- 94 -
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
SECOND=60吗
SECOND=0,并MINITE加1
MINITE=60吗
MINITE=0,并HOUR加1
HOUR=24吗
HOUR=0
显示数据处理
中断返回
AT89S51单片机实验及实践教程 www.supermcu.com
- 95 -
JNB SECONDK,$
NK1: JB MINITEK,NK2
LCALL DELY10MS
JB MINITEK,NK2
INC MINITE
MOV A,MINITE
CJNE A,#60,NM60
MOV MINITE,#00H
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
AT89S51单片机实验及实践教程 www.supermcu.com
- 96 -
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,#00H
INC T2SCNTB
MOV A,T2SCNTB
CJNE A,#05H,DONE
MOV T2SCNTB,#00H
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,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};
unsigned char dispbitcode[]={0xfe,0xfd,0xfb,0xf7,
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;
AT89S51单片机实验及实践教程 www.supermcu.com
- 97 -
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--);
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--);
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;
}
AT89S51单片机实验及实践教程 www.supermcu.com
- 98 -
}
tcnt++;
if(tcnt==4000)
{
tcnt=0;
second++;
if(second==60)
{
second=0;
minite++;
if(minite==60)
{
minite=0;
hour++;
if(hour==24)
{
hour=0;
}
}
}
dispbuf[0]=second%10;
dispbuf[1]=second/10;
dispbuf[3]=minite%10;
dispbuf[4]=minite/10;
dispbuf[6]=hour%10;
dispbuf[7]=hour/10;
}
}
21. 拉幕式数码显示技术
1. 实验任务
用AT89S51单片机的P0.0/AD0-P0.7/AD7端口接数码管的a-h端,8位数码管的S1-S8通过74LS138
译码器的Y0-Y7来控制选通每个数码管的位选端.AT 8 9 S 5 1单片机的P1.0-P1.2控制74LS138的A,
B,C端子.在8位数码管上从右向左循环显示"12345678".能够比较平滑地看到拉幕的效果.
2. 电路原理图
AT89S51I /'? ZZZVXSHUPFXFRP
- 99 -
4.21.1
U 2*4fi9- %E3
~1 ^)(2ˇ4 ,XP0.0/AD0 P0.7/AD7*ü88 f4 E y| D- / ,Xa
h0^ ×
~2 ^ A - + ,XY0 Y7*ü88 f4 E y| D- / ,XS1 S80^
×
~3 ^)(2ˇ4 ,XP1.0 P1.20^ *ü3―4 E y A - + ,XA^B^
C0^ ×
4 /: @í@― "
~1 | D- /T×V)E > | ¨+b 6 A} D- 1u/¨?!8¨ U/8
!,XDB¨ NO4 E A}D- 1u EB#/!^ ¨à ! D- 1u/,X K¨ 4zü
1ms4msK¨¨ Z-A !7.B/¨ NO! Lh1ms¨k D- 1u~5àE
K¨ G *ü)(,Xn /AuD D- /,X í¨ U /) Es8 /4 ¨! /4 > /,XAE
àDBG^~
U /: u-
/ c
AT89S51单片机实验及实践教程 www.supermcu.com
- 100 -
中断服务程序框图
开 始
显示缓冲区初始化
必要参数初始化
T0初始化,TH0,TL0装入初值
T0工作并开中断
等待中断
T0中断入口
通过查表方式,获得显示代码送入P0
位选数据送P1
位选数据=8吗
位选数据加1
位选数据=0
CNT加1
0.4秒定时到了吗
AT89S51单片机实验及实践教程 www.supermcu.com
- 101 -
图4.21.2
6. 汇编源程序
DISPBUF EQU 30H
DISPCNT EQU 38H
DISPBIT EQU 39H
T1CNTA EQU 3AH
T1CNTB EQU 3BH
CNT EQU 3CH
ORG 00H
LJMP START
ORG 0BH
LJMP INT_T0
START: MOV DISPCNT,#8
MOV A,#10
MOV R1,#DISPBUF
LP: MOV @R1,A
INC R1
DJNZ DISPCNT,LP
MOV DISPBIT,#00H
MOV T1CNTA,#00H
MOV T1CNTB,#00H
MOV CNT,#00H
MOV TMOD,#01H
MOV TH0,#(65536-1000) / 256
MOV TL0,#(65536-1000) MOD 256
SETB TR0
SETB ET0
SETB EA
SJMP $
INT_T0:
MOV TH0,#(65536-1000) / 256
MOV TL0,#(65536-1000) MOD 256
MOV A,DISPBIT
ADD A,#DISPBUF
MOV R0,A
MOV A,@R0
MOV DPTR,#TABLE
CNT=9吗
CNT=0
根据CNT来决定显示几位数据
中断返回
AT89S51单片机实验及实践教程 www.supermcu.com
- 102 -
MOVC A,@A+DPTR
MOV P0,A
MOV A,P1
ANL A,#0F8H
ADD A,DISPBIT
MOV P1,A
INC DISPBIT
MOV A,DISPBIT
CJNE A,#08H,NEXT
MOV DISPBIT,#00H
NEXT: INC T1CNTA
MOV A,T1CNTA
CJNE A,#50,LL1
MOV T1CNTA,#00H
INC T1CNTB
MOV A,T1CNTB
CJNE A,#8,LL1
MOV T1CNTB,#00H
INC CNT
MOV A,CNT
CJNE A,#9,LLX
MOV CNT,#00H
MOV A,CNT
LLX: CJNE A,#01H,NEX1
MOV 30H,#8
LL1: LJMP DONE
NEX1: CJNE A,#02H,NEX2
MOV 31H,#8
MOV 30H,#8
LJMP DONE
NEX2: CJNE A,#03H,NEX3
MOV 32H,#8
MOV 31H,#8
MOV 30H,#8
LJMP DONE
NEX3: CJNE A,#04H,NEX4
MOV 33H,#8
MOV 32H,#8
MOV 31H,#8
MOV 30H,#8
LJMP DONE
NEX4: CJNE A,#05H,NEX5
MOV 34H,#8
MOV 33H,#8
MOV 32H,#8
MOV 31H,#8
MOV 30H,#8
LJMP DONE
NEX5: CJNE A,#06H,NEX6
MOV 35H,#8
MOV 34H,#8
MOV 33H,#8
MOV 32H,#8
MOV 31H,#8
MOV 30H,#8
LJMP DONE
NEX6: CJNE A,#07H,NEX7
MOV 36H,#8
AT89S51单片机实验及实践教程 www.supermcu.com
- 103 -
MOV 35H,#8
MOV 34H,#8
MOV 33H,#8
MOV 32H,#8
MOV 31H,#8
MOV 30H,#8
LJMP DONE
NEX7: CJNE A,#08H,NEX8
MOV 37H,#8
MOV 36H,#8
MOV 35H,#8
MOV 34H,#8
MOV 33H,#8
MOV 32H,#8
MOV 31H,#8
MOV 30H,#8
LJMP DONE
NEX8: CJNE A,#00H,DONE
MOV 37H,#10
MOV 36H,#10
MOV 35H,#10
MOV 34H,#10
MOV 33H,#10
MOV 32H,#10
MOV 31H,#10
MOV 30H,#10
LL: LJMP DONE
DONE: RETI
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,00H
END
7. C语言源程序
#include
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};
unsigned char dispbitcode[]={0xf8,0xf9,0xfa,0xfb,
0xfc,0xfd,0xfe,0xff};
unsigned char dispbuf[8]={16,16,16,16,16,16,16,16};
unsigned char dispbitcnt;
unsigned int t02scnt;
unsigned char t5mscnt;
unsigned char u;
unsigned char i;
void main(void)
{
TMOD=0x02;
TH0=0x06;
TL0=0x06;
TR0=1;
ET0=1;
EA=1;
while(1);
}
void t0(void) interrupt 1 using 0
{
AT89S51单片机实验及实践教程 www.supermcu.com
- 104 -
t5mscnt++;
if(t5mscnt==4)
{
t5mscnt=0;
P0=dispcode[dispbuf[dispbitcnt]];
P1=dispbitcode[dispbitcnt];
dispbitcnt++;
if(dispbitcnt==8)
{
dispbitcnt=0;
}
}
t02scnt++;
if(t02scnt==1600)
{
t02scnt=0;
u++;
if(u==9)
{
u=0;
}
for(i=0;i<8;i++)
{
dispbuf[i]=16;
}
for(i=0;i K, ,XC1
C4R1 R40^ ×
4 , G/ cY
~1 4X4> K, A ×
~2 M ${*ó,X "'×
OjM $A AEà,XM L4 ,X¨5à! M L h-AEà,XNe)[¨E ^ *üAEà,XNe)[
,X4 ¨G^X U,XM $Z¨'' b)(9{*óAEà,XNe)[M2 ¨ ^ *ü)(
,Xn /AuDM 0oe Ne)[~HZ 1TB- ~T M 0oe Ne)[~HZ 1TB- ~T
"1DO 262 63628 # 4 FA# 740 64860
#1DO# 277 63731 5 SO 784 64898
AT89S51单片机实验及实践教程 www.supermcu.com
- 106 -
低2 RE 294 63835 # 5 SO# 831 64934
#2 RE# 311 63928 中 6 LA 880 64968
低 3 M 330 64021 # 6 932 64994
低 4 FA 349 64103 中 7 SI 988 65030
# 4 FA# 370 64185 高 1 DO 1046 65058
低 5 SO 392 64260 # 1 DO# 1109 65085
# 5 SO# 415 64331 高 2 RE 1175 65110
低 6 LA 440 64400 # 2 RE# 1245 65134
# 6 466 64463 高 3 M 1318 65157
低 7 SI 494 64524 高 4 FA 1397 65178
中 1 DO 523 64580 # 4 FA# 1480 65198
# 1 DO# 554 64633 高 5 SO 1568 65217
中 2 RE 587 64684 # 5 SO# 1661 65235
# 2 RE# 622 64732 高 6 LA 1760 65252
中 3 M 659 64777 # 6 1865 65268
中 4 FA 698 64820 高 7 SI 1967 65283
下面我们要为这个音符建立一个表格,有助于单片机通过查表的方式来获得相应的数据
低音0-19之间,中音在20-39之间,高音在40-59之间
TABLE: DW 0,63628,63835,64021,64103,64260,64400,64524,0,0
DW 0,63731,63928,0,64185,64331,64463,0,0,0
DW 0,64580,64684,64777,64820,64898,64968,65030,0,0
DW 0,64633,64732,0,64860,64934,64994,0,0,0
DW 0,65058,65110,65157,65178,65217,65252,65283,0,0
DW 0,65085,65134,0,65198,65235,65268,0,0,0
DW 0
2,音乐的音拍,一个节拍为单位(C调)
曲调值 DELAY 曲调值 DELAY
调4/4 125ms 调4/4 62ms
调3/4 187ms 调3/4 94ms
调2/4 250ms 调2/4 125ms
对于不同的曲调我们也可以用单片机的另外一个定时/计数器来完成.
下面就用AT89S51单片机产生一首"生日快乐"歌曲来说明单片机如何产生的.
在这个程序中用到了两个定时/计数器来完成的.其中T0用来产生音符频率,T1用来产生音拍.
5. 程序框图
AT89S51单片机实验及实践教程 www.supermcu.com
- 107 -
图4.22.2
6. 汇编源程序
KEYBUF EQU 30H
STH0 EQU 31H
STL0 EQU 32H
TEMP EQU 33H
ORG 00H
LJMP START
ORG 0BH
LJMP INT_T0
START: MOV TMOD,#01H
SETB ET0
SETB EA
T0中断入口
重装TH0,TL0初值
P1.0取反
中断返回
开 始
行列式键盘按键按下成功否
识别按键功能
根据按键功能,装入
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?