STC单片机定时器0产生pwm控制舵机运动和调速
- 首先,要使用pwm控制舵机,就需要对舵机的转角和脉宽关系有所了解,下图为一个周期内脉冲的宽度变化,所 以我们只需要按照图示产生固定比例的pwm波形就可以简单的控制舵机的正反转。

- 我使用的是stc8a8k32s型号单片机,用的24M晶振,为了给主程序和其他串口中断留下工作时间,所以将定时器定时时间设置为50us产生一次中断,所以对应舵机正反转的高电平时间500~2500us来说,是产生10次到50次中断,总的周期为400次中断,也就是20ms。所以编程思路为在总共400次的周期里,只需要控制中断次数在10到50次之间产生高电平就能让舵机转动。
- 对于舵机来说,需要的是对角度的精准控制和速度的可调,角度的控制在这篇文章就是将10到50次中断映射到舵机的全角度中,比如我使用的是270°舵机,所以就是对应270°角。对于舵机的调速来说,就是大角度的转动是靠小角度的堆积,并且在堆积中需要一定的延时,就可以完成对速度的调整,延时时间的控制就反映了舵机运动时间的快慢。
- 这是对定时器0初始化,并且定时50us.
void Time0_Init(void)
{
P0M1 &= 0xF7; P0M0 &= 0xF7;
P0 |= 0x08;
AUXR &= 0X7f;
TMOD = 0X01;
TL0 = 0X9c;
TH0 = 0XFF;
TR0 = 1;
ET0 = 1;
EA = 1;
pwm = 1;
}
void Time0Interrupt(void) interrupt 1
{
pwm_num++;
TL0 =0X9c;
TH0 =0XFF;
if(pwm_num<=angle)
pwm=1;
else
pwm=0;
if(pwm_num>400)
{
pwm_num=0;
}
}
void Servo_motion(unsigned int num,unsigned int speed)
{
unsigned int ang;
ang=(num/270.0)*40+10;
if(angle > ang)
{
while(angle>ang)
{
angle-=1;
Delay_ms(speed);
}
}
else
{
while(angle<ang)
{
angle+=1;
Delay_ms(speed);
}
}
}
int main(void)
{
Time0_Init();
angle=30;
while(1)
{
Servo_motion(150,60);
Servo_motion(200,60);
}
}
- 对于最合适的舵机pwm来说,应当是1us中断一次,刚好对应500到2500us的脉宽时间,总共是中断20000次,对应20ms的周期,所以如果使用stm32系列,可以尝试此方法,然后不断修改定时器重载值就可以实现舵机的精准控制和速度调整,这里只是为了说明舵机的pwm调速的原理,使得对于舵机的角度把握并不是精准的。