嵌入的是PWM

2023-09-21 16:45:46

PWM简介

在嵌入式系统中,PWM(脉冲宽度调制)是一种常用的技术,用于控制和生成脉冲信号,通常用于控制电机、LED亮度、音频输出等。针对STM32微控制器,它们通常具有内置的PWM控制器模块,使PWM生成相对容易。
PWM是一种用于控制电子设备的技术,通过调整信号的脉冲宽度和周期,可以模拟出不同的电压或功率级别。
在这里插入图片描述

频率、占空比和极性

脉冲宽度调制(PWM)中,频率、占空比和极性是重要的参数,用于控制和描述生成的PWM信号的特性。下面我将解释这些概念:

脉冲宽度调制在这里插入图片描述

频率(Frequency):

定义:PWM信号的频率是指在一个周期内脉冲的数量,通常以赫兹(Hz)为单位表示。一个完整的PWM周期是一个波形从最小值变化到最大值,然后再返回的时间。

作用:频率决定了PWM信号的周期,即脉冲的时间间隔。较高的频率通常意味着更短的周期,脉冲变化得更快。频率对于控制电机速度、LED亮度、音频输出等应用非常重要,因为它决定了信号的响应速度。

占空比(Duty Cycle):

在这里插入图片描述

定义:占空比是指PWM信号中高电平(高电平时间)所占的百分比。它表示脉冲的宽度相对于整个周期的比例。通常以百分比表示,范围从0%(全低电平)到100%(全高电平)。

作用:占空比决定了PWM信号的强度或效果。例如,在LED控制中,较高的占空比表示LED亮度更高。在电机控制中,占空比可以表示电机的速度控制,更高的占空比通常表示更高的速度。

极性(Polarity):

定义:PWM信号的极性指的是脉冲的电平是如何定义的。通常有两种极性:正极性和负极性。在正极性PWM中,高电平表示正逻辑(例如,高电平表示LED亮、电机正转等),而在负极性PWM中,高电平表示负逻辑。

作用:极性确定了在特定应用中高电平和低电平的含义。这对于与其他电路或设备进行交互时非常重要,以确保信号正确地被解释和控制。

以下是在STM32中使用PWM的一般步骤:

1 初始化

初始化:首先,你需要初始化所选的STM32引脚作为PWM输出。通常,STM32引脚有多种功能,你需要将其配置为PWM输出模式。这通常涉及到使用HAL库或标准的寄存器级编程方法来配置GPIO引脚。

配置PWM模块

配置PWM模块:接下来,你需要配置PWM模块。STM32通常有多个定时器(Timer),每个定时器都可以用于生成PWM信号。你需要选择一个合适的定时器,并配置它的时钟分频、计数周期等参数。

配置PWM通道:

配置PWM通道:定时器通常具有多个PWM通道。你需要选择一个通道,并配置其参数,如PWM信号的占空比(脉冲宽度与周期的比例)。

启动PWM:

启动PWM:一旦配置完成,你可以启动定时器,它将开始生成PWM信号。

控制PWM输出

控制PWM输出:根据你的应用,你可以在运行时更改PWM的占空比,以实现不同的控制效果。这通常涉及到修改PWM通道的占空比寄存器。

以下是使用STM32的HAL库来生成PWM的代码示例(具体的STM32型号可能有所不同)控制无刷电机的:

#include "stm32f10x.h"

// 定义PWM参数
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

// 定义电机控制参数
#define PWM_PERIOD 1000   // PWM周期(例如,1000个计数)
#define MOTOR_SPEED 500   // 初始电机速度(占空比)

// 电机控制初始化函数
void MotorControl_Init() {
  // 初始化SysTick定时器,用于产生1毫秒的时间基准
  SysTick_Config(SystemCoreClock / 1000);

  // 初始化TIM3定时器用于PWM生成
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  
  TIM_TimeBaseStructure.TIM_Prescaler = 0;                        // 不分频
  TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD - 1;               // PWM周期
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;                    // 不分频
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;      // 向上计数模式
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  // 配置TIM3通道1为PWM模式
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = MOTOR_SPEED;                    // 初始占空比
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;        // 输出高电平有效
  TIM_OC1Init(TIM3, &TIM_OCInitStructure);

  // 启动TIM3定时器
  TIM_Cmd(TIM3, ENABLE);
  
  // 启动TIM3通道1
  TIM_CtrlPWMOutputs(TIM3, ENABLE);
}

// 设置电机速度
void SetMotorSpeed(uint16_t speed) {
  TIM3->CCR1 = speed;
}

int main(void) {
  // 初始化电机控制
  MotorControl_Init();

  while (1) {
    // 在这里可以根据需要调整电机速度
    SetMotorSpeed(800);  // 例如,设置电机速度为80%
    
    // 延时或执行其他任务
    // ...
  }
}

