#include<reg51h>
#define uschar unsigned char
#define usint unsigned int
uschar code table[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};//0-f
uschar code tab[]={0xfe,0xfd,0xfb};//1-3
sbit wele=P2^7;
sbit dule=P2^6;
usint t;
uschar a,b,c,i,j,n;
void init();
void display(usint x);
void delay(uschar z);
void main()
{
init();
while(1)
{
a=t/100;
b=t%100/10;
c=t%10;
wele=1;
P0=tab[0];
wele=0;
dule=1;
P0=table[a];//10s
delay(5);
wele=1;
P0=tab[1];
wele=0;
dule=1;
P0=table[b];//1s
delay(5);
wele=1;
P0=tab[2];
wele=0;
dule=1;
P0=table[c];//100ms
delay(5);
}
}
void init()
{
a=0;
b=0;
c=0;
n=0;
t=0;
TMOD=0x01;
TH0=(65535-46080)/256;
TL0=(65535-46080)%256;//110592M 50ms
EA=1;
ET0=1;
TR0=1;
}
void timer0() interrupt 1
{
TH0=(65535-46080)/256;
TL0=(65535-46080)%256;
n++;
if(n==2)
{
n=0;
t++;
if(t==600)
t=0;
}
}
void delay(uschar z)
{
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
这个是 数码管显示计数器程序。稍加更改 既满足要求
要精确定时,必须使用自装载方式。这里我们使用T2定时器,让它工作在16bit自动装载方式,这时,有另一个位置专门装着16位预装载值,T2溢出时,预装载值立即被置入。这就保证了精确定时。
但是,即使是16位定时器,最长的溢出时间也就几十毫秒,要定时一秒,就需要一个变量来保存溢出的次数,积累到了多少次之后,才执行一次 *** 作。这样就可以累加到1秒或者更长的时间才做一次 *** 作了。
T2定时器有个特殊的地方,它进入中断后,需要自己清除溢出标记,而51的其他定时器是自动清除的。请参考51单片机相关书籍。
如果使用T2定时器实现1秒精确定时
下面我们就来计算:
仿真器的晶振是22118400HZ,每秒钟可以执行1843200个机器周期。而T2每次溢出最多65536个机器周期。我们尽量应该让溢出中断的次数最少,这样对主程序的干扰也就最小。
选择每秒中断24次,每次溢出1843200/24=76800个机器周期,超出65536,无效。
选择每秒中断30次,每次溢出1843200/30=61440个机器周期
选择每秒中断32次,每次溢出1843200/32=57600个机器周期
选择每秒中断36次,每次溢出1843200/36=51200个机器周期
选择每秒中断40次,每次溢出1843200/40=46080个机器周期
从上面可以看到我们可以选择方式有很多,但是最佳的是每秒中断30次,每次溢出61440个机器周期。也就是赋定时器T2初值65536-61440=4096,换成十六进制就是0x1000。
从上面的计算也可以看出晶振2118400Hz的好处,它可以整除的倍数多,要准确定时非常方便。更常见的应用是在串口波特率上,使用22118400HZ可以输出最多准确的标准波特率。
如果是其他频率的晶振 按照上面的方法计算即可
/
#include <reg52h> //包括一个52标准内核的头文件
#include<intrinsh>
/声明函数/
void x8led(unsigned long ddd);
void delay882us(void);
/定义IO/
sbit P20=P2^0;
sbit P21=P2^1;
sbit S16=P3^0;
sbit S15=P3^1;
sbit S14=P3^2;
sbit P10=P1^0;
sbit P11=P1^1;
sbit P12=P1^2;
sbit P13=P1^3;
sbit P14=P1^4;
sbit P15=P1^5;
sbit P16=P1^6;
sbit P17=P1^7;
bit f=0;//位变量
/定时器2中断/
timer2() interrupt 5
{
static unsigned char t;
TF2=0;
t++;
if(t==30) //T2的预置值0x1000,溢出30次就是1秒钟,晶振22118400HZ 这里晶振频率不同则会有所不同
{
t=0;
f=1;//每次长时间的溢出,就置一个标记,以便主程序处理
}
}
/数码管扫描/
void x8led(unsigned long ddd)
{
unsigned char q,r=0;
unsigned char l[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x7f};
//0-9的字段码
unsigned char xx[8]={0,0,0,0,0,0,0,0};
unsigned char y[8]={0x80,0x40,0x20,0x10,0x8,0x4,0x2,0x1};
xx[0]=ddd%10;
xx[2]=ddd/10%10;
xx[1]=ddd/100%10;
xx[3]=ddd/1000%10;
xx[4]=ddd/10000%10;
xx[6]=ddd/100000%10;
xx[5]=ddd/1000000%10;
xx[7]=ddd/10000000; //求出八位数,分别放在八个变量中
for(q=0;q<8;) //循环扫描
{
q++;
r++;
if(r==8)r=0;
P1=y[r];
P21=1;
delay882us();
P21=0;
P20=1;
P1=l[xx[r]];
delay882us();
P1=0xff;
P20=0;
}
}
/延时882us/
void delay882us(void)
{
unsigned char i;
for(i=0;i<255;i++)
{
_nop_();
}
}
/主程序/
void main(void)
{
unsigned long a=0;
RCAP2H =0x10; //赋T2的预置值0x1000,溢出30次就是1秒钟
RCAP2L =0x00;
TR2=1; //启动定时器
ET2=1; //打开定时器2中断
EA=1; //打开总中断
while(1)
{
if(f)//发现标记进入处理
{
f=0;//清除标记
a++;
if(a>99999999)a=0;
}
x8led(a);//将a的值送到数码管显示
}
}
//
; P0段选 ,P20个位位选,P21十位位选 。共阳数码管 16M晶振。
STRT EQU P25
STP EQU P26
CLRR EQU P27
ORG 00H
AJMP MAIN
ORG 0BH
AJMP T0INT
ORG 30H
MAIN: MOV R0,#20
MOV TMOD,#01H
MOV TH0,#3CH
MOV TL0,#0B0H
MOV DPTR,#TABLE
SETB EA
SETB ET0
k1: LCALL DISP
JB STRT,K2
LCALL DISP
JNB STRT,$-3
AJMP START
k2: JB STP,K3
LCALL DISP
JNB STP,STOP
K3: JB CLRR,K1
LCALL DISP
JNB CLRR,CLEAR
AJMP K3
START: SETB TR0
AJMP K1
STOP: CLR TR0
AJMP K2
CLEAR: CLR TR0
MOV 40H,#0
AJMP K1
T0INT: MOV TH0,#3CH
MOV TL0,#0B0H
DJNZ R0,RTI
MOV R0,#20
MOV A,40H
CJNE A,#99,ADD1
MOV 40H,#00H
CLR TR0
AJMP RTI
ADD1: ADD A,#01H
MOV 40H,A
RTI: RETI
DISP: MOV A,40H
MOV B,#10
DIV AB ;//当前值除以10
MOV 20H,A ;//得出的商送给十位
MOV 21H,B ;//得出的余数送给个位
CLR P20
SETB P21
MOV A,20H ;//十位显示
MOVC A,@A+DPTR
MOV P0,A
LCALL DELAY
CLR P21
SETB P20
MOV A,21H ; //个位显示
MOVC A,@A+DPTR
MOV P0,A
RET
DELAY: ;误差 0us
MOV R6,#01H
DL0:
MOV R5,#61H
DJNZ R5,$
DJNZ R6,DL0
RET
TABLE: DB 0C0H,0F9H,0A4H,0B0H,99H ;//共阳极0-9显示代码
DB 92H,82H,0F8H,80H,90H
END
若使用的是vivo手机,打开手机“闹钟时钟”软件--秒表--点击“”即可开始计时,点击“‖”停止计时会暂停,再点击“”会继续累计计时;计时过程中可点击计次,依次记录当前计次时间;计时停止后可点击复位重置。
1
“分分:秒秒”计数器设计
我们要实现“分分:秒秒”显示的电子秒表,需要设计计数频率为1Hz
的
计数器。因为“分分:秒秒”的结构对应有4个十进制数字(个位的秒,十位的
秒,个位的分,十位的分),如果采用统一计数再分别求出“分分:秒秒”
对应
的4个十进制数字进行译码显示,则求解对应的4个十进制数字的过程难于用硬
件实现。在此,我们将每个显示的值分别进行计数,即分别针对个位的秒、十位
的秒、个位的分、十位的分设计对应的计数器,其中个位的秒计数频率为1Hz,
其从0到9计数,当从9回到0时,向前进一位,使得十位的秒进行计数加1。
35
十位的秒从0到5计数,当从5回到0时,向前进一位,使得个位的分进行计数
加1。个位的分从0到9计数,当从9回到0
时,向前进一位,使得十位的分进
行计数加1。十位的分则从0
到5计数,计数到5时,又回到0。
2
扫描显示技术
因为4位数码管的段控制输入是复用的,要分别显示不同的计数数值,需要
使用动态扫描显示技术,其电路结构如图61
所示。首先,以扫描显示的频率进
行2比特宽的模4计数,然后由其值从4个数码管的待显示值输入中选择对应的
一个经译码后连接到公共的段控制输入端,同时将计数值经2到4译码后输出到
对应数码管位的公共端,点亮对应的数码管。虽然各数码管位是轮流显示,每个
数码管位上的数字是断续的显示,只要扫描的频率够快,由于人眼的视觉残余效
应,就可以看到各数码管位上稳定的数字显示值。这和我们使用的电视、显示器
的显示原理是一样的。参考液晶显示器的刷新频率,经验证,在每秒钟扫描60
帧的时候,各数码管位上即能得到稳定的数字显示,此时,对应计数时钟的等效
频率为240Hz。我们可以参考实验四的图47,再做一个等效分频计数器,通过
产生的后级时钟使能信号将20MHz的时钟等效分频到240Hz。
图
61
扫描显示电路结构
3
冒号点的处理
数码管中间的时间分隔冒号点(对应为左边第2个数码管位的DP点)每秒
钟闪烁一次,其频率为1Hz,只需要输出1Hz,占空比为50%的周期信号即可。
其他数码管位的点号不需要显示,对应的DP
点输出低电平无效信号即可。这4
个信号
所示的显示切换计数值进行4
选1
选择后接到数码管上公共的
DP控制端。
在实验四中,我们为了得到1Hz的主功能计数频率,前面利用precnt
进行了等效分频计数,其一个完整的计数周期即为1s,对应产生的使能信号en
频率即为1Hz,但我们在此不能直接使用en
的信号,因为其占空比只有
1/20000000,肉眼无法看到其闪烁的效果。为得到占空比为50%的1Hz信号,我
们可以通过对precnt
的计数值进行比较得出,只需要在precnt
计数周期内一半的
时间输出1,一半的时间输出0
即可,例如,当precnt>25'd9999999
时输出0,
否则输出1,此时即可得到占空比为50%的1Hz信号。
4
总体设计
总体设计只需要将时钟电路、复位电路、按键电路、数码管电路等组合起来,
综合使用时钟使能的同步设计技术、按键处理技术、扫描显示技术、“分分:秒
秒”计数器设计技术及冒号点的处理技术即可。
秒表的设计程序
用89C51,外接晶振,复位电路,二个数码管,二个按键,做一个电子秒表,具体要求为用按键起停电子表,可用按键设计倒计时时间(如10S,20S,60S),并启动倒计时功能。能用按键选择以上两功能之一。
三、程序代码:
A_BIT EQU 20H ;数码管个位数存放内存位置
B_BIT EQU 21H ;数码管十位数存放内存位置
TEMP EQU 22H ;计数器数值存放内存位置 ;开机初始化
MOV P3,#0FFH;对P3口初始化,设置为高电平,用于按键输入
MOV P0,#0FFH;使显示时间数码管熄灭
CLR F0
CLR F1
MOV DPTR,#NUMTAB ;指定查表启始地址
;等待按键输入
;根据按键的输入判断执行什么功能;按键1按下则执行功能1
MOV P3,#0FFH;对P3口初始化,设置为高电平,用于按键输入
MOV P0,#0FFH;使显示时间数码管熄灭
START:JB P36,START1;循环判断开始按钮K1是否按下
ACALL DELAY10;延时10毫秒触点消抖
JB P36,START;如果是干扰就返回
JNB P36,$;等待按键松开
LJMP GN1 ;按键2按下则执行功能2START1: JB P37,START;循环判断开始按钮K2是否按下
ACALL DELAY10;延时10毫秒触点消抖
JB P37,START1;如果是干扰就返回
JNB P37,$
LJMP GN2;数码管显示秒表时间的程序
GN1: ;先初始化
S1:MOV A,#0
MOV TEMP,A
GOON1: MOV R2,#2
JS1: MOV R3,#250
TIME1: MOV A,TEMP ;将TEMP中的十六进制数转换成10进制
MOV B,#10 ;10进制/10=10进制
DIV AB
MOV B_BIT,A ;十位在A
MOV A_BIT,B ;个位在B LCALL DPLOP1 ;插入一段判断定时过程中是否有按键输入的程序段
C1: JB P36,B1
ACALL DELAY10;延时10毫秒消抖
JB P36,C1
JNB P36,$;等待按键松开
CPL F0
ZT1: ; MOV P3,#0FFH;对P3口初始化,设置为高电平,用于按键输入
JB P36,$;循环判断开始按钮K1是否按下
ACALL DELAY10;延时10毫秒触点消抖
JB P36,ZT1;如果是干扰就返回
JNB P36,$;等待按键松开
LCALL DPLOP1
B1: JB P37,LOOP1
ACALL DELAY10;延时10毫秒消抖
JB P37,B1
JNB P37,$;等待按键松开
AJMP OVERLOOP1: DJNZ R3,TIME1 ;2毫秒循环执行250次,时间约05秒
DJNZ R2,JS1 ;循环执行2次,时间为1 秒钟INC TEMP;满一秒钟对时间加1
MOV A,TEMP
CLR C
SUBB A,#60
JNZ GOON1;判断TEMP的数值是否为60不为60循环
ACALL OVER
RET
GN2: MOV A,#14H ; 设定倒计时的时间20S
MOV TEMP,A;数码管显示倒计时时间的程序
;初始化
MOV P3,#0FFH;对P3口初始化,设置为高电平,用于按键输入
MOV P0,#14H;使显示时间为设定的倒计时时间 GOON2: MOV R2,#2
JS2: MOV R3,#250
TIME2: MOV A,TEMP ;将TEMP中的十六进制数转换成10进制
MOV B,#10 ;10进制/10=10进制
DIV AB
MOV B_BIT,A ;十位在A
MOV A_BIT,B ;个位在B MOV DPTR,#NUMTAB ;指定查表启始地址
DPLOP2: MOV A,A_BIT ;取个位数
MOVC A,@A+DPTR ;查个位数的7段代码
MOV P0,A ;送出个位的7段代码
CLR P25 ;开个位显示
ACALL DELY1;显示1毫秒
SETB P25;关闭个位显示,防止鬼影
MOV A,B_BIT ;取十位数
MOVC A,@A+DPTR ;查十位数的7段代码
MOV P0,A ;送出十位的7段代码
CLR P26 ;开十位显示
ACALL DELY1;显示1毫秒
SETB P26;关闭十位显示,防止鬼影 ;插入一段判断定时过程中是否有按键输入的程序段
C2: JB P36,B2
ACALL DELAY10;延时10毫秒消抖
JB P36,C2
JNB P36,$;等待按键松开
ZT2: MOV P3,#0FFH;对P3口初始化,设置为高电平,用于按键输入
JB P36,$;循环判断开始按钮K1是否按下
ACALL DELAY10;延时10毫秒触点消抖
JB P36,ZT2;如果是干扰就返回
JNB P36,$;等待按键松开
B2: JB P37,LOOP2
ACALL DELAY10;延时10毫秒消抖
JB P37,B1
JNB P37,$;等待按键松开
AJMP OVERLOOP2: DJNZ R3,TIME2 ;2毫秒循环执行250次,时间约05秒
DJNZ R2,JS2 ;循环执行2次,时间为1 秒钟DEC TEMP;满一秒钟对时间减1
MOV A,TEMP
JNZ GOON2;判断TEMP的数值是否为0不为0循环
ACALL OVER
RET
;结束定时
OVER: AJMP START;退到开机初始化状态;1毫秒延时子程序
DELY1: MOV R4,#2
D1:MOV R5,#248
DJNZ R5,$
DJNZ R4,D1
RET;10毫秒延时子程序
DELAY10: MOV R4,#20
D2:MOV R5,#248
DJNZ R5,$
DJNZ R4,D2
RET;实验板上的两位一体的数码管0~9各数字的显示代码
NUMTAB: DB 40H,79H,24H,30H,19H,12H,02H,78H,00H,10H
DPLOP1: MOV A,A_BIT ;取个位数
MOVC A,@A+DPTR ;查个位数的7段代码
MOV P0,A ;送出个位的7段代码
CLR P25 ;开个位显示
ACALL DELY1;显示1毫秒
SETB P25;关闭个位显示,防止鬼影
MOV A,B_BIT ;取十位数
MOVC A,@A+DPTR ;查十位数的7段代码
MOV P0,A ;送出十位的7段代码
CLR P26 ;开十位显示
ACALL DELY1;显示1毫秒
SETB P26;关闭十位显示,防止鬼影
RET
END
做了一个4位数码管的,可以计时到9分599秒
KEYVAL EQU 30H
DAT EQU 33H
SCANLED EQU 39H
CLK EQU 77H
SEC EQU 78H
SEC1 EQU 79H
SEC2 EQU 7AH
DOT BIT 00H
ORG 0000H
LJMP MAIN
ORG 0003H
LJMP EXTINT0
ORG 000BH
LJMP T0ISR ;50ms定时
ORG 001BH
LJMP T1ISR ;扫描显示
ORG 0030H
MAIN:
MOV SP,#5FH
MOV TMOD,#11H
MOV TH0,#03CH
MOV TL0,#0B0H
MOV TH1,#0ECH
MOV TL1,#078H
MOV KEYVAL,#2
MOV 33H,#10H
MOV 34H,#10H
MOV 35H,#10H
MOV 36H,#10H
MOV CLK,#0
SETB IT0
SETB EX0
CLR TR0
CLR ET0
MOV R2,#0
SETB TR1
SETB ET1
SETB EA
LOOP:
MOV A,KEYVAL
LOOP1:
JNZ LOOP2 ;启动
SETB TR0
SETB ET0
SJMP LOOP
LOOP2:
DEC A
JNZ LOOP3 ;暂停
CLR TR0
CLR ET0
SJMP LOOP
LOOP3:
DEC A
JNZ LOOP ;清零
MOV 36H,#0
MOV 35H,#0
MOV 34H,#0
MOV 33H,#0
SJMP LOOP
EXTINT0:
PUSH ACC
INC KEYVAL
MOV A,KEYVAL
CJNE A,#3,EXT00
EXT00:
JC EXT01
MOV KEYVAL,#0
EXT01:
POP ACC
RETI
T0ISR:
PUSH ACC
CLR TR0
MOV TH0,#3CH
MOV TL0,#0B0H
SETB TR0
INC CLK
MOV A,CLK
CJNE A,#2,T0ISRE
MOV CLK,#0
INC 36H
MOV A,36H
CJNE A,#10,T0ISRE
MOV 36H,#0
INC 35H
MOV A,35H
CJNE A,#10,T0ISRE
MOV 35H,#0
INC 34H
MOV A,34H
CJNE A,#6,T0ISRE
MOV 34H,#0
INC 33H
MOV A,33H
CJNE A,#10,T0ISRE
MOV 33H,#0
T0ISRE:
POP ACC
RETI
T1ISR:
PUSH ACC
CLR TR1
MOV TH1,#0ECH
MOV TL1,#78H
SETB TR1
MOV DPTR,#LEDTAB
T100:
MOV R0,#DAT
MOV A,SCANLED
ADD A,R0
MOV R0,A
MOV A,SCANLED
JNZ T101
MOV P2,#01H
SETB DOT
SJMP T1DIS
T101:
DEC A
JNZ T102
MOV P2,#02H
CLR DOT
SJMP T1DIS
T102:
DEC A
JNZ T103
MOV P2,#04H
SETB DOT
SJMP T1DIS
T103:
MOV P2,#08H
CLR DOT
T1DIS:
MOV A,@R0
MOVC A,@A+DPTR
JNB DOT,T1DIS1
ORL A,#01H
T1DIS1:
CPL A
MOV P0,A
INC SCANLED
MOV A,SCANLED
CJNE A,#4,T1END
MOV SCANLED,#0
T1END:
POP ACC
RETI
LEDTAB: DB 0FCH ;"0" 00H
DB 60H ;"1" 01H
DB 0DAH ;"2" 02H
DB 0F2H ;"3" 03H
DB 66H ;"4" 04H
DB 0B6H ;"5" 05H
DB 0BEH ;"6" 06H
DB 0E0H ;"7" 07H
DB 0FEH ;"8" 08H
DB 0F6H ;"9" 09H
DB 0EEH ;"A" 0AH
DB 3EH ;"B" 0BH
DB 9CH ;"C" 0CH
DB 7AH ;"D" 0DH
DB 9EH ;"E" 0EH
DB 8EH ;"F" 0FH
DB 00H ;" " 10H
END
以上就是关于跪求各位大神给我写一个51单片机电子秒表的程序全部的内容,包括:跪求各位大神给我写一个51单片机电子秒表的程序、基于51单片机的电子秒表设计、单片机程序设计,设计一个电子秒表,用2个共阳数码管,60秒清零等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)