单片机定时器定时如何计算?

单片机控制舵机旋转,用定时器控制0.5ms~2.5ms的脉宽,结果舵机无响应

#include 
unsigned char Count=0;
void Timer0Init(void)        //500微秒@11.0592MHz
{
    TMOD &= 0xF0;        //设置定时器模式
    TMOD |= 0x01;        //设置定时器模式
    TL0 = 0x66;        //设置定时初值
    TH0 = 0xEA;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    TR0 = 0;        //定时器0开始计时
    EA  = 1;
    ET0 = 1;
}
void main()
{

    Timer0Init();
    P0_0=0;           //P0_0接舵机pwm
    while(1)
    {
        if(P3_1==0)    //P3_1独立按键
        {
            P0_0=1;
            TR0 = 1;
            while(Count<1);
            P0_0=0;
            while(Count<4);
            P0_0=1;
            TR0 = 0;
            Count=0;
        }
    }
}

void Timer_Rountine(void)        interrupt 1
{
    TR0 = 0;
    Count++;
    TL0 = 0x66;        //设置定时初值
    TH0 = 0xEA;        //设置定时初值
    TR0 = 1;
}

这段代码实现的是一个定时器控制舵机转动的功能,但可能需要进一步检查舵机与单片机之间的连接和信号是否正确。同时,需要注意到控制舵机的脉宽应该在0.5ms到2.5ms之间,可以检查一下是否满足这个范围。另外,需要注意舵机的电源是否稳定,如果电源不稳定可能会影响舵机的响应。

定时器计时的时间与定时器的时钟频率和计数器初值有关,计算公式为:

计时时间 = 计数器初值 x 定时器计数周期 / 定时器时钟频率

其中,计时时间是我们需要设置的定时时间,计数器初值是通过计算得到的需要给定时器的初值,定时器计数周期是定时器计数器能够计数的范围,定时器时钟频率是定时器的时钟源的频率。

对于8051单片机,定时器0的计数器初值为TH0(高8位)和TL0(低8位)两个寄存器的值组成的16位数值。定时器0的时钟源为定时器时钟脉冲,频率为晶振频率/12,所以当晶振频率为11.0592MHz时,定时器时钟频率为11.0592MHz/12=921.6kHz。定时器0的计数器能够计数的范围为0~65535,即定时器计数周期为65536。根据计算公式,可以得到定时500微秒的计数器初值为:

计数器初值 = 500微秒 x 921.6kHz / 65536 = 70.208

因为计数器初值为整数,所以实际上需要将计数器初值设置为70。此时定时器0每计数70次,就会产生一次中断,从而触发定时器中断服务程序中的计数器Count增加。对于0.5ms~2.5ms的舵机脉宽,需要设置不同的计数器初值。具体可以通过手动计算或者使用在线计算工具来获得不同脉宽对应的计数器初值。
在这个程序中,使用了定时器0产生PWM波形来控制舵机的转动角度。由于舵机的转动角度范围在0.5ms到2.5ms之间,因此使用定时器0来产生周期为20ms的PWM波形,通过占空比的调节来改变舵机的转动角度。

具体实现时,定时器0的初值应该设为65536-50,这样就可以产生一个周期为20ms的PWM波形。然后,通过设置TCON寄存器的TR0位,启动定时器0。当定时器0计数到50时,产生一个中断,改变输出引脚的电平,然后再启动定时器0。这样反复循环,就可以产生一个PWM波形。

代码如下:


#include <regx52.h>

void Timer0Init(void) //初始化定时器0
{
    TMOD &= 0xF0; //设置定时器模式
    TMOD |= 0x01; //设置定时器模式
    TL0 = 0x00; //设置定时初值
    TH0 = 0x00; //设置定时初值
    ET0 = 1; //允许定时器0中断
    TR0 = 1; //启动定时器0
}

void main()
{
    Timer0Init(); //初始化定时器0

    while(1)
    {
        // 待机
    }
}

void Timer0Isr(void) interrupt 1 //定时器0中断服务程序
{
    static unsigned char count = 0; //静态变量,用于计数
    if (count < 10) //设置高电平时间为0.5ms
    {
        P0_0 = 1; //输出高电平
    }
    else if (count < 90) //设置高电平时间为1.5ms
    {
        P0_0 = 0; //输出低电平
    }
    else if (count < 100) //设置高电平时间为2.5ms
    {
        P0_0 = 1; //输出高电平
    }
    else //计数器清零,重新开始一个周期
    {
        count = 0; //计数器清零
    }
    count++; //计数器加1
}