// SysTick中断处理函数,用于产生1毫秒的时间基准
void SysTick_Handler(void) {
  // 递增操作等
}


更多推荐

【软件工程】软件工程之道—《人月神话》读后思考

目录写在前面1图书介绍2读后思考写在前面《人月神话》是一本由弗雷德里克·布鲁克斯(FrederickP.Brooks)所著的计算机科学经典著作。这本书首次出版于1973年,至今仍然被认为是计算机科学领域的重要参考书籍之一。它对我产生了深远的影响。通过作者弗雷德里克·布鲁克斯的深入剖析和丰富的实践经验,我对软件开发项目的

✔ ★ 算法基础笔记(Acwing)(三)—— 搜索与图论(17道题)【java版本】

搜索与图论1.DFS1.排列数字(3分钟)2.n-皇后问题2.BFS(队列)1.走迷宫二刷总结(队列存储一个节点pair<int,int>)三刷总结走过的点标记上距离(既可以记录距离,也可以判断是否走过)★★例题2.八数码二刷总结3.树与图的dfs1.树的重心二刷总结1.如何找根节点?用无向图遍历,则不需要根节点2.把

红与黑(bfs + dfs 解法)(算法图论基础入门)

红与黑问题文章目录红与黑问题前言问题描述bfs解法dfs解法前言献给阿尔吉侬的花束(入门级bfs查找+模版解读+错误示范在之前的博客当中,详细地介绍了这类题目的解法,今天为大家带来一道类似的题目练练手,后续还会更新更有挑战的题目以及更为详细的解析,喜欢的小伙伴可以点个关注啦!问题描述有一间长方形的房子,地上铺了红色、黑

8个很棒的Vue开发技巧

1.路由参数解耦通常在组件中使用路由参数,大多数人会做以下事情。exportdefault{methods:{getParamsId(){returnthis.$route.params.id}}}在组件中使用$route会导致与其相应路由的高度耦合,通过将其限制为某些URL来限制组件的灵活性。正确的做法是通过prop

实现 3D 倒计时器

构建单个倒计时器卡片实现思路从上述的总体效果图来看,单个倒计时器的卡片主要是分为头部为尾部两个部分,所以我们可以采用flex布局来实现整体的布局,并且利用flex布局实现文字内容的布局。具体实现步骤如下:编写HTML结构<divclass="flip_cardflip"><divclass="top">4</div><

openGauss学习笔记-69 openGauss 数据库管理-创建和管理普通表-更新表中数据

文章目录openGauss学习笔记-69openGauss数据库管理-创建和管理普通表-更新表中数据openGauss学习笔记-69openGauss数据库管理-创建和管理普通表-更新表中数据修改已经存储在数据库中数据的行为叫做更新。用户可以更新单独一行、所有行或者指定的部分行。还可以独立更新某个字段,而其他字段则不受

英国8月CPI意外降温,然而加息决定仍悬而未决

KlipC报道:据英国国家统计局公布最新数据显示,8月CPI同比上涨6.7%,低于上月数据,核心CPI增幅低于经济学家的预测。数据公布后,英镑走弱、英债收益率下跌,英镑应声下跌0.5%至5月以来的最弱水平,两年期英债债券收益率下跌至4.298%。KlipC的合伙人AndiD表示:“8月CPI涨幅微降主要原因是食品价格涨

西门子828d授权密钥破解经验分享 I7I54833762

操作数组的方法Array.prototype.toSorted(compareFn)//返回一个新数组,其中元素按升序排序,而不改变原始数组。Array.prototype.toReversed()//返回一个新数组,该数组的元素顺序被反转,但不改变原始数组。Array.prototype.toSpliced(star

【Qt】Unicode编码作用 ,以及在Qt中的理解

Unicode编码是一种字符编码标准,它为世界上几乎所有的字符都分配了一个唯一的数字标识符,以便在计算机系统中进行存储和处理。Unicode编码的作用有以下几点:统一字符表示:Unicode编码提供了一个统一的字符集,使得不同语言、不同文化背景的字符都能够被准确地表示和处理。它包括了世界上几乎所有的字符,包括字母、数字

【VS2019 Qt5 VTK9.2】界面编程问题&解决记录

一、Qt和VTK相关问题及解决1.Widget和Viewer的设置顺序imageViewer->SetupInteractor(renderWindow->GetInteractor());ui.qvtkWidget->setRenderWindow(imageViewer->GetRenderWindow());二者

C++ 里 ++i 是原子操作吗?

1.什么是原子操作在多线程环境下,原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何contextswitch(切换到另一个线程)。原子操作可以确保某些特定操作在多线程条件下,不会由于线程切换而导致数据污染。比如,对一个变量的读/写操作,就是一个常见的需要原子化的场景。如果把这

热文推荐