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

第六章第四节 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.xdnf.cn/news/17225.html

相关文章:

  • Kotlin反射
  • 暴力解决MySQL连接失败
  • 从0配置yolo实例分割(ubuntu)
  • springBoot集成minio并实现文件的上传下载
  • OpenAI 开源模型 GPT-OSS MCP服务器深度解密:从工具集成到系统提示全自动化,浏览器+Python无缝协同的底层逻辑
  • 轻松实现浏览器自动化——AI浏览器自动化框架Stagehand
  • 【R语言】重新绘制高清MaxEnt的单因素响应曲线图像
  • 写Rust GPU内核驱动:GPU驱动工作原理简述
  • 告别Cursor!最强AI编程辅助Claude Code安装到使用全流程讲解
  • Beelzebub靶机
  • 第二十七天(数据结构:图)
  • Linux线程学习
  • Flutter 局部刷新方案对比:ValueListenableBuilder vs. GetBuilder vs. Obx
  • 力扣经典算法篇-46-阶乘后的零(正向步长遍历,逆向步长遍历)
  • 了解大型语言模型:力量与潜力
  • 什么是键值缓存?让 LLM 闪电般快速
  • 每日五个pyecharts可视化图表-bars(6)
  • 关于Android studio调试功能使用
  • 2025年主流开源音视频播放项目深度解析
  • MCU中的USB
  • 聚众识别场景误报率↓76%:陌讯动态密度估计算法实战解析
  • 【C语言】深入理解编译与链接过程
  • 前后端加密传数据实现方案
  • OpenCV入门:图像处理基础教程
  • [优选算法专题一双指针——两数之和](双指针和哈希表)
  • Qwen-Image开源模型实战
  • Spring、Spring MVC、MyBatis 和 Spring Boot的关系
  • 防火墙环境下的全网服务器数据自动化备份平台搭建:基于 rsync 的完整实施指南
  • 板块三章节3——NFS 服务器
  • 秋招笔记-8.7