1.要求:使用两个数码管,并从01 开始,每隔1s 数码管加1,一直显示到60.
C 语言:
#include <>
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6;
// 段选,申明锁存器
1 的锁存端
sbit wela=P2^7;
// 位选,申明锁存器
2 的锁存端
uchar code table[]=
// 共阴极数码管编码
{ 0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f } ;
void delayms(uint xms)
// 延时
xms
{ uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void display(uchar,uchar);
uchar num,num1=1,shi,ge=1;
// 赋初值
void main()
{TMOD=0x10;
// 设定时器
1 方式
1 定时
50ms,循环
20 次实现
1s
延时
TH1=(65536-50000)/256;
// 装初值
TL1=(65536-50000)%256;
EA=1;
ET1=1;
TR1=1;
while(1)
// 开总中断
// 开定时器1 中断
// 启动定时器1
// 在这里不停的对数码管动态扫描等待中断发生
{display(shi,ge);
}
}
void display(uchar shi,uchar ge)
// 显示子函数
{dula=1;
P0=table[shi];
// 送段选数据
dula=0;
P0=0xff;
wela=1;
P0=0xfe;
// 消影,送位选数据前关闭所有显示,防止打开位选锁存时
// 原来段选数据通过位选锁存器造成混乱
// 送位选数据
wela=0;
delayms(5);
// 延时
dula=1;
P0=table[ge];
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delayms(5);
}
void T1_time()interrupt
{
3
TH1=(65536-50000)/256;
// 重装初值
TL1=(65536-50000)%256;
num++;
if(num==20)
//20
次循环,
50ms
20 次 =1s
{ num=0;
// 到
20 次以后清零重新再计数
20 次
num1++;
// 数码管显示加
1
if(num1==61)
// 数码管显示到
60 后又从
01 开始
num1=1;
shi=num1/10;
// 把两位数分离后分别送数码管显示十位和个位
ge=num1%10;
}
}
汇编:ORG 0000H
AJMPMain
ORG000BH// 定时器 0 的中断入口地址
AJMPZD
ORG 0030H
Main:MOVR0,#1// 初始值从01 开始
MOVR4,#20// 循环 20 次来实现1s 延时
MOVDPTR,#TABLE// 表头地址送给DPTR
MOVTMOD,#01H// 定时器 0 方式 1 定时 50ms
MOVTH0,#03CH// 赋初值
MOVTL0,#0B0H
SETBEA// 开总中断
SETBET0// 开定时器0 中断
SETBTR0// 启动定时器0 中断
LP1:MOV A,R0
MOV B,#10
DIVAB//A 为整数 B 为余数
MOVCA,@A+DPTR
SETB// 数码管显示十位
MOVP0,#0FEH
CLR
SETB
MOV P0,A
CLR
ACALLDELAY5MS
MOV A,B// 数码管显示个位
MOVCA,@A+DPTR
SETB
MOV P0,#0FDH
CLR
SETB
MOV P0,A
CLR
ACALLDELAY5MS
AJMPLP1
ZD:MOV TH0,#03CH
MOV TL0,#0B0H
DJNZR4,LP2
MOV R4,#20
INC R0
CJNER0,#61,LP2
MOV R0,#01
LP2: RETI
DELAY5MS: MOVR6,#5
LOP1: MOVR5,#250
LOP2: NOP
// 重新赋初值
// 是否循环20 次
// 中断返回
// 延时
5ms
NOP
DJNZ R5,LOP2
DJN