学习STC51单片机12(芯片为STC89C52RC)

有点脑子烧焦的感觉了老xi们

初识PWM(可以用来开发舵机)

PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进

行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通

过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的

时间占据整个信号周期的百分比,例如方波的占空比就是50%

这个看看就好 ,真的是天马行空.....

  1. 脉冲宽度调制
  2. 通过占空比编码模拟信号
  3. 占空比 一个波形周期内,高电平占据时长的百分比(面试会问)

        就是这样的信号我们称为PWM,之前我们继电器或者是LED都是传低电平或者是高电平,就可以让他运转,现在这个舵机单单传高电平或者低电平是没有用的,舵机的运转要用PWM这样的波形信号来运转,就是一个周期内有高电平和低电平搭配才能运转舵机,然后高电平占据市场的百分比又是控制舵机旋转角度的关键,所以这个占空比也很重要

但是很尴尬的是我们这个c51RC没有PWM外设的口,加强版的有,这个看原理图就知道了

我们的                                                                         新版的

主要是看芯片上面有PWM的口的芯片原理图是什么样的就好

那么我没有PWM口怎么办 ,那么就需要用io口模拟出来这个PWM波形,用软件来模拟,其实就是用编程啦,用上定时器,一段时间是高电平,一段时间是低电平的,就可以模拟出来了,但是相较于硬件来说,精准度比较差

Tips:在单片机等设备中,一方面可以利用特定的定时器等硬件模块,通过复用 IO 口输出 PWM 信号,这些复用 IO 口具备专门的 PWM 输出功能,能产生高精度、高频率的 PWM 波形 ;另一方面,也能用普通 IO 口模拟 PWM 信号,通过在代码里精确控制 IO 口电平的高低变化时间,来实现高低电平周期性变化,进而模拟出 PWM 波形 ,不过这种方式产生的 PWM 信号精度和频率相对有限 。

  • 硬件 PWM:由硬件电路(如单片机内部特定的定时器、计数器等模块 )直接产生 PWM 信号。像 STM32 单片机的定时器外设,能精准控制脉冲的频率、占空比 ,具备高精度、高稳定性和高速度的优势,可产生高频且准确的 PWM 波形,适用于对实时性、精度要求高的场景,如电机精确调速、伺服系统控制 。
  • 软件模拟 PWM:借助普通 IO 口,通过软件编程(如在单片机中利用定时器中断 )来控制 IO 口电平高低变化时间,模拟出 PWM 波形。例如 51 单片机常利用定时器中断改变 IO 口电平持续时间实现占空比调节 。其优势是无需额外硬件资源,成本低、灵活性高;缺点是精度和频率受限于软件执行速度和定时器精度,难以产生高频、高精度 PWM 信号,一般用于对精度和频率要求不高的简单控制场景,如简易 LED 亮度调节 。

因为这个pwm的一个周期为20ms  所以我们要用到定时器,设置定时器的初值,当爆表的时候执行什么操作是解决舵机问题的关键

Sg90舵机图

2. 怎么控制舵机

向黄色信号线“灌入”PWM信号。

PWM波的频率不能太高,大约50HZ,即周期=1/频率=1/50=0.02s,20ms左右

数据:

0.5ms-------------0度; 2.5% 对应函数中占空比为250

1.0ms------------45度; 5.0% 对应函数中占空比为500

1.5ms------------90度; 7.5% 对应函数中占空比为750

2.0ms-----------135度; 10.0% 对应函数中占空比为1000

2.5ms-----------180度; 12.5% 对应函数中占空比为1250

定时器需要定时20ms, 关心的单位0.5ms, 40个的0.5ms,初值0.5m cnt++

1s = 10ms * 100

20ms = 0.5ms * 40

        舵机从一个角度转动到另一个角度需要物理时间(通常为几百毫秒)。如果没有 Delay2000ms(),主程序会立即执行 jiaodu=1;,导致舵机收到新角度指令而中断当前转动。通过延时 2 秒:

这个舵机的话我们把这个延时改成300ms你会发现转得特别的快,他不是因为你改变了舵机的转速,而是你提前改变了舵机的方向,甚至舵机没有到相应的角度就去下一个角度了,只是视觉上面看着快,就是说舵机从一个角度到一个角度是有最小的时间的,那个都有好几百毫秒,如果设置比这个时间还少的延时,那么是不是没有到达对应的角度就换角度了,那么这个程序就是无作用的

这个舵机真的有说法

        这个代码是想要控制舵机从0度到90度 的代码并且想要初始化为0度,就是舵机从0度开始变化

还有一种情况,后面我们经过添加延时函数发现,每次无论初始化为什么角度,舵机都会有一个归位为0度开始的动作,然后再转动到我们设定的初始角度,当然这种情况在你想要设置初始值为0度的时候看不出来

        

当然我们可以分析一下

这个是我们设置初始值为 135度角的时候 ,代码是怎么运行的呢?

        我们每爆表一次都会进入中断,第一个count=1;那么此时count <jd,那么执行sg90=1;

其实你只要看得懂上面这张图就很好知道了,就是说这个高电平占有比例是随着时间的推移而升高的,因为你看上方这张图片当count=4的时候那是不是之前的高电平就已经满足4个0.5ms了,我不懂这样解释你们能不能接受......

关于舵机控制代码的两个版本分析

