打印
[应用方案]

PWM方波控制舵机

[复制链接]
564|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
juliestephen|  楼主 | 2023-5-14 19:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <reg52.h>
sbit PWMOUT = P1^7;                     //方波输出通道
sbit KEY1 = P3^0;
sbit KEY2 = P3^1;
sbit KEY3 = P3^2;
unsigned char HighRH = 0;                   //高电平重载值的高字节
unsigned char HighRL = 0;                   //高电平重载值的低字节
unsigned char LowRH = 0;                    //低电平重载值的高字节
unsigned char LowRL = 0;                    //低电平重载值的低字节
unsigned char KeySta[4] = {                 //按键的当前状态
    1,1,1,1
};
void ConfigPWM(unsigned int fr, unsigned char dc);//启动PWM,fr是频率,dc为占空比
void ClosePWM();                            //关闭方波输出
void KeyScan();                             //按键扫描函数,需在定时中断中调用
void KeyDriver();                           //按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用

void main()
{
    unsigned int i;
    EA = 1; //开总中断
    while (1)
    {
        //ConfigPWM(100, 5);                //频率100Hz,占空比10%
        for (i=0; i<40000; i++);            //不断发送ConfigPWM中的方波
        //ClosePWM();      
        KeyScan();
        KeyDriver();
    }
}
/* 配置并启动PWM,fr-频率,dc-占空比 */
void ConfigPWM(unsigned int fr, unsigned char dc)
{
    unsigned int high, low;
    unsigned long tmp;
    tmp = (11059200/12) / fr;               //计算一个周期所需的计数值
    high = (tmp*dc) / 100;                  //计算高电平所需的计数值
    low = tmp - high;                       //计算低电平所需的计数值
    high = 65536 - high + 12;               //计算高电平的重载值并补偿中断延时
    low = 65536 - low + 12;                 //计算低电平的重载值并补偿中断延时
    HighRH = (unsigned char)(high>>8);      //高电平重载值拆分为高低字节
    HighRL = (unsigned char)high;
    LowRH = (unsigned char)(low>>8);        //低电平重载值拆分为高低字节
    LowRL = (unsigned char)low;
    TMOD &= 0xF0;                           //清零T0 的控制位
    TMOD |= 0x01;                           //配置T0 为模式1
    TH0 = HighRH;                           //加载T0 重载值
    TL0 = HighRL;
    ET0 = 1;                                //使能T0 中断
    TR0 = 1;                                //启动T0
    PWMOUT = 1;                             //输出高电平
}
/* 关闭PWM */
void ClosePWM()
{
    TR0 = 0;                                //停止定时器
    ET0 = 0;                                //禁止中断
    PWMOUT = 0;                             //输出低电平
}
/* 按键扫描函数,需在定时中断中调用 */
void KeyScan()                             
{
    unsigned char i;
    static unsigned char keybuf[4] = { //按键扫描缓冲区
    0xFF, 0xFF, 0xFF, 0xFF
    };
    //按键值移入缓冲区
    keybuf[0] = (keybuf[0] << 1) | KEY1;  //按键按下的时候,KEY会变成0XFF,使得keybuf = 0x00
    keybuf[1] = (keybuf[1] << 1) | KEY2;
    keybuf[2] = (keybuf[2] << 1) | KEY3;
    //消抖后更新按键状态
    for (i=0; i<3; i++)
    {
        if (keybuf == 0x00)
        { //连续8 次扫描值为0,即16ms 内都是按下状态时,可认为按键已稳定的按下
            KeySta = 0;
        }
        else if (keybuf == 0xFF)
        { //连续8 次扫描值为1,即16ms 内都是弹起状态时,可认为按键已稳定的弹起
            KeySta = 1;
        }
    }
}
/* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
void KeyDriver()
{
    unsigned char i;
    static unsigned char backup[4] = {1,1,1,1};//备份按键扫描
    for (i=0; i<4; i++) //循环检测4 个按键
    {
        if (backup != KeySta)         //检测按键动作
        {                                   //如果不一样,代表该按键已经被按下
            if (backup != 0)             //按键按下时执行动作
            {
                if (i == 0)                 //按键为0,旋转-90
                {
                    ConfigPWM(50, 3);   //频率50Hz,20ms,占空比10%
                    for (i=0; i<40000; i++);
                    ClosePWM();
                           
                }
                else if (i == 1)            //按键为1,旋转0
                {
                    ConfigPWM(50, 8);   //频率50Hz,20ms,占空比3%
                    for (i=0; i<40000; i++);
                    ClosePWM();
                }
                else if (i == 2)            //按键为0,旋转90
                {
                    ConfigPWM(50, 13);  //频率50Hz,20ms,占空比8%
                    for (i=0; i<40000; i++);
                    ClosePWM();
                }
            }
        backup = KeySta;              //刷新前一次的备份值
        }
    }
}
/* T0 中断服务函数,产生PWM 输出 */
void InterruptTimer0() interrupt 1
{
    //如果一开始是高,那么中断到了之后输出低即可完成PWM
    if (PWMOUT == 1)                        //当前输出为高电平时,装载低电平值并输出低电平
    {
        TH0 = LowRH;
        TL0 = LowRL;
        PWMOUT = 0;
    }
    //如果一开始是低,那么中断到了之后输出高即可开始产生PWM
    else                                    //当前输出为低电平时,装载高电平值并输出高电平
    {
        TH0 = HighRH;
        TL0 = HighRL;
        PWMOUT = 1;
    }
}

