STM32 学习10 PWM输出

STM32 学习10 PWM输出

  • 一、PWM简介
    • 1. PWM的概念
    • 2. PWM的工作原理
    • 3. PWM 常用的应用场景
  • 二、一些概念
    • 1. 频率
    • 2. 占空比
  • 三、STM32F1 PWM介绍
    • 1. 定时器与寄存器
      • (1)**自动重装载寄存器(ARR)**:
      • (2)**比较寄存器(CCR)**:
    • 2. PWM的输出模式
      • (1)PWM模式1
      • (2)PWM模式2
    • 3. 边沿对齐与中心对齐
      • (1)边沿对齐模式
      • (2)中心对齐模式
  • 四、PWM输出配置步骤
    • 1. 使能定时器及端口时钟
    • 2. 定时器的重映像
      • (1)定时器4复用功能重映像
      • (2)定时器3复用功能重映像
      • (3) 定时器2复用功能重映像
    • 3. 输出端口复用
    • 4. 初始化定时器参数
    • 5. 初始化PWM输出参数
    • 6. 开启定时器
    • 7. 修改TIMx_CCRx的值控制占空比
    • 8. 使能 TIMx 在 CCRx 上的预装载寄存器
    • 9. 使能 TIMx 在 ARR上的预装载寄存器允许位
    • 10. 设置 MOE位
  • 五、代码示例
    • 1. pwm_utils.h
    • 2. pwm_utils.c
    • 3. main函数实现

一、PWM简介

1. PWM的概念

PWM的全称是脉冲宽度调制(Pulse Width Modulation),是一种控制模拟信号的方法。它通过改变脉冲的宽度来控制模拟信号的平均值。

2. PWM的工作原理

PWM的工作原理是将一个周期性的脉冲信号与一个控制信号进行比较。当控制信号大于脉冲信号时,输出高电平;当控制信号小于脉冲信号时,输出低电平。通过改变脉冲信号的宽度,可以控制输出信号的平均值。

输出信号的平均值连在一起,可以达到模拟信号的效果,如下图所示:
wikipedia示例

3. PWM 常用的应用场景

  • 电机控制:用于控制电机的速度和方向;
  • 照明控制:用于控制灯光的亮度;
  • 电源管理:用于控制电源的输出电压;
  • 音频控制:用于控制声音的大小。

二、一些概念

1. 频率

PWM波形在单位时间内重复出现的次数。

2. 占空比

PWM波形中高电平信号所占的比例。

三、STM32F1 PWM介绍

1. 定时器与寄存器

STM32F1除了基本定时器TIM6和TIM7,其它定时器都可以产生PWM输出。其中:

  • TIM1和TIM8:均可同时产生7路PWM输出;
  • 其它通用定时器:均可同时产生4路PWM输出。

在STM32微控制器中,生成PWM信号通常涉及到自动重装载寄存器(ARR)和比较寄存器(CCR)两个重要的寄存器。

(1)自动重装载寄存器(ARR)

  • 通过修改ARR的值,可以调节PWM信号的周期,从而改变PWM信号的频率。
  • 当ARR增加时,整个PWM信号的周期增加,导致PWM信号的频率降低。

(2)比较寄存器(CCR)

  • 通过修改CCR的值,可以调节PWM信号的占空比,从而改变PWM信号的高电平持续时间。
  • CCR的值通常应该小于ARR的值,以确保PWM信号的占空比在0到100%之间。
  • 当CCR增加时,高电平部分的持续时间增加,导致PWM信号的占空比增加。

2. PWM的输出模式

PWM输出模式一共8种,常用的是PWM1和PWM2,其用法差不多,区别如下:
下表是PWM1和PWM2的区别:

(1)PWM模式1

在该模式下,定时器的计数器从0开始递增,

  • 当计数器的值小于CCR时,输出为高电平;
  • 当计数器的值大于等于CCR时,输出为低电平;
  • 在计数器达到ARR时,产生一个更新事件,计数器重新从0开始计数。