版本 1:未添加延时(可能存在首个周期波形异常)就是那个delay10ms();

如果代码中不添加延时,程序执行逻辑如下:

  1. 首次中断触发:定时器启动后,首个 0.5ms 溢出时进入中断,此时会将电平设置为低电平(SG90=0)。
  2. 主程序执行时序
    1. 首次中断后,第二个 0.5ms 溢出前,主程序可能已进入while循环,执行角度切换代码(如jiaodu=3)。
    2. 关键问题:首个 20ms 周期内,可能因主程序提前修改角度,导致 PWM 波形中途突变(例如从 0 度的 0.5ms 高电平,突变为 90 度的 1.5ms 高电平)。
  3. 舵机的实际反应
    1. 尽管首个周期波形不完整(占空比异常突变),但舵机通过平均脉冲宽度识别角度,单个异常周期对最终位置影响较小。
    2. 现象:舵机可能在启动时轻微抖动,但后续角度切换正常。
版本 2:添加延时(确保首个周期波形完整)

在初始化阶段添加延时(如Delay10ms()),程序执行逻辑如下:

也就是你充足的给足了时间给画波形  那么也最好充足的满足舵机转动的时间一般是几百毫秒 ,要是手中舵机的状态是一个不是0度的度数,这样你就可以清楚的看到舵机会回到0度开始,随后等待剩下的延时后开始while里面的角度

  1. 时序保障
    1. 延时确保在进入while循环前,定时器已完成多个完整的 PWM 周期(如 20 个周期,共 10ms)。
    2. 首个周期的jiaodu=1(0 度)能稳定输出 0.5ms 高电平 + 19.5ms 低电平的完整波形。
  2. 舵机的实际反应
    1. 舵机从 0 度开始平稳转动,无启动抖动,后续角度切换逻辑与波形完全一致。
    2. 优势:代码行为与预期完全匹配,便于调试和理解,稳定性更高。

Tips:

一、延时函数的计时本质:纯软件空转

1. 延时函数如何计时?

延时函数(如Delay10ms())的核心是通过 CPU 执行空循环指令 来消耗时间。例如:

void Delay10ms() {

    unsigned char i, j;

    i = 18; j = 235;

    do { while (--j); } while (--i); // 循环次数固定,靠指令执行速度计算时间}

  • 计时依据:单片机的晶振频率(如 11.0592MHz)决定了每条指令的执行时间,循环次数 × 单指令时间 = 总延时时间。
  • 关键点延时时间仅由代码逻辑和 CPU 性能决定,与外部硬件(如舵机)的物理动作 完全无关
2. 延时期间 CPU 在做什么?
  • CPU 会持续执行循环指令,直到延时结束,期间不会处理任何其他任务(包括检测舵机状态或修改 PWM 信号)。
  • 此时,舵机是否转动、转动多久,取决于 PWM 信号是否在延时前已设置好
    • 若延时前已设置目标角度的 PWM(如 0 度),则舵机从延时开始时启动转动,边转动边等待 CPU 延时结束
    • 延时函数的计时只是 “CPU 自己在数循环次数”,不关心舵机的转动是否完成

二、舵机转动的时间:纯硬件物理动作

1. 舵机何时开始转动?
  • 舵机接收到新的 PWM 信号(对应目标角度)时,立即启动转动。例如:

set_servo_angle(0); // 设置0度对应的PWM,舵机开始转动Delay1000ms(); // 启动延时

    • 转动起始点:执行set_servo_angle(0)时,舵机开始转动。
    • 延时起始点:执行Delay1000ms()时,CPU 开始空转计时。
    • 两者同时开始,但属于独立过程:舵机的转动由硬件驱动,延时由软件控制。
2. 延时时间与转动时间的时间轴关系

假设:

  • 舵机转动到 0 度需要 200ms(硬件特性)。
  • 延时函数设置为 1000ms(软件计时)。
    则时间轴如下:

0ms       200ms      1000ms

├─────────┼───────────┼─────────┤

| set_servo(0)       |         |

| 舵机开始转动       | 转动完成 |

| CPU开始延时        |         | 延时结束

  • 0~200ms:舵机转动,CPU 空转延时。
  • 200~1000ms:舵机已停在 0 度,CPU 继续空转剩余 800ms。
  • 结论延时时间(1000ms)包含了舵机转动时间(200ms)和额外等待时间(800ms),但这是时间上的自然重叠,而非延时函数 “主动包含” 了转动时间。

三、常见误区:延时函数 “等待舵机转动” 的本质

1. 为什么需要延时?
  • 舵机转动需要时间,若不延时,程序可能在舵机未到位时就执行后续操作(如修改角度),导致动作混乱。
  • 延时的目的是 “人为让 CPU 等待足够久”,确保舵机有充足时间完成转动而非 “计时包含转动过程”。
2. 延时时间如何设定?
  • 保守策略:假设舵机最大转动时间为 T_max(如转动 180 度需要 1.8 秒),则延时设为 T_delay ≥ T_max(如 2 秒),确保无论初始角度如何,都能转动到位。
  • 精准策略:通过公式计算转动时间(角度差 ÷ 转速),再设置延时为计算值 + 安全余量。
    例如:转动 60 度需要 0.6 秒(转速 100 度 / 秒),延时设为 0.7 秒。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

真的想上岸啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值