当前位置: 首页 > 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.lryc.cn/news/614664.html

相关文章:

  • 校招秋招春招小米在线测评小米测评题库|测评解析和攻略|题库分享
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘huggingface_hub’问题
  • Numpy科学计算与数据分析:Numpy高效数据处理与优化
  • Mac 电脑放在环境变量中的通用脚本
  • 免费PDF批量加密工具
  • 从零掌握 Java AWT:原理、实战与性能优化
  • 【沉浸式解决问题】pycharm关闭科学模式
  • 杰理ac791 [Info]: [LL_S]Recv - LL_CHANNEL_MAP_REQ
  • Python从入门到精通计划Day07: Python数据卷轴术:文件魔法与防御结界全指南
  • nlp-语义分析
  • 在 Vue 中使用 ReconnectingWebSocket实现即时通讯聊天客服功能
  • Java 使用 SSHJ 执行 SSH 命令和 SFTP 文件上传和下载
  • 【前端后端部署】将前后端项目部署到云服务器
  • Redis(④-消息队列削峰)
  • 吴恩达 深度学习笔记
  • Coze Studio 概览(九)--插件管理
  • 配电线路故障定位在线监测装置的技术解析与应用价值
  • 应急响应流程
  • 基于 C++ 的湍流数值模拟理论报告
  • 从零构建桌面写作软件的书籍管理系统:Electron + Vue 3 实战指南
  • 中小业务遭遇网络攻击,防护能力不足的解决办法​
  • electron 静默安装同时安装完成后自动启动(nsis)
  • Spark在什么情况下CBO才会判断失误,如何避免
  • 服务器登上去,显示 failed to send WATCHDOG 重启有效吗?
  • Uber的MySQL实践(一)——学习笔记
  • I/O原理与服务。
  • 智慧交通场景下 mAP↑28%:陌讯多模态融合算法实战解析
  • OpenAI 开源模型 GPT-OSS MCP服务器深度解密:从工具集成到系统提示全自动化,浏览器+Python无缝协同的底层逻辑
  • 微软Azure AI Foundry正式上线GPT-5系列模型
  • CORS 跨域问题 Next.js 跨域问题放通