当前位置: 首页 > news >正文

第六章第四节 PWM驱动LED呼吸灯 PWM驱动舵机 PWM驱动直流电机

1. PWM 驱动 LED 呼吸灯

① Keil 中常见的英文注释

        Specifies the output polarity.

        This parameter can be a value of @ref TIM_Output_Compare_Polarity

  • 整句翻译:指定输出极性。此参数可以是 @ref TIM_Output_Compare_Polarity 中定义的一个值。
  • Specifies :动词,意为 “指定;规定;明确说明” ,在这里表示对 “输出极性” 进行设定操作。
  • the output polarity :名词短语,“输出极性” ,指的是 PWM(脉冲宽度调制)等信号输出时的电平极性相关属性,比如是高电平有效还是低电平有效。
  • This parameter :“此参数;这个参数” ,指代用于设置输出极性的参数

② 核心原理:利用PWM 极性驱动,通过占空比变化控制 LED 亮度渐变,模拟呼吸效果。高电平点亮、低电平熄灭,占空比越高(高电平占比大 ),LED 越亮;占空比越低,LED 越暗 。

③ 函数:

(1) 用结构体初始化输出比较单元:

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
  • TIM_OC1Init ()、TIM_OC2Init ()、TIM_OC3Init ()、TIM_OC4Init () 这四个函数为同类型通道初始化函数,核心功能与参数结构完全一致,仅操作的定时器通道不同(对应通道 1-4)。

(2) 单独更改 CCR 寄存器值的函数:

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);  
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);  
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);  
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);  
  • 作用:直接修改定时器 TIMx 的通道 1~4 对应的比较寄存器(CCR)值,控制 PWM 占空比或比较触发时机。

④ PWM.c 模块

(1) 有效电平 = "正在充电" 的状态:

  • 当充电器正在给手机供电时(比如线里有电流),就像 PWM 的 "有效电平"—— 这是有实际作用的状态。
  • 在代码里,我们需要指定 "有效电平是高电平还是低电平",就像规定 "有电流 = 正在充电" 还是 "没电流 = 正在充电"。

(2) 无效电平 = "停止充电" 的状态:

  • 当充电器停止供电时(比如线里没电流),就像 PWM 的 "无效电平"—— 这是不发挥作用的状态。
  • 它和有效电平总是相反的:如果有效是 "有电流",无效就是 "没电流"。

(3) 极性 = 定义 "什么是有效"

  • 极性就像充电的 "判断标准"
    • TIM_OCPolarity_High(高电平有效):相当于规定 "线里有电流 = 正在充电(有效)"
    • TIM_OCPolarity_Low(低电平有效):相当于规定 "线里没电流 = 正在充电(有效)"

(4) PWM 输出比较配置

TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure); 
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
TIM_OCInitStructure.TIM_Pulse = 0; 
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
  • TIM_OCStructInit:给输出比较结构体赋默认值,方便后续只修改需要的参数,避免未初始化成员出问题 。
  • TIM_OCMode:输出比较模式,TIM_OCMode_PWM1 是 PWM 模式 1。工作逻辑:当定时器计数值小于 TIM_Pulse 时,输出有效电平(由 TIM_OCPolarity 决定);计数值大于等于 TIM_Pulse 时,输出无效电平 。
  • TIM_OCPolarity:输出极性,TIM_OCPolarity_High 表示有效电平为高电平,即满足计数值条件时,引脚输出高电平,反之低电平 。
  • TIM_OutputState:输出使能,TIM_OutputState_Enable 开启输出比较功能,让定时器能通过引脚输出电平变化 。
  • TIM_Pulse:比较值(对应 CCR 寄存器值),决定 PWM 占空比。初始设为 0,意味着占空比为 0%(计数值小于 0 不成立,一直输出无效电平 ),后续可通过 PWM_SetCompare1 函数修改 。

2. PWM 驱动舵机

① Servo.c 模块:

#include "stm32f10x.h"
#include "PWM.h"  // 依赖 PWM.c 的功能// 舵机初始化:直接调用 PWM_Init() 复用底层配置
void Servo_Init(void)
{PWM_Init();  
}// 设置舵机角度:将角度转换为 PWM 占空比
void Servo_SetAngle(float Angle)
{// 角度 → 占空比映射:// 0° → 500(对应 0.5ms 高电平),180° → 2500(对应 2.5ms 高电平)// 公式:Compare = Angle/180 * 2000 + 500 PWM_SetCompare2(Angle / 180 * 2000 + 500);  
}

(1) 角度映射逻辑

  • 舵机控制要求:0.5ms 高电平 → 0°,2.5ms 高电平 → 180°(不同舵机可能有差异,需校准)
  • 占空比计算:
    • 总有效范围:2500 - 500 = 2000(对应 180° 角度差)
    • 公式推导:Compare = 500 + (Angle / 180) * 2000

② main.c 模块

