最简单的51单片机舵机控制器DIY

一、核心原理

舵机控制只需要一个PWM信号:

  • 周期:20ms(50Hz)
  • 高电平时间:0.5ms~2.5ms
  • 对应角度:0°~180°

二、所需材料

材料 数量 说明
51单片机最小系统板 1个 STC89C52/STC12C5A60S2等
SG90舵机 1个 最常用的小型舵机
杜邦线 3根 连接用
USB转TTL模块 1个 下载程序用
5V电源 1个 舵机需要单独供电

三、电路连接

复制代码
舵机红线  →  5V电源正极
舵机棕线  →  5V电源负极
舵机橙线  →  P1.0(信号线)

单片机VCC →  5V电源正极
单片机GND →  5V电源负极

重要 :舵机电流较大(约200-500mA),不要直接从单片机引脚取电!

四、代码

c 复制代码
#include <reg52.h>

sbit Servo = P1^0;  // 舵机信号线接P1.0

// 延时函数(12MHz晶振)
void Delay_us(unsigned int us) {
    while(us--) {
        _nop_(); _nop_(); _nop_(); _nop_();
        _nop_(); _nop_(); _nop_(); _nop_();
    }
}

// 延时函数(毫秒级)
void Delay_ms(unsigned int ms) {
    unsigned int i, j;
    for(i=0; i<ms; i++)
        for(j=0; j<123; j++);
}

// 控制舵机角度
void Servo_Angle(unsigned char angle) {
    unsigned int high_time;
    
    // 角度转换为高电平时间(0.5ms~2.5ms)
    // 公式:高电平时间 = 500 + angle * (2000/180) 微秒
    high_time = 500 + angle * 11;  // 近似计算
    
    // 产生一个PWM周期
    Servo = 1;           // 高电平开始
    Delay_us(high_time); // 保持高电平
    Servo = 0;           // 低电平
    Delay_us(20000 - high_time); // 补足20ms周期
}

void main() {
    unsigned char angle = 90;  // 初始角度90度
    
    while(1) {
        // 从0度到180度扫描
        for(angle = 0; angle <= 180; angle++) {
            Servo_Angle(angle);
            Delay_ms(20);  // 每个角度停留20ms
        }
        
        // 从180度到0度扫描
        for(angle = 180; angle > 0; angle--) {
            Servo_Angle(angle);
            Delay_ms(20);
        }
    }
}

五、进阶代码

c 复制代码
#include <reg52.h>

sbit Servo = P1^0;

unsigned int high_time = 1500;  // 默认1.5ms(90度)

// 定时器0初始化(12MHz晶振)
void Timer0_Init() {
    TMOD |= 0x01;    // 定时器0,模式1(16位)
    TH0 = 0xFE;      // 定时0.5ms初值
    TL0 = 0x33;
    ET0 = 1;         // 允许定时器0中断
    EA = 1;          // 开总中断
    TR0 = 1;         // 启动定时器0
}

// 设置舵机角度(0-180度)
void Set_Angle(unsigned char angle) {
    // 角度转换为高电平时间(0.5ms~2.5ms)
    // 500us + angle * (2000/180)us
    high_time = 500 + angle * 11;  // 近似值
}

// 定时器0中断服务函数
void Timer0_ISR() interrupt 1 {
    static unsigned int count = 0;
    
    // 重装初值(0.5ms)
    TH0 = 0xFE;
    TL0 = 0x33;
    
    count++;
    
    if(count < high_time/500) {  // 高电平时间
        Servo = 1;
    } else {
        Servo = 0;
    }
    
    if(count >= 40) {  // 20ms周期(40*0.5ms)
        count = 0;
        Servo = 1;     // 新周期开始
    }
}

void main() {
    unsigned char angle = 0;
    
    Timer0_Init();
    
    while(1) {
        // 示例:让舵机在0、90、180度之间切换
        Set_Angle(0);    // 0度
        Delay_ms(1000);
        
        Set_Angle(90);   // 90度
        Delay_ms(1000);
        
        Set_Angle(180);  // 180度
        Delay_ms(1000);
    }
}

六、制作步骤

  1. 硬件连接

    复制代码
    舵机红线 → 5V电源
    舵机棕线 → GND
    舵机橙线 → P1.0
  2. 程序烧录

    • 使用USB转TTL模块连接单片机
    • 用STC-ISP软件下载程序
  3. 测试

    • 上电后舵机会自动转动
    • 观察是否平滑转动0°→180°→0°

参考代码 最简单DIY基于51单片机的舵机控制器 www.youwenfan.com/contentcst/160854.html

七、常见问题解决

问题 可能原因 解决方法
舵机不转 电源不足 使用独立5V电源,不要用USB供电
抖动严重 PWM信号不稳定 改用定时器中断方式
角度不准 延时误差 调整high_time计算公式
只转一边 信号线接反 检查橙线是否接P1.0

八、扩展功能(可选)

  1. 电位器控制:加一个电位器,实时调节角度
  2. 按键控制:用两个按键控制角度增减
  3. 多舵机控制:使用PCA/PWM模块控制多个舵机
  4. 串口控制:通过电脑串口发送角度值

九、最简零件清单

  1. STC89C52最小系统板 ×1(5元)
  2. SG90舵机 ×1(8元)
  3. USB转TTL模块 ×1(5元)
  4. 杜邦线若干(2元)
相关推荐
fengfuyao98513 小时前
利用 STM32 和 ADS1256 进行高精度数据采集
stm32·单片机·嵌入式硬件
黑白园13 小时前
ADC读取XY二轴操纵杆数据通过I2C_GPIO模拟 控制0.96寸OLED显示
stm32·单片机·嵌入式硬件
一个平凡而乐于分享的小比特14 小时前
还在手动挡写单片机?MicroPython 一脚油门踩进 Python 硬件世界
单片机·嵌入式硬件·micropython
FreakStudio14 小时前
WIZnet-EVB-Pico2开始,用MicroPython玩转以太网开发
python·单片机·嵌入式·大学生·面向对象·技术栈·并行计算·电子diy·电子计算机
LCG元15 小时前
STM32实战:基于STM32F103的工业仪表数据采集(多路ADC)
stm32·单片机·嵌入式硬件
BT-BOX15 小时前
Stm32CubeMX+Proteus仿真--STM32外部中断
stm32·单片机·proteus
Wallystech-Linda16 小时前
DR9574 vs DR9574S — Choosing the Right IPQ9574 WiFi 7 Platform for Your Network
嵌入式硬件
森利威尔电子-17 小时前
森利威尔SL8700 降压型大功率 LED 恒流驱动器:5A/95%效率,支持 PWM/模拟调光
单片机·嵌入式硬件·集成电路·芯片·电源芯片
三佛科技-1873661339717 小时前
GP8892SEH贴片SOP7省外围5V2A隔离型原边反馈芯片直接替代MT3723
单片机·嵌入式硬件
Quinn2717 小时前
正点原子 STM32MP257 修复异核 FreeRTOS 例程 osDelay() 函数比 HAL_Delay() 延时快的问题
stm32·单片机·嵌入式硬件