Add a timer-add 1 to the six-digit display number every 1s until 999999, then reset to zero and start again.

Add a timer

2021-01-23, 51 MCU study notes

Every 1s, the six-digit digital tube displays the number plus 1 until 999999, after which it returns to zero and restarts.

Insert picture description here

代码:
#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)
	{
    
    	/**************************************************************************
		此处,n=50000,num_set=20,时间间隔是:50000*1us*20=100ms=1s;
		若要调整时间间隔,需要调整n和num_set,如:
		(1)当n=50000,num_set=2时,时间间隔是:50000*1us*2=100ms=0.1s;
		(2)当n=5000 ,num_set=2时,时间间隔是:5000 *1us*2=10ms=0.01s,
		此时,同时需要将“if(num==num_set)”改为“if(num>=num_set)”,
		否则数码管显示数字会出错!
		
		【出现错误的原因可能是:程序运行到此处时,中断服务响应次数已经超过预设值,
		这当然会对数码管显示值的精度造成影响!而且这种误差还会随着时间累加。
		这一点是此代码的缺陷。】
		
		同时,也要合理地调整延时函数的参数,以保证显示效果稳定。
		如果延时时间不合理,就会造成显示时能够看出明显的闪烁。
		
		***************************************************************************/
		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++); 
   } 
}

思考:

When the interval time is as small as 0.01s, when the program runs to the if(num==num_set){...}position, the interrupt service response times have exceeded the preset value, and the condition "num==num_set" is not satisfied, the subsequent statements cannot be executed, resulting in the display value staying at a certain value. Numerical value. At this time, changing the judgment condition to "num>=num_set" can avoid the above situation. However, the actual number of interrupts is greater than the preset value, which also causes the error of the timer. This error will accumulate as the number of while loops increases.

How can this be solved?

Guess you like

Origin blog.csdn.net/qq_46541463/article/details/113044793