这种模式下,PWM信号的周期由ARR决定,占空比由CCR决定。

(2)PWM模式2

与PWM模式1相比,PWM模式2输出有效性正好是相反的。

下表是PWM1和PWM2的比较:

模式CNT 计算方式CNT<CCRCNT>CCR
PWM1递增通道CH有效通道CH无效
PWM1递减通道CH无效通道CH有效
PWM2递增通道CH无效通道CH有效
PWM2递减通道CH有效通道CH无效

3. 边沿对齐与中心对齐

(1)边沿对齐模式

  • 在边沿对齐模式下,PWM信号的起始位置位于PWM周期的起始边沿(即ARR),然后递增至CCR,再递增至ARR,最后重复此过程。
  • PWM信号的高电平和低电平都与PWM周期的边沿对齐,即从PWM周期的起始边沿开始。
  • 边沿对齐模式通常用于需要高精度输出的应用,例如需要精确控制PWM信号的起始和终止时间的应用场景。
    在这里插入图片描述
    以上图为例,TIMx_CR1寄存器的DIR位为低时,递增计数,设ARR=8,当CCRx=4时:
  • CNT从0增至3的时候,输出PWM参考信号0CxREF为有效的高电平;
  • CNT从4到8的时候,0CxREF输出为低电平;

0CXREF表示定时器的比较器

(2)中心对齐模式

  • 在中心对齐模式下,PWM信号的起始位置位于PWM周期的中间,然后递增至CCR,再递减至0,再重复此过程。
  • PWM信号的高电平和低电平都与PWM周期的中心对齐,即从PWM周期的中间开始。
  • 中心对齐模式通常用于需要调节占空比范围较大的应用,例如需要在PWM周期内任意调节占空比的应用场景。由于PWM信号的起始位置位于PWM周期的中间,因此可以实现更宽范围的占空比调节。

在这里插入图片描述
以上图为例,设ARR=8,当CCRx=4时,

  • 当CNT<CCRx,输出为有效信号高电平 ;
  • 当CNT>CCRx,输出为有效信号低电平;

四、PWM输出配置步骤

PWM 的配置在库文件 time.c 中。

1. 使能定时器及端口时钟

下面是使能设置代码:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

2. 定时器的重映像

后面示例的 PWM 需要配置引脚的复用功能(重映像),定时器的重映像可在《STM32F10x参考手册》查询,摘录如下:

(1)定时器4复用功能重映像

在这里插入图片描述

(2)定时器3复用功能重映像

在这里插入图片描述

(3) 定时器2复用功能重映像

在这里插入图片描述

以使用 TIM3 的通道1为例,它默认是在PA6引脚上,它完全重映像是在PC6,后面使用的开发板上原理图示:
在这里插入图片描述
示例代码将使用PC6输出TIM3的通道1 PWM波。

代码示例:

// 设置 TIM3 完全重映像
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);

3. 输出端口复用

在输出PWM信号时,通常需要考虑信号的稳定性、噪声抑制以及输出电流的能力等因素。复用推挽输出是一种常见的配置方式。

// 复用推挽输出
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;  

4. 初始化定时器参数

包括 : 自动重载值、分频系数、计数方式等。

void TIM_TimeBaseInit(TIM_TypeDef*TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStructure)

5. 初始化PWM输出参数

包括 :PWM 模式、输出极性、使能等。

void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStructure);// 结构体定义 
typedef struct
{uint16_t TIM_OCMode;  		// 比较输出模式uint16_t TIM_OutputState;  	// 比较输出使能uint16_t TIME_OutputNState: // 比较互补输出使能uint32_t TIM_Pulse;        	// 脉冲宽度 0~65535/*** 输出极性*   * TIM_OCPolarity_High: 高电平有效*   * TIM_OCPolarity_Low: 低电平有效*/uint16_t TIM_OCPolarity;/*** 互补比较输出极性*   * TIM_OCNPolarity_High: 高电平有效*   * TIM_OCNPolarity_Low: 低电平有效*/	uint16_t TIM_OCNPolarity;/*** 空闲状态下比较输出状态*   * TIM_OCIdleState_Set: 置位*   * TIM_OCIdleState_Reset: 复位*/	uint16_t TIM_OCIdleState;/*** 空闲状态下比较输出状态*   * TIM_OCNIdleState_Set: 置位*   * TIM_OCNIdleState_Reset: 复位*/uint16_t TIM_OCNIdleState;
} TIM_OCInitTypeDef;

