基于51单片机实现SG90舵机角度控制与PWM驱动
SG90是一款广泛应用于轻量级机械结构与模型控制的微型舵机。本文将探讨如何利用STC89C52单片机通过PWM(脉冲宽度调制)信号对其进行精确的角度控制。
舵机工作原理
SG90舵机的运动由PWM信号的占空比决定。典型的控制周期为20ms,其对应的脉冲宽度范围约为0.5ms至2.5ms:
- 0.5ms脉宽: 对应舵机转动至0°极限位置。
- 1.5ms脉宽: 对应舵机处于90°中间位置。
- 2.5ms脉宽: 对应舵机转动至180°极限位置。
舵机的工作电压通常在4.8V至6V之间。在开发过程中,需确保电源供电充足,以应对电机启动时的瞬时电流需求。
实现方案一:基于延时循环的PWM生成
此方法通过程序控制IO口的电平翻转实现简易PWM,适用于对实时性要求不高的简单动作逻辑:
#include <reg51.h>
sbit SERVO_OUT = P1^0;
void soft_delay(unsigned int cycles) {
while(cycles--);
}
void drive_servo(unsigned int target_angle) {
// 将角度映射为脉宽:0-180度映射到500-2500us
unsigned int high_level_time = 500 + (target_angle * 11);
unsigned char i;
for(i = 0; i < 20; i++) {
SERVO_OUT = 1;
soft_delay(high_level_time);
SERVO_OUT = 0;
soft_delay(20000 - high_level_time);
}
}
void main() {
while(1) {
drive_servo(0); // 转至0度
soft_delay(50000);
drive_servo(180); // 转至180度
soft_delay(50000);
}
}
实现方案二:利用定时器中断实现精准控制
通过定时器中断生成PWM信号,可以有效释放CPU资源并提高控制精度。以下代码演示了如何利用Timer0实现周期性的信号触发:
#include <reg52.h>
sbit SERVO_PIN = P1^0;
volatile unsigned int pulse_counter = 0;
unsigned int target_width = 150; // 目标占空比
void Timer0_Setup() {
TMOD = (TMOD & 0xF0) | 0x01;
TH0 = 0xFC; // 定时约1ms
TL0 = 0x66;
ET0 = 1;
EA = 1;
TR0 = 1;
}
void Timer0_ISR() interrupt 1 {
TH0 = 0xFC;
TL0 = 0x66;
if (pulse_counter < target_width) {
SERVO_PIN = 1;
} else {
SERVO_PIN = 0;
}
pulse_counter++;
if (pulse_counter >= 2000) { // 20ms周期
pulse_counter = 0;
}
}
void main() {
Timer0_Setup();
while(1);
}
在上述方案中,定时器中断作为PWM信号的基准时钟。通过改变target_width变量的值,可以灵活调整舵机的旋转角度,从而实现更加平滑的运动控制。