蓝桥杯——定时器详解

实验目的:实现20s的计时

一、原理部分

时钟周期和机械周期

1.时钟周期即晶振的单位时间发出的脉冲数。
2.一个机器周期等于12个时钟周期。
15系列的芯片晶振是12MHZ,12MHZ=12×10的6次方,即每秒发出12000000个脉冲信号,那么发出一个脉冲的时间就是时钟周期,即1/12微秒,一个机器周期等于12个时钟周期,所以是1微秒。
15系列还有12T模式,即一个机器周期等于一个时钟周期,就是1/12微秒,我们采用1T模式,即一个机器周期为1微秒

定时器和计数器的异同

异:时钟来源不同,定时器时钟来源为内部系统时钟,计数器为外部时钟。
同:都是统计脉冲个数

定时器的相关寄存器

用定时器0为例
在这里插入图片描述
TH0和TL0为存储定时器值的寄存器

定时器工作模式寄存器TMOD

在这里插入图片描述
配置定时器0为16位定时器(TMOD.1=0 TMOD.0=1),并且用作定时器(TMOD.2=0),TMOD.3不需要置1的功能,于是TMOD.3置0。所以配置配置定时器0的TMOD寄存器的代码为TMOD = TMOD&0xF0|0x01;与上0xf0是为了保留高四位的数值不影响定时器1的配置并且清空第四位,或上0x01是为了配置定时器0。

定时器控制寄存器TCON

在这里插入图片描述
TR0相当于是定时器0的一个开关,,打开定时器0即TR0=1,关闭定时器0即TR0=0
溢出时,TF0 = 1

定时器初值

定时器每过一个机器周期,定时器的值便会加1,定时器的值储存在TH0和TL0两个寄存器中,分别为高8位和第8位,共16位寄存器。即可以计数2的16次方次,即65536次,计数达到65536次时,会溢出,即TF0 = 1。
这里的机器周期为1us,即最多可以产生65536us的时间。
用定时器0产生50ms的时间来说明如何给TH0和TL0赋初值
50ms=50000us
65536us-50000us=15536us
15536us/1us=15536
即说明当定时器从15536次开始计数时,再次计数50000次就可以溢出。
所以初值为

	TH0=(65536-50000)/1/256;
	TL0=(65536-50000)/1%256;

这里除以256和取余256是为了获取高八位和第八位,也可以用计算器转化为16进制,即

	TH0=0x3c;
	TL0=0xb0;

定时器溢出时的处理

当定时器溢出时,说明指定的时间已经达到,用if(TF0 == 1)来判断是否达到定时的时间。
此时需要将TF清零,并且重新给定时器0赋值。即

		TF0 = 0;
		TH0=0x3c;
		TL0=0xb0;

实验中我们要的时间为20s,但是定时的时间为50ms,可以定义一个count变量来计数,定时器0每溢出一次,count就加一,这样count等于50时,就达到了1s的时间,再定义一个变量sec来记录秒,每到1s的时间sec加一,当sec达到20时就清零,这样就完成了20s的计时。

			 	if(++count == 20)
			   {		  
				   if(++sec == 20)
					sec = 0;				   
				count = 0;				  
			   }				

二、代码部分

实验平台:CT107D
实验芯片:stc15f2k60s2
实验现象:20s的计时
代码如下

#include "stc15f2k60s2.h"
#include "intrins.h"
sbit buzz = P0^6;		 //位定义蜂鸣器
unsigned char display[] = { 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};//定义0-7对应段选数组
unsigned char code wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //定义位码数组 
unsigned char disbuff[8];
unsigned char sec = 0;

void Delay2ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 24;
	j = 85;
	do
	{
		while (--j);
	} while (--i);
}

void show_num()
{
	 disbuff[0] = 10;
	 disbuff[1] = 10;
	 disbuff[2] = 10;
	 disbuff[3] = 10;
	 disbuff[4] = 10;
	 disbuff[5] = 10;
	 disbuff[6] = sec/10;
	 disbuff[7] = sec%10;
}

void close_buzz()	//蜂鸣器上电默认高电平,所以关闭蜂鸣器
{
	 P2=0xa0;
	 buzz = 0;
	 P2=0x00;
}
void time0_init()//50ms定时器
{
		TMOD = TMOD&0xF0|0x01;//设置定时器模式
		TH0 = (65536-50000)/1/256;//定时器0初值
		TL0 = (65536-50000)/1%256;//定时器0初值
		TR0 = 1;//打开定时器0
		TF0 = 0;//清除定时器0溢出标志	
}

void main()
{	  
		unsigned char i,count;
		close_buzz();
		time0_init();
		while(1)
		{	
			if(TF0 == 1)
			{
				TF0 = 0;//清除定时器0溢出标志
				TH0=0x3c;//定时器0初值
				TL0=0xb0;//定时器0初值
			 	if(++count == 20)
			   {		  
				   if(++sec == 20)
					sec = 0;				   
				count = 0;				  
			   }				
			}

			for(i=0;i<8;i++)
			{

				P2 = 0xc0;
				P0 = wei[i];
			    P2 = 0x00;//关闭锁存器

				P2 = 0xe0; //打开段选锁存器
				P0 = ~display[disbuff[i]];//数组定义为共阴极的段码,开发板上的为共阳极于是取反
				P2 = 0x00;//关闭锁存器	
								
				Delay2ms();//刷新频率为2ms
			}
			show_num();								
		}
}


发布了16 篇原创文章 · 获赞 26 · 访问量 5728

猜你喜欢

转载自blog.csdn.net/FuckerGod/article/details/104050987