6. 开启定时器

// NewState: 新的状态,可以是 ENABLE 或 DISABLE。
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)   

7. 修改TIMx_CCRx的值控制占空比

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1);

8. 使能 TIMx 在 CCRx 上的预装载寄存器

// 参数 TIM_OCPreload 可为 TIM_OCPreload_Enable、TIM_OCPreload_Disable
void TIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

9. 使能 TIMx 在 ARR上的预装载寄存器允许位

// NewState: 新的状态,可以是 ENABLE 或 DISABLE。
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

10. 设置 MOE位

对于高级定时器,需要设置MOE位。
MOE 位,全称 Master Output Enable,是定时器控制寄存器 1 (TIMx->CR1) 中的一个控制位(15位),用于使能或禁用定时器主输出。

  • MOE 位可以用于控制 PWM 输出的使能和禁用。
  • 可以使用 MOE 位来实现软启动和软停止功能。
  • 可以使用 MOE 位来实现故障保护功能。
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);

五、代码示例

本实验对TIM3控制,使用通道1, 对TIM3_CH1重映像到PC6引脚,控制PC6上接的LED亮度。
示例程序控制LED呼吸灯效果,渐渐变亮,再渐渐变暗。

1. pwm_utils.h

#ifndef __PWM_UTILS_H__
#define __PWM_UTILS_H__#include "stm32f10x.h"void tim3_ch1_pwm_init(u16 preriod, u16 prescaler);
void tim3_ch1_pwm_set_duty(u16 duty);
#endif

2. pwm_utils.c

#include "pwm_utils.h"
#include "led_utils.h"/*** @brief  定时器3初始化
*/
void tim3_ch1_pwm_init(u16 preriod, u16 prescaler){// 使能TIM3时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);// 使能LED所在端口的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);// 使能AFIORCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置输出速度为50MHzGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置为推挽输出模式GPIO_Init(LED_PORT, &GPIO_InitStructure); //初始化 LED_PORT// 管脚重映像GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);// 定时器初始化TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Period = preriod; //设置自动重装载寄存器周期值TIM_TimeBaseStructure.TIM_Prescaler = prescaler; //设置时钟预分频数TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分频因子TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;// 初始化TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);// PWM模式1TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性高TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能TIM_OC1Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC1// 使能TIM3的CCR1寄存器预装载TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);// 使能TIM3的ARR寄存器预装载TIM_ARRPreloadConfig(TIM3, ENABLE);// 使能TIM3TIM_Cmd(TIM3, ENABLE);
}
void tim3_ch1_pwm_set_duty(u16 duty){// 设置定时器3的PWM占空比TIM_SetCompare1(TIM3, duty);
}

3. main函数实现

#include "gpio_utils.h"
#include "stm32f10x.h"
#include "sys_tick_utils.h"
#include "led_utils.h"
#include "pwm_utils.h"// 主函数
int main(void)
{// led 初始化custom_led_init();// tick 初始化sys_tick_init(72);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// PWM 初始化,2Ktim3_ch1_pwm_init(500, 72-1);led_all_off();int i = 0;u8 direction=0;while (1) //无限循环{tim3_ch1_pwm_set_duty(i);if(direction==0){i++;}else{i--;}if(i>300){direction = 1;}else if(i<1){direction = 0;}delay_ms(10);}
}

实测PC6的波形是一直变化中:

