基于51单片机(普中开发板)的四位数码管秒表设计

说明

今天学校布置的课后作业,利用51单片机做一个秒表,本来是做了个8位数码管的秒表,但后来想了下秒表计时一般都不会用到以小时为单位,就把小时的部分以及毫秒的部分去掉了,就留下了分钟跟秒。

每个开发板的电路连接不一定是一样的,我所使用这块开发板是普中科技的,连接数码管的位选是接了一个138译码器的,如果是购买的普中科技的开发板可以直接复制程序就能使用,如果开发板的数码管的位选是接了锁存器的,那么就要相应地更改。

如果不理解138芯片使用方法的,我也要把138芯片的真值表附在下面了,顺便说下它的用法:
74HC138译码器可接受3位二进制加权地址输入(A0, A1和A2),并当使能时,提供8个互斥的低有效输出(Y0至Y7)。74HC138特有3个使能输入端:两个低有效(E1和E2)和一个高有效(E3)。除非E1和E2置低且E3置高,否则74HC138将保持所有输出为高。74HC138正常工作的话,一次只能输出一个低电平,其他全为高电平

要求:

  1. 按下按钮S1,秒表开始计时;
  2. 按下按钮S2,秒表暂停计时(停留在计时的数);
  3. 按下按钮S3,秒表清零;
  4. 计时精确到0.5s

电路图

基于51单片机(普中开发板)的四位数码管秒表设计_第1张图片基于51单片机(普中开发板)的四位数码管秒表设计_第2张图片基于51单片机(普中开发板)的四位数码管秒表设计_第3张图片基于51单片机(普中开发板)的四位数码管秒表设计_第4张图片基于51单片机(普中开发板)的四位数码管秒表设计_第5张图片

程序

程序已经过测试,可以正常使用,注释非常多,比较容易理解。

/****************************************************************************************
								秒表实验
实验现象:按下按钮S1开始计时,最大为59.59。按下按钮S2定时器暂停,按下按钮S3清零

*****************************************************************************************/
#include 
#define uint unsigned int						  //对数据类型进行声明定义
#define uchar unsigned char

sbit LS138_A = P2^2;							  //138芯片A2引脚
sbit LS138_B = P2^3;							  //138芯片A1引脚
sbit LS138_C = P2^4;							  //138芯片A0引脚

uchar DT_s = 0;								  //秒计时
uchar DT_min = 0;									  //分计时

uchar code duan[] = {0x3F,0x06,0x5B,0x4F,		  //共阴数码管无小数点 显示0~9
					 0x66,0x6D,0x7D,0x07,
					 0x7F,0x6F	
					};

uchar code duanpoint[] = {0xbf,0x86,0xdb,0xcf,	   //共阴数码管有小数点 显示0~9
						  0xe6,0xed,0xfd,0x87,
						  0xff,0xef,0xf7,0xfc,
						  0xb9,0xde,0xf9,0xf1
						 };

/************************************************
函数名				:delay1ms
函数功能            :t=1,大约延时1ms
************************************************/
void delay1ms(uint t)
{
	uint i,j;
	for(i=0;i<t;i++)
	{
		for(j=0;j<120;j++);	
	}
}

/************************************************
函数名				:Timer0Init
函数功能			:定时/计数器0中断初始化
*************************************************/
void Timer0Init()
{
	TMOD = 0x01; 		//选择T0定时/计数器,工作在方式1,16位计数器		
	TH0 = 0xFC;			//计数初始值,计数从64536开始,计1000个数,完成一次计数,时间为1ms
	TL0 = 0x18;		
	ET0 = 1;			//定时/计数器0中断允许位
	EA = 1;				//总中断
}

/************************************************
函数名				:S3
函数功能			:按下按钮S3时,秒表归零
*************************************************/
void S3()
{
	DT_s = 0;			//秒归零
	DT_min = 0;			//分归零
	TR0 = 0;			//运行控制位清0,关闭定时器
}

/**********************************************************
函数名				:ScanKey
函数功能			:按键扫描函数,循环扫描哪个键被按下
**********************************************************/
void ScanKey()
{
	uchar Key;		   //临时变量
	Key = P3&0x07;	   //只需要三个按键,分别接的P3^1,P3^2,P3^3,故把P3高五位被屏蔽
	if(Key!=0x07)	   //判断哪个键被按下
	{
		delay1ms(10);	 //消抖10ms
		Key = P3&0x07;	 //再次赋值,避免此时按键状态改变
		if(Key!=0x07)	 //确认按键被按下
		{
			switch(Key)
			{
				case 0x05:				  //S1(P3^2)被按下
							TR0 = 1;	  //定时器0运行控制位为1,启动定时器0
							break;
				case 0x06:				  //S2(P3^1)被按下
							TR0 = 0;	  //定时器0运行控制位为0,关闭定时器0
							break;
				case 0x03:				  //S3(P3^3)被按下
							S3();
							break;
			}
		}
		while(Key!=0x07)		//松手检测
		{
			Key = P3&0x07;
		}
	}
}

/*******************************************************************
函数名				:DigDisplay
函数功能			:数码管动态扫描函数,循环扫描8个数码管显示
********************************************************************/
void DigDisplay(uchar s,uchar min)
{
	LS138_A = 0;			  //秒个位位选
	LS138_B = 0;
	LS138_C = 0;
	P0 = duan[s%10];		  //发送段码,显示秒个位
	delay1ms(5);			  //间隔一段时间扫描
	LS138_A = 1;			  //秒十位位选
	LS138_B = 0;
	LS138_C = 0;
	P0 = duan[s/10];		  //发送段码显示秒十位
	delay1ms(5);			  //间隔一段时间扫描

	LS138_A = 0;			  //分的个位位选
	LS138_B = 1;
	LS138_C = 0;
	P0 = duanpoint[min%10];		  //发送段码,显示分的个位
	delay1ms(5);			  //间隔一段时间扫描
	LS138_A = 1;			  //分的十位位选
	LS138_B = 1;			  //间隔一段时间扫描
	LS138_C = 0;
	P0 = duan[min/10];		  //发送段码,显示分的十位
	delay1ms(5);			  //间隔一段时间扫描
	P0 = 0x00;				  //消隐
}

/**********************************************************
函数名				:主函数
函数功能			:无
**********************************************************/
void main(void)
{
	P0 = 0x00;		  //读端口前写1
	P3 = 0xFF;		  //读端口前写1
	Timer0Init();	  //定时器中断初始化函数
	while(1)
	{
		DigDisplay(DT_s,DT_min);	   //数码管显示函数
		ScanKey();							   //按键扫描函数
	}
}

/**********************************************************
函数名				:Timer0
函数功能			:定时器计数
**********************************************************/
void Timer0() interrupt 1
{
	static uint count_s;	
	static uint count_min;		
	TH0 = 0xFC;				//计数值初始化,从64536开始计数,计满时为65536,溢出时即为 1ms
	TL0 = 0x18;
	count_s++;				 //秒计数
	count_min++;				 //分计数
	if(count_s==1000)			 //计数到1s时,秒计数器开始工作
	{
		count_s = 0;		 //秒计数清零
		DT_s++;			 //显示秒计数值自增
		if(DT_s>59)		 //秒数最大为59
		{
			DT_s = 0;
		}
	}
	if(count_min==60000)		  //计数到60000ms时,秒计数器开始工作
	{
		count_min = 0;		  //分计数清零
		DT_min++;				  //显示分计数值自增
		if(DT_min>59)			  //分数最大为59
		{
			DT_min = 0;
		}
	}
}

你可能感兴趣的:(单片机)