51单片机系列——定时器T0、T1怎么用(方波发生器实例+PWM呼吸灯实例+PWM直流电机调速实例)

今天,小小学渣又来复习51的定时器啦!

实例一:方波发生器
图1
源码如下:
main.c

#include <reg52.h>
sbit Square=P1^5; //设置方波输出引脚P1^5
void main(void){
 TMOD=0x02; //配置TMOD:定时器,工作方式2(自动重装初值)
 TH0=0x06;  //方式2,预装值
 TL0=0x06; //方式2,计数器
 IE=0x82;  //配置IE:中断允许/*也可以位操作,写成EA=1,ET0=1*/
 TR0=1;   //配置TCON:位操作,T0的中断标志位
 while(1); //死循环,等待中断
}
//这里没有其他中断服务程序,因此没有配置IP中断优先级
void time0_int(void) interrupt 1{	//定时器中断服务程序
 Square=!Square; 
}

结构图如下:
图2
上面是一个很简单的例子,但由此我们可以归纳出定时器的使用方法和步骤:
1、初始化定时器
(1)配置TMOD,TMOD的作用如下
图3
(2)设定THx、TLx的值。需要注意的是除了在工作方式2外。其他的工作方式下,这两个值要在定时器的中断服务函数中重新装入。
(3)设置IP,即中断优先级(不需要的话就不用设置的)
图4

(4)开中断:总中断允许和定时器T0/T1的中断允许
图5
(5)打开定时器的中断标志位TRx(直接位操作即可)
图6
这样就完成了定时器的初始化,接下来写一下中断服务程序即可

下面再讲两个实例:
实例二:PWM调直流电机速度
仿真图:图中K1是加速键,K2是减速键
图7

代码如下:

//控制直流电机转速

#include <reg51.h>
#define uint unsigned int
sbit Power=P1^0; //启停控制,Power=0电源断开,Power=1电源接通
sbit JiaSu=P1^1; //加速键
sbit JianSu=P1^2; //减速键

unsigned char PWMH; //高电平保持时间(以定时器定时时间的倍数计算)
unsigned char PWM; //PWM的整个周期(也已定时器定时时间的倍数计算)
unsigned char Counter; //定时器定时时间计数器

void INTT0() interrupt 1{  //每溢出一次来判断一次
 Counter++; //计数值加1
 if((Counter!=PWMH)&&(Counter==PWM)){//不在PWMH高电平时间,并且一个PWM的周期也到了
  Counter=1; //计数值复位
  Power=1; //开电源进入下一个PWM的周期,拉高电平 
 }else if(Counter==PWMH){ //高电平时间结束了,拉低电平关电源不供电
  Power=0;
 }
}

void main(void){
 PWMH=0x04; //设一个高电平的保持时间4/15(暂时定为2倍定时时间)
 Counter=0x01; //定时时间计数值,设初值为1
 PWM=0x15; //一个脉冲周期,暂定15倍定时时间
 TMOD=0x02; //定时器0在模式2下工作
 TL0=256-200;
 TH0=256-200;//200us产生一次溢出,即200us为一个定时时间
 ET0=1; //开定时器0中断使能
 EA=1; //开总中断使能
 TR0=1; //开始计时,定时器的中断标志位
 while(1){
  if(JiaSu==0){
     PWMH++; //扫描按键K1 ,加速
   while(!JiaSu); //这个很重要,判断开关是否断开 
  }
  if(JianSu==0){
     PWMH--; //扫描按键K2 ,减速
   while(!JianSu); //这个很重要,判断开关是否断开 
  }
 } 
}

这个自己运行一下仿真就知道啦!!!

实例三:PWM控制LED模仿呼吸灯(这个是我从普中上搬下来的,勿喷啦)
图8
代码如下:

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit PWM=P2^1; //定义使用的IO口
bit DIR; //用于改变方向的,1:PWM高电平延长;0:PWM高电平减短
uint count,value,timer1; //count:起到计数(一个缓冲的作用,延时一段时间在让value与timer1比较) timer1:整个PWM的周期  value:起到一个PWM波高低点交替点的作用,与timer1比较:timer1<value则输出高;否则输出低

void Time1Init(){
 TMOD|=0x10; //选择定时器1模式,工作方式1,仅用TR1打开启动
 TH1=0xFF;
 TL1=0xFF; //1us
 ET1=1; //打开定时器1中断允许
 EA=1; //开总中断
 TR1=1; //打开定时器
}

void main(){
 Time1Init(); //定时器1初始化
 while(1){
  if(count>100){
   count=0;
   if(DIR==1){
    value++;
   }
   if(DIR==0){
    value--;
   }
  }
  if(value==1000){
   DIR=0;
  }
  if(value==0){
   DIR=1;
  }
  if(timer1>1000) {//PWM周期为1000*1us
   timer1=0;
  }
  if(timer1<value){
   PWM=1;
  }else{
   PWM=0;
  }
 }
}

void Time1(void) interrupt 3
{
 TH1=0xFF;
 TL1=0xFF; //1us,重装初值
 timer1++;
 count++;
}

运行一下,就能看出仿真结果,但我觉得这个仿真的结果不是很好,还不如看一下它示波器的变化。

小编的一点学习分享,虽然很简单的东西,但希望对一些朋友有所帮助。嘻嘻嘻。

©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页