STC89C52RC数码管秒表程序编写

数码管显示秒表,芯片STC89C52RC。

具体要求,采用动态扫描的方式让,6个数码管前三个显示秒数,后两个显示毫秒。第四个不用。秒数精确到1%。


#include 
#define uint unsigned int
#define uchar unsigned char
#define N	2000	//定义中断初值。2000 x 1/12MHz x 12 = 2ms
uchar point;		//中断点,或计数点。比如point的值为5,那么当经过5个N(2000)时会计数一次。
uchar code table[] = { //数码管能显示的数值0x0~0xf
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
sbit dula = P2^6;	//数码管段选引脚定义
sbit wela = P2^7;	//数码管位选引脚定义

int wenum;	//控制显示哪个数码管
uchar code wetable[] = { //用到的数码管位选开关
0xfe,0xfd,0xfb,0xef,0xdf};

int fre = 0; //作为发生时钟计数次数的计数。时钟计数5次为10ms(5 x 2ms)。
uint s,ms;	//秒,毫秒

uint numBuffer[3] = {0};
//用于存取s,ms每一位的存储。比如s=123秒。那么numBuffer[0]=1;numBuffer[1]=2;numBuffer[2]=3
uint timebuffer[5] = {0}; //因为毫秒的显示只有两位计数0~99.秒的计数三位0~999。所以共5个存储空间即可。
void divNumber(uint ); //分离整数。把整数的百、十、个三位的数值分离开。存到numBuffer中。
void SavTime(uint ,uint ); //把时间保存到timebuffer中。
//如51秒350毫秒,数组中依次为05135。毫秒只显示两位即可,以10毫秒为单位。
//如678秒290毫秒,数组中依次为67829。
void main()
{
	point = 0;  
	wenum = 4;
	ms = s = 0;
	//s = 995; //这个可以打开。那么时间就会从995s开始显示,到999秒会从0开始。
	TMOD = 0x01;  //打开mod1.
	TH0 = (65536 - N) / 256; //高位附初值
	TL0 = (65536 - N) % 256; //低位附初值
	
	EA = ET0 = TR0 = 1; //EA 总中断;ET0 时钟中断;TR0启动计数器。
	while(1);
}
void timer0() interrupt 1{ //时钟0,中断数是1;时钟1,中断数是3
	TH0 = (65536 - N) / 256;
	TL0 = (65536 - N) % 256;
	point++;
	if(point == 1){
			wenum--;
			if(wenum < 0)	wenum = 4;	
			wela = 1;
			P0 = wetable[wenum];//从右到左显示
			wela = 0;

			dula = 1;
			P0 = table[timebuffer[wenum]];
			dula = 0;
	
			fre++;
			if(fre == 5){ //为什么要5次计数毫秒才++?程序尾解释。
				ms++;
				if(ms == 100){
					ms = 0;
					s++;
					if(s == 1000)	s = 0;
				}
				SavTime(s,ms);
				point = 0;
				fre = 0;	
			}
		point = 0;
	}
}

void divNumber(uint num){
	for(int b=2;!(b < 0);b--,num/=10)	numBuffer[b] = num %10;
	//b的初值是2,原因是num的最大值是3位数。那么数组的大小刚好够用。
}
void SavTime(uint STs,uint STms){  //把秒和毫秒都存到数组中。
	divNumber(STms);
	timebuffer[4] = numBuffer[2];
	timebuffer[3] = numBuffer[1];
	divNumber(STs);
	timebuffer[2] = numBuffer[2];
	timebuffer[1] = numBuffer[1];
	timebuffer[0] = numBuffer[0];
//  0 0 0   0 0
//	  秒    毫秒
}
	
秒表上毫秒一般都显示两位。实际上都知道毫秒~秒直接是1000级,三位。那为了只显示两位我们也只能取高位的显示。以10毫秒为单位的话,就是0~99了。也就是说我们10ms要改变数码管的显示了。比如 111 87,这是111秒870毫秒(10ms为单位)。过10ms就要显示111 88了。所以,题目要求后两个数码管显示毫秒,只能这样10ms为单位做了。
时钟频率是11~12MHz,这里假设是12M.
如果你想得到精确的时间,那么2ms = 2000 * (12 / 时钟频率)。那么这里就假设是12MHz。这么算下来2ms =2000 * 1/12MHz * 12(时钟周期)。
这个2ms代表了什么?就是代表程序里面设置的时钟2ms会加1一次。也就是说10ms的时间我需要加5次2ms才可以。


那干嘛不把初值N设置为10000,直接算出来的就是10ms了(10000 * 1/12MHz * 12 = 10ms)
那是因为这个动态数码管显示的原因。它每个计数加1一次要显示一个数码管的。一共5个数码管要显示,那么就得在10毫秒内进行至少5次的扫描。对于人眼来说,已经分辨不出跳变了。10ms内必须有5的倍数次扫描才行。

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