int main(void)
{// 初始化 OLED 显示屏,执行完后 OLED 可以开始工作,比如显示内容OLED_Init(); // 初始化舵机,让舵机进入可控制状态,准备接收角度控制指令Servo_Init(); // 初始化按键,配置好按键相关的硬件,让程序能正确读取按键状态Key_Init(); // 在 OLED 第 1 行第 1 列的位置显示字符串 “Angle:”,用于提示后面显示的是角度值OLED_ShowString(1, 1, "Angle:"); while (1)  // 无限循环,程序会一直执行循环里的内容{// 读取按键编号,Key_GetNum 函数会检测按键状态,返回对应的按键值(比如按下哪个按键)KeyNum = Key_GetNum(); if (KeyNum == 1)  // 判断是否是按键 1 被按下{Angle += 30;  // 按键 1 按下一次,角度增加 30 度if (Angle > 180)  // 因为舵机通常最大角度是 180 度,超过后让角度回到 0 度,实现循环{Angle = 0;  }}// 根据 Angle 变量的值设置舵机转动到对应的角度,Servo_SetAngle 函数内部会处理舵机控制的时序等Servo_SetAngle(Angle); // 在 OLED 第 1 行第 7 列的位置显示 Angle 变量的值,显示 3 位数字(比如 000、030、180 等)OLED_ShowNum(1, 7, Angle, 3); }
}

(1) 简单总结程序流程:

  • 先初始化 OLED、舵机、按键这些外设,让它们能正常工作。
  • 在 OLED 上显示角度提示文字。
  • 进入无限循环,不断检测按键状态:
    • 若按键 1 按下,角度增加 30 度,超过 180 度就重置为 0 度。
    • 然后根据当前角度值控制舵机转动,同时在 OLED 上显示实时的角度数值 。

3. PWM 驱动直流电机

void Motor_SetSpeed(int8_t Speed)
{// 1. 控制电机方向(正转/反转)if (Speed >= 0) {// Speed ≥ 0 → 正转:PA4 高电平,PA5 低电平GPIO_SetBits(GPIOA, GPIO_Pin_4);    // PA4 = 1GPIO_ResetBits(GPIOA, GPIO_Pin_5);  // PA5 = 0} else {// Speed < 0 → 反转:PA4 低电平,PA5 高电平GPIO_ResetBits(GPIOA, GPIO_Pin_4);  // PA4 = 0GPIO_SetBits(GPIOA, GPIO_Pin_5);    // PA5 = 1}// 2. 控制电机转速(PWM 占空比)PWM_SetCompare3( Speed >= 0 ? Speed : -Speed ); /* - Speed 是负数时,取绝对值(-Speed),保证占空比为正。- PWM_SetCompare3(xxx):修改定时器的比较寄存器(CCR),直接改变 PWM 占空比 → 电机转速变化。*/
}

① 关键参数解析:

(1) int8_t Speed:速度控制参数

  • 数据类型:int8_t(有符号 8 位整数),取值范围为 - 128 至 127
  • 符号意义:正号表示正转,负号表示反转
  • 绝对值意义:代表 PWM 占空比的大小,决定电机转速(值越大转速越快)

(2) 电机转速控制部分:

// 控制电机转速(PWM占空比)
PWM_SetCompare3( Speed >= 0 ? Speed : -Speed ); 
  • 使用三元运算符获取 Speed 的绝对值(确保占空比为非负数)
  • 通过PWM_SetCompare3()函数设置定时器的比较寄存器值
  • 比较寄存器的值直接决定 PWM 信号的占空比:
    • 占空比 = (比较值 / 自动重装载值) × 100%
    • 占空比越高,电机获得的平均电压越高,转速越快
http://www.dtcms.com/a/321871.html

相关文章:

  • 计算机网络:到底什么是可变长子网掩码VLSM?
  • win11中Qt5.14.0+msvc2019+opencv4.9配置
  • 全方位无限随机地图实现指南
  • 模块 PCB 技术在未来通信领域的创新突破方向
  • Docker 创建镜像错误记录
  • Java技术栈/面试题合集(21)-Docker篇
  • 如何动态执行 JS 脚本
  • 揭秘Java synchronize:轻量级锁升级与偏向锁
  • Java-注解
  • 重新 mybatis plus 的 撒着OrUpdate 方法,实现根据自定义字段插入或者修改
  • P1044 [NOIP 2003 普及组] 栈
  • B4263 [GESP202503 四级] 荒地开垦 题解
  • 【工作笔记】Docker Desktop一直转圈加载不出来然后报错
  • 提升LLM服务效率的秘密武器——vLLM!
  • Docker 安装 Redis
  • 机柜中不同类型板卡的操作系统配置情况一览
  • 解决苍穹外卖项目中 MyBatis - Plus 版本冲突问题
  • 【Linux运维】深入理解Cookie与Session机制:安全性与性能的平衡艺术
  • SAP接口日志查询
  • 多级缓存架构:新品咖啡上线引发的数据库压力风暴与高并发实战化解方案
  • 数据返回后需要刷新才会展示的解决方法
  • Vue3 组合式API
  • 飞算JavaAI深度解析:专为Java生态而生的智能引擎
  • 快速了解svm算法
  • Java 执行 SFTP 文件上传和下载
  • ​​《深入浅出K-means算法:从原理到实战全解析》​预告(提纲)
  • 【Spring Boot 快速入门】八、登录认证(一)基础登录与认证校验
  • 阿里巴巴高级Java工程师面试算法真题解析:LRU Cache实现
  • 详解 RT-Thread 串口一配置、设备查找与打印功能(rt_kprintf)的绑定机制
  • 完整设计 之 运行时九宫格 (太乙九宫 播放器)