跪求各位大神给我写一个51单片机电子秒表的程序

跪求各位大神给我写一个51单片机电子秒表的程序,第1张

#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秒清零等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9344127.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存