【前言】
这是我在大三下学期的时候做的一个机械电子课程设计,现在分享给有需要的小伙伴,相关资料仅供参考。
如果你也想学习单片机,请参考我的另外一篇文章,希望这些内容能给你带来一些帮助。
以下是电子秒表的资料、系统框图、流程图、C51 程序以及 Proteus 仿真电路图
【基于51单片机的电子秒表程序设计及Proteus仿真】
材料:STC89C52、共阳极数码管、三极管、按键。
计时范围:00.00 秒 - 99.99 秒
功能:开始、停止、复位。
所有文件下载:基于51单片机的电子秒表程序设计及Proteus仿真.zip
文件中包含:系统框图、流程图、C51 程序以及 Proteus 仿真电路图
一、系统框图

二、流程图
1、按键流程图

2、数码管显示流程图

三、C51 程序
#include<reg52.h>
void delay();
sbit KEY1 = P3^3; //启动为按键1
sbit KEY2 = P3^4; //停止为按键2
sbit KEY3 = P3^5; //复位为按键3
sbit LED0 = P2^3; //第0位数码管使能 4
sbit LED1 = P2^2; //第1位数码管使能 1
sbit LED2 = P2^1; //第2位数码管使能 2
sbit LED3 = P2^0; //第3位数码管使能 3
sbit point = P0^7;
unsigned char backup[3] = {1,1}; //上次按键值
unsigned char keysta[3] = {1,1}; //按键值
unsigned char KEY[3] = {1,1,1}; //按键值
unsigned char keybuff[3] = {0xFF,0xFF,0xFF}; //按键四次缓存值
unsigned long num = 0; //用于计时,每1ms加一
unsigned int sec = 0; //用于计时,每10ms加一
unsigned char i = 0; //数码管显示的某一位
unsigned char j = 0; //用于for循环
unsigned char k = 0; //用于for循环
unsigned int m = 0; //用于for循环
unsigned char flagstart = 0; //走秒标志位
unsigned char code LedChar[]={
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
}; //数码管显示字符转换表
unsigned char LedBuff[4] = {0,0,0,0}; //储存个位、十位、十分位、百分位的数值
void main()
{
TMOD = 0x01; //定时器0设置模式1
TH0 = 0xFC;
TL0 = 0x67; //定时1ms 11.0592MHZ
TR0 = 1; //开始计时
EA = 1; //开总中断
ET0 = 1; //开定时器0中断
P2 = P2&0xF0;
while(1)
{
LedBuff[0] = sec%10; //在sec中提取个位,即0.01秒
LedBuff[1] = sec/10%10; //在sec中提取十位,即0.1秒
LedBuff[2] = sec/100%10; //在sec中提取百位,即1秒
LedBuff[3] = sec/1000%10; //在sec中提取千位,即10秒
for(j=0;j<=3;j++) //循环检测按键是否有动作
{
if(backup[j]!=keysta[j]) //如果按键有动作
{
if(backup[0]==0) //如果上次开始/继续按键为按下状态
{
flagstart = 1; //开始计时
}
else if(backup[1]==0) //如果上次停止按键为按下状态
{
flagstart = 0; //停止计时
}
else if(backup[2]==0) //如果上次复位按键为按下状态
{
sec = 0; //计时结果清零
flagstart= 0; //停止计时
}
backup[j] = keysta[j]; //将当前按键值存储在数组内
}
}
if(sec>=10000) //如果计时大于等于100.00s
{
flagstart = 0;
sec = 0;
num = 0;
}
P0=LedChar[LedBuff[0]]; //数码管显示百分位
for(m=0;m<=225;m++);LED0=0;LED1=1; //延时,位选选择下一个数码管
P0=LedChar[LedBuff[1]]; //数码管显示十分位
for(m=0;m<=225;m++);LED1=0;LED2=1; //延时,位选选择下一个数码管
P0=LedChar[LedBuff[2]]&0x7f; //数码管显示个位
for(m=0;m<=225;m++);LED2=0;LED3=1; //延时,位选选择下一个数码管
P0=LedChar[LedBuff[3]]; //数码管显示十位
for(m=0;m<=225;m++);LED3=0;LED0=1; //延时,位选选择下一个数码管
}
}
void InterruptTimer0() interrupt 1
{
TH0 = 0xFC;
TL0 = 0x67; //重置定时器初值(1ms)
num++; //num每1ms加一
if(flagstart == 1&&num%10 == 0) //如果处于计时状态且达到10ms,则sec加一
{
sec++;
}
if(num%4 == 0) //每4ms依次扫描按键状态并储存在数组内
{
keybuff[0] = (keybuff[0]<<1)|KEY1;
keybuff[1] = (keybuff[1]<<1)|KEY2;
keybuff[2] = (keybuff[2]<<1)|KEY3;
for(k=0;k<3;k++)
{
if((keybuff[k]&0xFF) == 0x00)//如果按键4次状态都为低电平,则为按下状态
{
keysta[k] = 0;
}
if((keybuff[k]&0xFF) == 0xFF)//如果按键4次状态都为高电平,则为抬起状态
{
keysta[k] = 1;
}
}
}
}
四、Proteus 仿真

