上图是小蜜蜂的视频,我的理解是,定时器和计数器本质上是计数器,作为定时器是他的信息来源也就是脉冲来源就是内部晶振,等计数满了,也就是定时的时间到了,就去执行定时中断。作为计数器是就是外部信息作为一个脉冲,比如传感器监控传送带上通过了几个物体,然后设置的计数数量满了就触发计数中断,在ne555上测量频率,用的就是八位重装模式,所以本质上他们都是计数器,通过寄存器的不同设置可以用做不同的用途

   上图为定时器和计数器的初值是如何设定的,也     就是TL0和TH0,这个只做理解。具体的初值设定有软件设定,

       

        定时器与中断是绑定一起的,在软件生成定时器初始化函数之后,要自己加上ET和EA使能,即赋为1.与中断寄存器不一样,TCON可以位寻址,像上图,但是上图是其他51单片机的;TCON应该就是中断寄存器,他包括EA,ET0,.Tmod模式寄存器只能字节寻址,TMOD有八位,他的高四位控制定时器1和计数器1的模式选择,低四位控制的是定时器0和计数器0的模式选择。GAME位为0的时候就需要用TR0和TR1来启动,一般都是用TR0启动,我们一般用的是01模式,16位不重载,就需要在中断服务函数里面重新设置初值,重载就不需要,他会自动设置初值。c/t为0就是定时器,为1是计数器,

void Timer0_INT() interrupt 1  //大概1毫秒进一次中断服务函数
{
	static unsigned int count;
	TL0 = 0x66;		//重装定时初值
	TH0 = 0xFC;		//重装定时初值
	count++;
	if(count>=1000)  //建议要大于等于,不然可能刚好卡在一个机器周期瞬间超过之后就不响应
	{
		count=0;
		sign=1;
		
	}
}

以上是定时器中断的服务函数,有个基本的框架,容易忽视的是在函数中要记得重装定时初值,还有就是大于等于的问题,具体看上面;但是好像软件设置的定时初值有点模糊,具体还要看看江科大和小蜜蜂的视频;

2025-3-1修正:在软件上计算计时器就是我想的那样,具体还是看江科大的视频,小蜜蜂看到现在并没有教软件计算定时器

#include <REGX52.H>
#include "registerr.h"

unsigned char sign=0;

void Timer0Init(void)		//1毫秒@11.0592MHz
{
//	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x66;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=1;  //软件生成之后要自己加上,EA也是; 
	EA=1;
}

void LED_run()
{
	if(sign==1)
	{
		sign=0;
		registerr(4);
		P0=0x00;
	}
		
}

void main()
{
	Timer0Init();
	while(1)
	{
		LED_run();
	}
}

void Timer0_INT() interrupt 1  //大概1毫秒进一次中断服务函数
{
	static unsigned int count;
	TL0 = 0x66;		//重装定时初值
	TH0 = 0xFC;		//重装定时初值
	count++;
	if(count>=1000)  //建议要大于等于,不然可能刚好卡在一个机器周期瞬间超过之后就不响应
	{
		count=0;
		sign=1;
		
	}
}

以上是总体代码示例,可能定时精度有点问题;但是具体功能是实现了的;

 

 

#include <REGX52.H>
#include "registerr.h"
#include "Close.h"

unsigned char hour;
unsigned char min;
unsigned char sec;
unsigned char Keynum;
unsigned char Keynum_m;
unsigned char sign=1;//为1才进入中断

void Delay(unsigned int t)
{
	unsigned int i,j;
	for(i=0;i<t;i++)
	for(j=0;j<110;j++);
}

void Timer0Init(void)		//1毫秒@12.000MHz
{
//	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0=1;
	EA=1;
}


unsigned char code SMG[]=
{
	0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf
};

void SMGG(unsigned char pos,unsigned char dat)
{
	registerr(6);
	switch(pos)
	{
		case 1 : P0=0x01;break;
		case 2 : P0=0x02;break;
		case 3 : P0=0x04;break;
		case 4 : P0=0x08;break;
		case 5 : P0=0x10;break;
		case 6 : P0=0x20;break;
		case 7 : P0=0x40;break;
		case 8 : P0=0x80;break;
	}
	registerr(7);
	P0=SMG[dat];
	Delay(5);
}

void Scan_SMG()
{
	SMGG(1,hour/10);
	SMGG(2,hour%10);
	SMGG(3,10);
	SMGG(4,min/10);
	SMGG(5,min%10);
	SMGG(6,10);
	SMGG(7,sec/10);
	SMGG(8,sec%10);
}

void Ctrl()
{
	if(Keynum==7)
	{
		sign=1;
	}
	if(Keynum==6)
	{
		sign=0;
	}
	if(Keynum_m==5)
	{
		hour=0;
		min=0;
		sec=0;
		Keynum_m=0;
	}
}

void KEY() //7启动;6暂停;5清零
{
	if(P3_0==0)
	{
		Delay(20);
		if(P3_0==0)
		{
			while(P3_0==0);
			Keynum=7;
		}
	}
	
	if(P3_1==0)
	{
		Delay(20);
		if(P3_1==0)
		{
			while(P3_1==0);
			Keynum=6;
		}
	}
	
	if(P3_0==2)
	{
		Delay(20);
		if(P3_2==0)
		{
			while(P3_2==0);
			Keynum_m=5;
		}
	}
}


void main()
{
	Timer0Init();
	Close();
	while(1)
	{
		KEY();
		Ctrl();
		Scan_SMG();
	}
}

void Timer0_Rountine() interrupt 1
{
	
	if(sign==1)
	{
		static unsigned int count;
		TL0 = 0x18;		//设置定时初值
		TH0 = 0xFC;		//设置定时初值
		count++;
		if(count>=1000)
		{
			count=0;
			sec++;
			if(sec>=60)
			{
				sec=0;
				min++;
				if(min>=60)
				{
					min=0;
					hour++;
					if(hour>=24)
					{
						hour=0;
					}
				}
			}
		}
	}
}


        以上是用一个定时器制作时钟;唯一不足是数码管有点闪烁,解决办法有一个,用定时器扫描数码管,这个方法可以到江科大那里看教学,方法很精妙;

 

 

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