51单片机电子跑表
要求
利用单片机为核心设计一个多功能电子表,具有电时钟和跑表功能。用做时钟时,在显示器上显示时、分、秒,用做跑表时,显示范围00时00分00秒-23时59分59秒并具有跑表启动和跑表复位功能键。当按下启动按钮跑表开始计时,按下停止按停止计时,当按下复位按钮跑表回零。
\
元器件清单
STC89C52芯片一块;
7.3728MHz晶振一个;
30pF瓷片电容两个,10uF电解电容一个;
8位排阻一个,10Ω电阻两个;
按键六个;
\
硬件电路设计图
硬件电路焊接完成实物图
焊接好的实物使用视频教程参考:B站地址,点击观看参考
\
程序清单及资料下载
代码较多,源程序及仿真资料下载地址:电子跑表资料,点击下载
电子跑表程序:
/************************ mian.c *************************/
#include <reg52.h>
#include "1602.h"
#include "main.h"
#include "delay.h"
#include "control.h"
#include "key.h"
uchar code tablea[]=" 2020-12-31 Thu ";
uchar code tableb[]=" 00:00:00 ";
uchar code tablec[]="0 -- 00:00:00:00";
uchar code tabled[]=" 00:00:00:00 ";
extern uint mode,imode;
void main()
{
uchar num;
init();
while(1)
{
keyscan() ;
if (mode==CLOCK)
{
/***********************************/
if(imode)
{
write_com(0x80);
for(num=0;num<=15;num++)
{
write_date(tablea[num]);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<=15;num++)
{
write_date(tableb[num]);
delay(5);
}
imode=0;
}
/***********************************/
keyscan_clock();
if(TR0==1)show_clock();
}
if (mode==RUN)
{
/***********************************/
if(imode)
{
write_com(0x80);
for(num=0;num<=15;num++)
{
write_date(tabled[num]);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<=15;num++)
{
write_date(tablec[num]);
delay(5);
}
imode=0;
}
/***********************************/
keyscan_run();
show_run();
}
}
}
/********************** main.h ********************************/
#ifndef __MAIN_H_
#define __MAIN_H_
#define uchar unsigned char
#define uint unsigned int
#endif
/************************ 1602.c *****************************/
#include <reg52.h>
#include "delay.h"
#include "1602.h"
sbit rs=P1^0;
sbit lcden=P1^2;
sbit rw=P1^1;
void write_com(uchar com)
{
rs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_date(uchar date)
{
rs=1;
lcden=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_sfm(uchar hang,uchar add,uchar date)
{
uchar shi,ge;
shi=date/10;
ge=date%10;
if (hang==1)
write_com(0x80+add);
if(hang==2)
write_com(0x80+0x40+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
/******************** 1602.h *******************************/
#ifndef __1602_H_
#define __1602_H_
#include "main.h"
void write_com(uchar com);
void write_date(uchar date);
void write_sfm(uchar hang,uchar add,uchar date);
#endif
/************************ delay.c ****************************/
#include "delay.h"
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=800;y>0;y--);
}
/************************* delay.h ***********************/
#ifndef __DELAY_H__
#define __DELAY_H__
#include "main.h"
void delay(uint z);
#endif
/********************** key.c ********************************/
#include <reg52.h>
#include "key.h"
#include "main.h"
#include "delay.h"
#include "1602.h"
sbit s1=P2^0; //时钟调整按键
sbit s2=P2^1; //时钟加按键/计时清零键
sbit s3=P2^2; //时钟减按键/计时开始或停止
sbit time_cap=P2^3; //计时捕获按键
sbit mode_change=P2^4; //模式切换按键
uint mode=CLOCK; // mode : 模式标志位
extern uchar count,miao,shi,fen; //时钟参数
extern uchar msecond,second,minute,hour; //跑表参数
uchar s1num; // 调整时钟用的状态标志
uint s1_state=0,s3_state=0;
uint site=0,ssite=0; //计时保存排名位
long time[15]; //计时保存数组
uint flag=0,imode=0;
void keyscan(void) //模式按键扫描
{
if(mode_change==0)
{
delay(5);
if(mode_change==0) //模式转换huan
{
flag++;
if(flag%2==0)
{
mode=CLOCK;
imode=1;
}
else
{
mode=RUN;
imode=2;
}
while(!mode_change);
}
}
}
/*
keyscan_clock : 时钟模式下按键扫描
输入 : 无
输出 : 无
*/
void keyscan_clock(void)
{
if(s1==0)
{
delay(5);
if(s1==0)
{ s1num++;
while(!s1);
if(s1num==1)
{
TR0=0;
write_com(0x80+0x40+10);
write_com(0x0f);
}
}
if(s1num==2)
{
write_com(0x80+0x40+7);
}
if(s1num==3)
{
write_com(0x80+0x40+4);
}
if(s1num==4)
{
s1num=0;
write_com(0x0c);
TR0=1;
}
}
if(s1num!=0)
{
if(s2==0)
{
delay(5);
if(s2==0)
{
while(!s2);
if(s1num==1)
{
miao++;
if(miao==60)
miao=0;
write_sfm(2,10,miao);
write_com(0x80+0x40+10);
}
if(s1num==2)
{
fen++;
if(fen==60)
fen=0;
write_sfm(2,7,fen);
write_com(0x80+0x40+7);
}
if(s1num==3)
{
shi++;
if(shi==24)
shi=0;
write_sfm(2,4,shi);
write_com(0x80+0x40+4);
}
}
}
if(s3==0)
{
delay(5);
if(s3==0)
{
while(!s3);
if(s1num==1)
{
miao--;
if(miao==-1)
miao=59;
write_sfm(2,10,miao);
write_com(0x80+0x40+10);
}
if(s1num==2)
{
fen--;
if(fen==-1)
fen=59;
write_sfm(2,7,fen);
write_com(0x80+0x40+7);
}
if(s1num==3)
{
shi--;
if(shi==-1)
shi=23;
write_sfm(2,4,shi);
write_com(0x80+0x40+4);
}
}
}
}
}
/*
keyscan_run : 跑表模式下按键扫描
输入 : 无
输出 : 无
*/
void keyscan_run(void)
{
if(time_cap==0)
{
delay(5);
if(time_cap==0)
{
if(site<15)
{
site++;
time[site]=hour*1000000+minute*10000+second*100+msecond;
write_sfm(2,0,site);
write_sfm(2,5,time[site]/1000000);
write_sfm(2,8,time[site]%1000000/10000);
write_sfm(2,11,time[site]%10000/100);
write_sfm(2,14,time[site]%100);
}
}
}
if(s1==0) //计时清零
{
uint i=0;
delay(5);
if( s1==0 && s3_state%2==0 )
{
msecond=second=minute=hour=0;
for(i=0;i<15;i++)
{
time[i]=0;
}
site=0;
write_sfm(2,0,0);
write_sfm(2,5,0);
write_sfm(2,8,0);
write_sfm(2,11,0);
write_sfm(2,14,0);
}
}
if(s2==0) // 查询数据
{
delay(5);
if(s2==0)
{
ssite++;
if(ssite>site) ssite=1;
write_sfm(2,0,ssite);
write_sfm(2,5,time[ssite]/1000000);
write_sfm(2,8,time[ssite]%1000000/10000);
write_sfm(2,11,time[ssite]%10000/100);
write_sfm(2,14,time[ssite]%100);
}
}
if(s3==0) // 开始 / 停止 计时
{
delay(5);
if(s3==0)
{
s3_state++;
if(s3_state%2)
{
TR1=1;
}
if(s3_state%2==0)
{
TR1=0;
}
while(!s3);
}
}
}
/********************** key.h ********************************/
#ifndef __KEY_H_
#define __KEY_H_
#define CLOCK 0 //时钟模式
#define RUN 1 //跑表模式
void keyscan_clock(void); //时钟模式按键扫描
void keyscan(void); //状态模式扫描
void keyscan_run(void); //跑表模式扫描
#endif
/***************** control.c ******************************/
#include "control.h"
#include "1602.h"
#include "delay.h"
uchar count,miao,shi,fen; //时钟参数
uchar code table[]=" 2020-12-31 Thu "; //初始化LCD见界面参数
uchar code table1[]=" 00:00:00 ";
uchar msecond,second,minute,hour; //跑表参数
//初始化,LCD及定时器
void init(void)
{
uchar num;
// lcden=0;
// fen=59;
// miao=53;
// shi=23;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<=15;num++)
{
write_date(table[num]);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<=15;num++)
{
write_date(table1[num]);
delay(5);
}
TMOD=0x11;
TH0 = 0x88;
TL0 = 0x00;
EA=1;
ET0=1;
TR0=1;
TH1 = 0x0E8; //定时器1 10ms
TL1 = 0x00;
ET1=1;
TR1 = 0;
}
//定时器2中断服务函数,用于时钟进行
void timer0() interrupt 1
{
TH0 = 0x88;
TL0 = 0x00;
count++;
if(count==20)
{
count=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
}
}
}
}
}
//定时器1中断服务函数,用于跑表计时
void timer1() interrupt 3
{
TH1 = 0x0E8; //定时器1 10ms
TL1 = 0x00;
msecond++;
if(msecond==100)
{
msecond=0;
second++;
if(second==60)
{
second=0;
minute++;
if(minute==60)
{
minute=0;
hour++;
if(hour==24)
hour=0;
}
}
}
}
//更新时钟函数
void show_clock(void)
{
write_sfm(2,4,shi);
write_sfm(2,7,fen);
write_sfm(2,10,miao);
}
//更新跑表计时函数
void show_run(void)
{
write_sfm(1,2,hour);
write_sfm(1,5,minute);
write_sfm(1,8,second);
write_sfm(1,11,msecond);
}
/*************************** control.h ********************/
#ifndef __CONTROL_H_
#define __CONTROL_H_
void init(void);
void show_clock(void);
void show_run(void);
#endif