【嵌入式】基于STC89C52RC的51单片机学习(二)

第二节 定时器

1 、概述

        C51中的定时器计数器是一个硬件电路支持的,通过对寄存器的不同配置,我们就可以使用定时器。

        确切的说定时器计数器区别导致它们加一的信号不同

        当我们配置为定时器时,每经过一个计数周期,计数存储器的值就加一。

        当我们配置为计数器时,每来一个负跳变信号(信号从P3.4或P3.5引脚输入输入),就加一,这样就可以达到计数的目的。

总结一下 

      定时器和计数器电路一样

      定时或者计数的本质上就是让单片机某个部件数数

      当定时器用的时候,靠内部震荡电路数数

      当计数器用的时候,数外面的信号,读取针脚的数据

        这里再来区分一下晶振时钟周期机器周期 

        晶振(晶体振荡器),是数字电路的“心脏”。数字电路的所有工作都离不开晶振,晶振的快慢与好坏会影响整个系统的稳定性。

        时钟周期:在一个时钟周期内,CPU只完成一个最基本的动作。是计算机中最小的,最基本的时间单位。也叫振荡周期,定义为时钟频率的倒数

        机器周期:机器周期也叫CPU周期。一个机器周期完成一条指令。在计算机中,为了方便管理,将一条指令分为若干阶段(取指、译码、执行),每一个阶段完成一个基本操作。每个基本操作完成所需要的时间称为机器周期。一个机器周期由若干时钟周期组成。

下面我们来举一个例子:

当芯片晶振频率是11.0592MHz的时候,我们的定时器加一时间是多少?

周期 = 1 / 频率 

        当晶振频率是11.0592MHz 的时候,等于 11059.2KHz = 11059200Hz
        机器周期 = 12 x 时钟周期 =12 x (1/ 时钟频率 )   = 12 / 时钟频率 s  = 12 / 11059200  s  = 12 000 000 / 11059200   us  = 1.085  us       
所以说当我们的定时器(12T模式)加一时,时间过去了 1.085us,这在之后有很多用处。

2、如何配置定时器

STC89C52RC单片内部设置了两个定时器/计数器。

 TCON寄存器:

         TCON寄存器的第5位(TF0)第7位(TF1)分别表示定时器计数值是否溢出,溢出为1,未溢出为0。

         bit6(TR1)bit4(TR0)定时器的开关,为1时开始计时

  TMOD寄存器

    

 

 TMOD中我们一般使用16位计数,设置M1M0两位为01,再设置TL0、TH0(定时器0存放计数值的寄存器)

这样就配置好了一个定时器。

3、通过定时器来控制LED 

以下代码通过定时器来实现灯一秒亮一次。

void main()
{
	 int cnt = 0;
	 led = 1;
  // 1.配置定时器0工作模式为16位计时
	  TMOD = 0x01;
  // 2.给初值,定一个10ms来计时
	  TL0 = 0x00;
	  TH0 = 0xDC;
 // 3.开始计时
	  TR0 = 1;
	  TF0 = 0;
 //当爆表时,硬件会修改bit5(TF0)位上面的数据,改成1(置一),如果不用中断,就要用代码清零
	 while(1){			 
	    if( TF0 == 1 ){
				   TF0 = 0;//代码手动清零
				   cnt++;//统计爆表的次数
				   TL0 = 0x00;//重新给初值
	               TH0 = 0xDC;		      
	   }
// 4.爆表了,操作led吗,累积到1s,再操作led
// 爆表了,变量加一,加个100次就是1s,每隔1s转换led状态
				
 //  if( !(cnt % 500) ) 
		 if(cnt == 100){
			 led = !led;
			 cnt = 0;//当100次表示1s,cnt重新从0开始计算下一次的一秒
         }
     }
	 	 
}

这里需要注意

   (1)    通过前面我们可以了解到,定时器加一(计的是机器时间,上面已经算过了),时间过去1.085us,我们的定时器模式设置为16位,最大可以计数到2^{16}=65536,65536*1.085us=71106.56us 约定等于71ms。也就是说该模式下定时器最大可以定时71ms

        现在我们想让灯一秒亮一秒灭,可以用软件延时,但是不是很准确。这个时候定时器就派上用场了。

         我们先让定时器每次定10ms,当过去100个10ms时,1s钟的时间就到啦。所以我们可以设置定时器的初值,使得初值到最大值刚好过去10ms,那么该怎么算呢?

         假设初值为x,那么(65536- x)*1.085 us= 10000 us 就可以算出初值x 约等于56320,十六进制0xDC00

        或者我们还有更简单的方法:

       用STC-ISP来直接计算:

 可以看到初值存放在TL0和TH0中,为0xDC00,与我们的手算结果一致。

         配置好了定时器的模式以及初值,我们可以打开定时器计时,通过TF0/TF寄存器判断是否溢出,当有溢出时,我们设置变量cnt++,cnt计数到100,说明过去了1s,可以控制灯的开关。

(2)TF寄存器由硬件置1,在中断中使用时,当请求cpu被响应时由硬件清零,也可以由程序查询清零

(3)在编写这个代码时,在判断 cnt是否到100时我出现了一个错误,导致灯一闪随即又灭了。   if( !(cnt%100) ),这里当cnt 是0或者100的时候都是成立的,所以有小bug。

4、通过定时器中断的方式来控制Led

        中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行

STC89C51的有8个中断源,4个外部中断,3个定时器中断,1个串口中断

中断控制的相关寄存器: 

 这里我们只用到了两个寄存器

        EA是总中断开关,在使用时需要置1

        ET0是定时器零溢出的中断允许位,在使用时也要置1

       这里我们只使用这俩个寄存器便可以开始定时器零溢出的中断

 XICON寄存器:

void Timer0Init(void)		//10毫秒@11.0592MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0xDC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;    //开启Time0中断
	EA  = 1;    //开启总中断开关
}


void main()
{
     led  = 1;
	 led1 = 1;
	 
	 Timer0Init();	//10毫秒@11.0592MHz
	
	//当爆表时,硬件会修改bit5(TF0)位上面的数据,改成1(置一),如果不用中断,就要用代码清零
		while(1){
		   led1 = 0;
			 Delay500ms();
			 led1 = 1;
			 Delay500ms();	
   }
	 	 
}



//执行中断处理函数
void Time0Handler()   interrupt 1 
{
    	cnt++;//统计爆表的次数
     	TL0 = 0x00;//重新给初值
        TH0 = 0xDC;
		  // 4.爆表了,操作led吗,累积到1s,再操作led
	    // 爆表了,变量加一,加个100次就是1s,每隔1s转换led状态				
			
	    //  if( !(cnt % 500) ) 
	  	if(cnt == 100)
	   {
  			 led = !led;
  			 cnt = 0;//当100次表示1s,cnt重新从0开始计算下一次的一秒
      }
}

 代码中出现了AUXR &=0X7F;这里简单说明一下,是为了降低单片机时钟对于外界电磁辐射的干扰。

在这里再整理一下自己对于中断不太明白的点,首先:

 (1)中断函数不同于子函数,不需要主函数调用就可以执行

 (2)C51中断处理函数也叫中断函数,在写中断函数时必须用interrupt n 来设定终端号,编译时就会自动的确定入口地址

 (3)例如中断函数 void timer0_sev(void) interrupt 1

          这里timer0_sev(void)是中断函数名,可以随意写

          interrupt1中断号不能随意写

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值