在这里插入图片描述
本文代码开源地址:
https://gitee.com/xundh/stm32_arm_learn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/731583.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python基础——输入与输出【input 和 print】

&#x1f4dd;前言&#xff1a; 上一篇文章python基础——入门必备知识中讲解了一些关于python的基础知识&#xff0c;可以让我们更好的理解程序代码中内容的含义&#xff0c;不至于一头雾水。今天我就来介绍一下&#xff0c;python中两个常见的输入和输出语句 input 和 print …

产品推荐 - 基于星嵌 OMAPL138+国产FPGA的DSP+ARM+FPGA三核开发板

1 评估板简介 基于TI OMAP-L138&#xff08;定点/浮点DSP C674xARM9&#xff09; FPGA处理器的开发板&#xff1b; OMAP-L138是TI德州仪器的TMS320C6748ARM926EJ-S异构双核处理器&#xff0c;主频456MHz&#xff0c;高达3648MIPS和2746MFLOPS的运算能力&#xff1b; FPGA…

粘包与拆包

优质博文&#xff1a;IT-BLOG-CN 一、粘包出现的原因 服务端与客户端没有约定好要使用的数据结构。Socket Client实际是将数据包发送到一个缓存buffer中&#xff0c;通过buffer刷到数据链路层。因服务端接收数据包时&#xff0c;不能断定数据包1何时结束&#xff0c;就有可能出…

【操作系统概念】第11章:文件系统实现

文章目录 0.前言11.1 文件系统结构11.2 文件系统实现11.2.1 虚拟文件系统 11.3 分配方法11.3.1 连续分配11.3.2 链接分配11.3. 3 索引分配 11.5 空闲空间管理11.5.1 位图/位向量11.5.2 链表11.5.3 组 0.前言 正如第10章所述&#xff0c;文件系统提供了机制&#xff0c;以在线存…

springboot251基于springboot-vue的毕业论文管理系统

毕业论文管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本毕业论文管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…

视频批量混剪剪辑,批量剪辑批量剪视频,探店带货系统,精细化顺序混剪,故事影视解说,视频处理大全,精细化顺序混剪,多场景裂变,多视频混剪

前言 工具的产生源于dy出的火山引擎的云视频混剪制作是按分钟数收费的&#xff0c;这个软件既能实现正常混剪也能避免二次收费。属于FFMPEG合成的。 欢迎大家给一些好的建议和功能&#xff0c;回复可见&#xff0c;附加了一些天卡&#xff0c;周卡&#xff0c;请大家不要一人占…

JavaSec 基础之 URLDNS 链

文章目录 URLDNS 链分析调用链复现反序列化复现 URLDNS 链分析 URLDNS是ysoserial里面就简单的一条利用链&#xff0c;但URLDNS的利用效果是只能触发一次dns请求&#xff0c;而不能去执行命令。比较适用于漏洞验证这一块&#xff0c;而且URLDNS这条利用链并不依赖于第三方的类…

练习3-softmax分类(李沐函数简要解析)与d2l.train_ch3缺失的简单解决方式

环境为:练习1的环境 网址为:https://www.bilibili.com/video/BV1K64y1Q7wu/?spm_id_from333.1007.top_right_bar_window_history.content.click 代码简要解析 导入模块 导入PyTorch 导入Torch中的nn模块 导入d2l中torch模块 并命名为d2l import torch from torch import nn…

Neo4j安装 Linux:CentOS、openEuler 适配langchain应用RAG+知识图谱开发 适配昇腾910B

目录 Neo4j下载上传至服务器后进行解压运行安装JAVA再次运行在windows端打开网页导入数据 Neo4j下载 进入Neo4j官网下载页面 向下滑动找到 Graph Database Self-Managed 选择 社区版&#xff08;COMMUNITY&#xff09; 选择 Linux / Mac Executable Neo4j 5.17.0 (tar) 单机下…

分销商城微信小程序:用户粘性增强,促进复购率提升