使用特权

评论回复
沙发
yangxiaor520| | 2023-5-14 19:52 | 只看该作者
现在舵机应用还多吗?

使用特权

评论回复
板凳
keaibukelian| | 2023-6-10 11:08 | 只看该作者
航天方面,导弹姿态变换的俯仰、偏航、滚转运动都是靠舵机相互配合完成的

使用特权

评论回复
地板
xiaoqizi| | 2023-6-10 11:44 | 只看该作者
舵机主要是由外壳、电路板、无核心马达、齿轮与位置检测器所构成

使用特权

评论回复
5
wakayi| | 2023-6-10 11:55 | 只看该作者
舵机是遥控模型控制动作的动力来源,不同类型的遥控模型所需的舵机种类也随之不同

使用特权

评论回复
6
renzheshengui| | 2023-6-10 13:16 | 只看该作者
控制舵机的时候,需要不断的给PWM波才能使得舵机在某个角度有扭矩

使用特权

评论回复
7
tpgf| | 2023-6-10 13:28 | 只看该作者
舵机只能在一定角度内转动,不能一圈圈转(数字舵机可以在舵机模式和电机模式中切换,没有这个问题)。普通直流电机无法反馈转动的角度信息,而舵机可以。

使用特权

评论回复
8
chenqianqian| | 2023-6-11 15:52 | 只看该作者
现在舵机玩的少了

使用特权

评论回复
9
jf101| | 2023-7-25 13:42 | 只看该作者
现在都是伺服驱动系统

使用特权

评论回复
10
星辰大海不退缩| | 2023-7-25 14:15 | 只看该作者
有说16路驱动的?

使用特权

评论回复
11
AdaMaYun| | 2023-7-26 11:40 | 只看该作者
现在应该用伺服控制的比较多吧

使用特权

评论回复
12
LOVEEVER| | 2023-7-26 17:34 | 只看该作者
你的舵机具体是啥参数呢?

使用特权

评论回复
13
elsaflower| | 2023-8-7 07:28 | 只看该作者
将PWM信号输入到舵机控制电路中,控制电路会将PWM信号转换为直流电压,控制舵机的转动方向和速度。

使用特权

评论回复
14
wangdezhi| | 2023-8-7 08:15 | 只看该作者
根据舵机的要求,设置合适的 PWM 输出频率。通常舵机的工作频率为 50Hz,也有些舵机工作在其他频率,需确保 PWM 的频率与舵机要求一致。

使用特权

评论回复
15
pentruman| | 2023-8-7 08:29 | 只看该作者
编写程序来控制 PWM 输出引脚的频率和占空比。

使用特权

评论回复
16
houjiakai| | 2023-8-7 20:59 | 只看该作者
如何用单片机的pwm波对舵机实现调速而且不抖?

使用特权

评论回复
17
pixhw| | 2023-8-7 21:49 | 只看该作者
51单片机PWM控制舵机,为什么舵机动不起来

使用特权

评论回复
18
nomomy| | 2023-8-9 15:19 | 只看该作者
PWM程序控制舵机,求助其中的几个参数问题

使用特权

评论回复
19
xiaoyaodz| | 2023-8-9 17:10 | 只看该作者
可以通过逐步调整参数并观察舵机的运动情况来实现期望的效果。

使用特权

评论回复
20
bestwell| | 2023-8-14 11:50 | 只看该作者
参考所使用的开发平台和舵机的相关文档和示例代码

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

1091

帖子

2

粉丝