‘壹’ 求用单片机设计一个秒表AT89C51
;汇编程序如下。
;使用T0定时方式1,每隔50ms中断一次,用于修改时间及显示
;使用外部中断0、1,用于控制启动和清零
;========================================================
ORG0000H
AJMPMAIN
ORG0003H
AJMPX0_INT
ORG000BH
AJMPT0_INT
ORG0013H
AJMPX1_INT
MAIN:
MOVTMOD,#01H;T0定时方式1
MOVTH0,#(65536-50000)/256;50ms@12MHz
MOVTL0,#(65536-50000)MOD256;
SETBTR0
SETBET0;开启定时中断
SETBEX0
SETBEX1
SETBEA;定时器初始化结束,下面循环显示即可
MOVR1,#99H;0~99计数.
MOVR7,#1;50ms计数.
MOVP0,#0C0H
MOVP2,#0C0H
LOOP:
SJMPLOOP
;-----------------------------------------------------------
DELAY:;延时子程序.
AA4:MOVR4,#0
DJNZR4,$
DJNZR4,$
RET
;-----------------------------------------------------------
X0_INT:;启动/停止
CPLF0
RETI
;-----------------------------------------------------------
X1_INT:;清零
MOVR1,#0
MOVP0,#0C0H
MOVP2,#0C0H
RETI
;-----------------------------------------------------------
T0_INT:;50ms中断执行一次.
MOVTL0,#(65536-50000)MOD256;
MOVTH0,#(65536-50000)/256;50ms@12MHz
DJNZR7,T0_END;中断不到20次.
MOVR7,#20
JNBF0,T0_END
MOVA,R1
ADDA,#1
DAA
MOVR1,A
ANLA,#0FH
MOVDPTR,#TAB
MOVCA,@A+DPTR;查出段码
MOVP2,A
MOVA,R1
SWAPA
ANLA,#0FH
MOVCA,@A+DPTR;查出段码
MOVP0,A;显示十位数.
T0_END:
RETI
;-----------------------------------------------------------
TAB:
DB0c0H,0f9H,0a4H,0b0H,99H,92H,82H,0f8H,80H,90H
;===========================================================
;仿真截图如下:
‘贰’ 基于51单片机的电子秒表设计
这个是 数码管显示计数器程序。稍加更改 既满足要求
要精确定时,必须使用自装载方式。这里我们使用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 <reg52.h> //包括一个52标准内核的头文件
#include<intrins.h>
/****************************声明函数*****************************/
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的值送到数码管显示
}
}
/*****************************************************************/
‘叁’ 51单片机制作一个秒表
//功能:0~99秒的简易秒表设计,两个静态数码管,定时器采用中断方式
#include"reg51.h"
#define uchar unsigned char
#define uint unsigned int
uchar count=0;//对50ms定时时间进行计数
uchar miao=0; //秒计数器
//函数名:timer_1()
//函数功能:定时器T1的中断函数,T1在工作方式1下每50秒产生中断,执行该中断函数
//形式参数:无
//返回值:无
void timer_1() interrupt 3 //T1的中断类型号为3
{
TH1=(65536-50000)/256; //重新设置T1计数初值高8位
TL1=(65536-50000)%256; //重新设置T1计数初值低8位
count++; //50ms计数器加1
if(count==20) //1s时间到
{
count=0; //50ms计数器清0
miao++; //秒计数器加1
if(miao==100)miao=0; //miao计数到100,则从0开始计数
}
}
bit b=0;
void int_0() interrupt 0
{
if(b == 0){TR1 = 0;b = 1;}
else
{
b = 0;
TR1 = 1;
}
}
void int_1() interrupt 2
{
miao=0;
count = 0;
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
TR1=1;
}
//函数名:disp
//函数功能:将i的值显示在两个静态连接的数码管上
//形式参数:i,取值范围0~99
//返回值:无
void disp(uchar i)
{
uchar led[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//定义0~9显示码,共阳极数码管
P1=led[i/10]; //显示i高位
P2=led[i%10]; //显示i地位
}
void main()
{
TMOD=0x10;//设置T1在工作方式1
TH1=(65536-50000)/256;//设置T1计数初值高8位,定时时间50ms
TL1=(65536-50000)%256;//设置T1计数初值低8位
ET1=1;//开放T1中断允许
EX0 = 1;
IT0 = 1;
EX1 = 1;
IT1=1;
EA=1;//开放总中断允许
TR1=1;//启动T1开始计时
while(1)
{
disp(miao);//显示秒计数器值
}
}
‘肆’ 单片机秒表设计
用AT89C51设计一个2位的LED数码显示作为“秒表”,这应该是一个仿真题,可用两位一体的共阴数码管,用定时器T0定时,得到1秒计时。
‘伍’ 鍗旷墖链哄备綍鐢6涓锷ㄦ佹暟镰佺¤捐′竴涓绉掕〃
鍗旷墖链虹敤6涓锷ㄦ佹暟镰佺¤捐′竴涓绉掕〃瀹氭椂鍣ㄧ紪鍐欑浉搴旇佹眰瀹氭椂镞堕棿銆傚埯濮嫔寲涓哄伐浣沧ā寮1瀹氭椂鍣ㄥ畾镞舵椂闂翠负20ms锛屼篃灏辨槸瀹氭椂鍣ㄦ疮婧㈠嚭涓娆$殑镞堕棿涓20ms锛屽垯婧㈠嚭50娆″嵆涓1绉挜挓銆傞氲繃镆ヨ㈡孩鍑烘爣蹇椾綅镄勫煎嵆鍙銆
‘陆’ 单片机课程设计 秒表设计
#include<reg51.h>#include<stdio.h>#define dat P0
#define uchar unsigned char#define uint unsigned int
sbit seg1 = P2^0;sbit seg2 = P2^1;sbit seg3 = P2^2;sbit seg4 = P2^3;
uchar a,b,c,d;uint timeout=0,us=0,ms=0;uchar code table[]={0xC0,0xF9,0xA4,0xB0, 0x99,0x92,0x82,0xF8, 0x80,0x90,0x88,0x83, 0xC6,0xA1,0x86,0x8E}; //共阳
/*uchar code table[]={0x3f,0x06,0x5b,0x4f, //0~3 0x66,0x6d,0x7d,0x07, //4~7 0x7f,0x6f,0x77,0x7c, //8~b 0x39,0x5e,0x79,0x71}; //共阴 */
void delay(uint z){while(z--);}
void display(){ dat = table[a]; seg1 = 0; delay(1000); seg1 = 1; dat = 0xff; dat = table[b]-0x80; seg2 = 0; delay(1000); seg2 = 1; dat = 0xff; dat = table[c]; seg3 = 0; delay(1000); seg3 = 1; dat = 0xff; dat = table[d]; seg4 = 0; delay(1000); seg4 = 1; dat = 0xff; }
void InitTimer0(void){ TMOD = 0x01; TH0 = (65536-10000)/256; TL0 = (65536-10000)%256; EA = 1; ET0 = 1; TR0 = 1;}
void main(void){ InitTimer0(); while(1) { d = us%10; c = us/10; b = ms%10; a = ms/10; display(); }}
void Timer0Interrupt(void) interrupt 1{ TH0 = (65536-10000)/256; TL0 = (65536-10000)%256; //add your code here! timeout++; if(timeout==1) { timeout = 0; us++; if(us==100) { us = 0; ms++; { if(ms==100) { ms = 0; } } } }}