在数字化浪潮的推动下&#xff0c;微信小程序作为一种轻便、高效的移动应用形式&#xff0c;正成为越来越多企业开展电商业务的重要平台。而分销商城微信小程序的出现&#xff0c;更是为企业带来了前所未有的机遇。通过分销商城微信小程序&#xff0c;企业不仅能够拓宽销售渠道…

产品推荐 - 基于矽海达 SEM9363的无线数字图传编码开发板

Sihid SEM9363无线数字图传编码调制板(A版本)通过HDMI接口输入高清数字视频到Hi3516A处理器做H.264压缩编码&#xff0c;压缩后的视频信号通过FPGA实现COFDM信道调制&#xff0c;再经AD936x转换为模拟信号调制发射出去。 SEM9363板功能与技术规格 通过Micro HDMI接口输入数字视…

生活的色彩--爱摸鱼的美工(17)

题记 生活不如意事十之八九&#xff0c; 恶人成佛只需放下屠刀&#xff0c;善人想要成佛却要经理九九八十一难。而且历经磨难成佛的几率也很小&#xff0c;因为名额有限。 天地不仁以万物为刍狗&#xff01; 小美工记录生活&#xff0c;记录绘画演变过程的一天。 厨房 食…

AI探索实践12 - Typescript开发AI应用4:大模型响应数据的格式化输出

大家好&#xff0c;我是feng&#xff0c;感谢你阅读我的博文&#xff0c;如果你也关注AI应用开发&#xff0c;欢迎关注公众号和我一起​探索。如果文章对你有所启发&#xff0c;请为我点赞&#xff01; 一、重点回顾 在介绍本文之前的文章中&#xff0c;我们先来回顾一下使用L…

两天学会微服务网关Gateway-Gateway过滤器

锋哥原创的微服务网关Gateway视频教程&#xff1a; Gateway微服务网关视频教程&#xff08;无废话版&#xff09;_哔哩哔哩_bilibiliGateway微服务网关视频教程&#xff08;无废话版&#xff09;共计17条视频&#xff0c;包括&#xff1a;1_Gateway简介、2_Gateway工作原理、3…

数据结构 - 栈和队列

本篇博客将介绍栈和队列的定义以及实现。 1.栈的定义 栈是一种特殊的线性表&#xff0c;只允许在固定的一端进行插入和删除数据&#xff0c;插入数据的一端叫做栈顶&#xff0c;另一端叫做栈底。栈中的数据遵守后进先出的原则 LIFO (Last In First Out)。 插入数据的操作称为压…

如何借助私域营销在医美行业中脱颖而出?

在现今这个以貌取人的社会&#xff0c;外貌焦虑已变得司空见惯。美丽往往能给人带来更多的瞩目和机遇&#xff0c;但天生丽质并非人人可得。随着经济的繁荣和消费结构的升级&#xff0c;颜值经济开始崭露头角&#xff0c;医美行业因此受到了广大消费者的青睐&#xff0c;迎来了…

Leetcode 剑指 Offer II 068.搜索插入位置

题目难度: 简单 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定一个排序的整数数组 nums 和一个整数目标值 target &#xf…

阿波罗登月需要解决飞行控制问题,数学家卡尔曼在维纳控制的基础上提出了卡尔曼滤波

说到登月&#xff0c;很多人只想到和火箭以及航天器相关的技术&#xff0c;其实登月离不开信息技术的革命。因为从飞行控制到远程通信&#xff0c;都需要解决很多过去从未遇到过的难题。 登月首先要保证在月球上着陆的地点准确&#xff0c;而且要保证返回火箭和飞船能够在月球轨…

【LeetCode: 211. 添加与搜索单词 - 数据结构设计 + 前缀树】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

npm install没有创建node_modules文件夹

问题记录 live-server 使用时 报错&#xff1a;live-server : 无法将“live-server”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 npm install 安装 但是 这时npm install没有创建node_modules文件夹&#xff0c;只生成package-lock.json文件 方法一&#xff1a; 手…