加一计时器——每隔1s六位数码管显示数字加1,直至999999,之后归零,重新开始。

   日期:2021-01-24     浏览:173    评论:0    
核心提示:加一计时器——每个1s六位数码管显示数字加1,直到最大值是999999,之后回零#include <reg52.h>#define uchar unsigned char#define uint unsigned int#define ulint unsigned long intsbit dula=P2^6;sbit wela=P2^7;uint num;ulint disnum;uchar code table_du[]={0x3f,0x06,0x5b,0&#

加一计时器

2021-01-23,51单片机学习笔记

每隔1s六位数码管显示数字加1,直至999999,之后归零,重新开始。

代码:
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define ulint unsigned long int
sbit dula=P2^6;
sbit wela=P2^7;
uint num,num_set,n;//中断计次num,中断次数预设,中断服务初始化参数n
ulint disnum;
//欲显示的数字,因其最大值为999999,已经超过uint的范围(0~65535),这里采用ulint

uchar code table_du[]={ 
0x3f,0x06,0x5b,0x4f,0x66,0x6d,
0x7d,0x07,0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};//六位共阴极8段数码管段显编码

void display(ulint);//展示数字 声明
void delayms(uint); //延时函数 声明

void main()
{ 
	n=50000;
	num_set=20;
	
	EA=1;
	ET0=1;
	TMOD=0x01;
	TH0=(65536-n)/256; 
	TL0=(65536-n)%256;
	TR0=1;
	while(1)
	{ 	
		if(num==num_set)//每间隔1s(=2*50ms),更新一次disnum
		{ 
			num=0;
			if(disnum==1000000)//溢出回零
			{ 
			disnum=0;
			}
			disnum++;	
		}
		display(disnum);//显示当前数字
	}
}

//中断服务程序
void time0() interrupt 1 
{ 
	TH0=(65536-n)/256; 
	TL0=(65536-n)%256;
	num++;//记录中断次数
	//晶振f=12MHz,震荡周期=1/12um,机器周期=1us
	//n=50000时,单次中断服务耗时50ms(=50000*1us)
}

void display(ulint disnum)  
{ 
	uint ms;//延时函数参数
	ms=1;
	
	if(disnum>=100000)//当欲显示数字大于 该位显示的最小值 时才点亮
	{ 
		P0=table_du[disnum/100000];//取十万位
		dula=1;	
		dula=0;//段显锁存
		P0=0xfe;//11 11 1110 (对应LED1(第一位数码管);LED1~6自左到右分布)
		//位显编码(六位共阴极8段数码管,由P0口低六位控制,低电平时相应位点亮)
		wela=1;
		wela=0;//位显锁存
		delayms(ms);
	}
	
	if(disnum>=10000)
	{ 
		P0=table_du[disnum%100000/10000];//取万位
		dula=1;	
		dula=0;
		P0=0xfd;//11 11 1101 (对应LED2)
		wela=1;
		wela=0;
		delayms(ms);
	}	
	
	if(disnum>=1000)
	{ 
		P0=table_du[disnum%100000%10000/1000];//取千位
		dula=1;	
		dula=0;
		P0=0xfb;//11 11 1011 (对应LED3)
		wela=1;
		wela=0;
		delayms(ms);
	}
	
	if(disnum>=100)
	{ 
		P0=table_du[disnum%100000%10000%1000/100];//取百位
		dula=1;
		dula=0;
		P0=0xf7;//11 11 0111 (对应LED4)
		wela=1;
		wela=0;
		delayms(ms);
	}

	if(disnum>=10)
	{ 
		P0=table_du[disnum%100000%10000%1000%100/10];//取十位
		dula=1;
		dula=0;
		P0=0xef;//11 10 1111 (对应LED5)
		wela=1;
		wela=0;
		delayms(ms);
	}
	
	if(disnum>=0)
	{ 
		P0=table_du[disnum%100000%10000%1000%100%10];//取个位
		dula=1;
		dula=0;
		P0=0xdf;//11 01 1111 (对应LED6)
		wela=1;
		wela=0;
		delayms(ms);
	}
}

void delayms(uint ms) //延时函数,ms=100时,延时约为100ms 
{  
   uchar k; 
   while(ms--) 
   {  
      for(k = 0; k < 90; k++); 
   } 
}

思考:

当间隔时间小到0.01s时,程序运行到if(num==num_set){...}位置时,中断服务响应次数已经超过预设值,则不满足条件“num==num_set”,就无法执行后续语句,导致显示数值一直停留在某个数值。这时,将判断条件改为“num>=num_set”,就可以避免上述情况发生,但是,实际中断次数已经大于预设值,也造成了计时器的误差。这种误差会随着while循环次数的增加而累加。

这该如何解决呢?

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服