基于51单片机的电子秒表程序设计及Proteus仿真

                           
2020年04月19日

前言

这是我在大三下学期的时候做的一个机械电子课程设计,现在分享给有需要的小伙伴,相关资料仅供参考。

如果你也想学习单片机,请参考我的另外一篇文章,希望这些内容能给你带来一些帮助。

51单片机学习资料及学习方法分享

以下是电子秒表的资料、系统框图、流程图、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 仿真

冷场莹