STM32 学习10 PWM输出

news2024/12/24 8:07:05

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);
    // 使能AFIO
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置输出速度为50MHz
    GPIO_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模式1
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
    TIM_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);
    // 使能TIM3
    TIM_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 初始化,2K
	tim3_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.coloradmin.cn/o/1499939.html

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

相关文章

leetcode刷题(2):链表

文章目录 1. 两数相加1.1 解题思路1. 2 c 实现 2 删除排序链表中的重复元素 ||2.1 解题思路2.2 c 实现 3 旋转链表3.1 解题思路3.2 c 实现 4 剑指 Offer 06: 从尾到头打印链表4.1 解题思路4.2 c 实现 5 剑指 Offer 24. 反转链表5.1 解题思路5.2 c实现 21. 合并两个有序链表解题…

【传输层】进程之间基于网络的通信(湖科大慕课自学笔记)

进程之间基于网络的通信 我们正式进入运输层的学习&#xff0c;先介绍进程之间基于网络的通信&#xff0c;我们在之前的学习中&#xff0c;已经介绍了物理层&#xff0c;数据链路层&#xff0c;网络层&#xff0c;它们共同解决并实现了主机到主机的通信 举例如下图所示&#x…

DDS技术概述及测试策略与方案

随着车载通信技术的快速发展&#xff0c;传统的通信技术在满足车载通信需求方面面临着一些挑战。车载通信对实时性、可靠性以及通信带宽的需求越来越高&#xff0c;同时车载通信环境存在多路径衰落、信号干扰等问题&#xff0c;这些都给通信技术的选择和应用带来了一定的挑战。…

VMware 集群-虚拟机配置反亲和性(互斥)

简介 博客&#xff1a;https://songxwn.com/ 为实现应用系统的冗余&#xff0c;经常会双机或者多机部署&#xff08;如数据库集群等&#xff09;。在VMware 集群里面&#xff0c;要保证不同应用集群的节点虚拟机在不同的物理宿主机上&#xff0c;防止单个宿主机故障&#xff…

Web Servlet

目录 1 简介2 创建Servlet项目并成功发布运行3 新加Servlet步骤4 Servlet项目练习5 Servlet运行原理6 操作 HTTP Request头的方法(部分方法示例)7 操作 HTTP Response头的方法(部分方法示例)8 两种重定向(页面跳转)方法9 Cookie9.1 Cookie工作原理9.2 cookie构成9.3 Servlet 操…

Unity DropDown 组件 详解

Unity版本 2022.3.13f1 Dropdown下拉菜单可以快速创建大量选项 一、 Dropwon属性详解 属性&#xff1a;功能&#xff1a;Interactable此组件是否接受输入&#xff1f;请参阅 Interactable。Transition确定控件以何种方式对用户操作进行可视化响应的属性。请参阅过渡选项。Nav…

个人商城系统开源(展示宣传)

原文地址&#xff1a;个人商城系统开源&#xff08;展示宣传&#xff09; - Pleasure的博客 下面是正文内容&#xff1a; 前言 由于近期实在没有什么话题可写和一些有趣的项目教程可以分享。所以我只能决定将我自己亲手编写的一个迷你商城系统进行开源。 也就是放在我博客右边…

Unity UGUI之Scrollbar基本了解

Unity的Scrollbar组件是用于在UI中创建滚动条的组件之一。滚动条通常与其他可滚动的UI元素&#xff08;如滚动视图或列表&#xff09;一起使用&#xff0c;以便用户可以在内容超出可见区域时滚动内容。 以下是Scrollbar的基本信息和用法: 1、创建 在Unity的Hierarchy视图中右…

Android屏幕共享-硬编码硬解码

Android屏幕共享-硬编码硬解码 说起Android之间的屏幕共享&#xff0c;第一次接触会比较陌生&#xff0c;不过大家多少有了解过ffmpeg&#xff0c;看上去是不是很熟悉&#xff1f;ffmpeg是一套处理音视频的开源程序&#xff0c;但对于C了解较少的同学&#xff0c;编译起来很复杂…

掌握这几个技术点,你也能开发出爆款ARPG游戏!

在众多ARPG游戏的发售下&#xff0c;游戏市场温度迅速升高&#xff0c;今年很可能会成为一个“ARPG手游大年”&#xff0c;或许会再次出现“神仙打架”的情况。 ARPG作为一种非常经典且流行的游戏类型, 已经诞生过无数经典的作品,比如魂系,暗黑破坏神系列,塞尔达传说系列&#…

网页在特殊日子一键变灰

<template> <div :class"{ grayscale: isGrayscale }"> <!-- 你的页面内容放在这里 --> </div> </template> <script> export default { data() { return { // 存储哀悼日的数组 aidaoriDates:["0404", &q…

Filter过滤器+JWT令牌实现登陆验证

一、背景 我们需要在客户端访问服务器的时候给定用户一定的操作权限&#xff0c;比如没有登陆时就不能进行其他操作。如果他需要进行其他操作&#xff0c;而在这之前他没有登陆过&#xff0c;服务端则需要将该请求拦截下来&#xff0c;这就需要用到过滤器&#xff0c;过滤器可以…

高速缓冲存储器(Cache)

程序访问的局部性原理 程序访问的局部性原理包括时间局部性和空间局部性。 时间局部性&#xff1a;指在最近的未来要用到的信息&#xff0c;很可能是现在正在使用的信息&#xff0c;因为程序中存在循环。空间局部性&#xff1a;指在最近的未来要用到的信息&#xff0c;很可能…

简析内部审计数字化转型的方法和路径【小落送书(第6期)】

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

利用IP地址信息提升网络安全

在计算机网络中&#xff0c;IP地址是用于唯一标识网络设备的重要标识符。然而&#xff0c;由于网络中存在大量设备&#xff0c;有时会出现IP地址冲突的情况&#xff0c;即两个或多个设备在同一网络中使用了相同的IP地址&#xff0c;这可能导致网络连接故障和通信中断。本文将介…

基于PHP的医院绩效管理系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 PHP技术简介 3 1.2 Bootstrap框架简介 3 1.3 MVC技术模式简介 3 1.4 Ajax技术简介 3 1.5 MySQL数据库简介 4 1.6本章小结 4 2 系统需求分析 5 2.1系统分析 5 2.2需求分析 8 2.2.1用户需求分析 8 2.2.2管理员需求分析 10 2…

知识付费开发:开启智慧的新篇章

在数字化时代的浪潮下&#xff0c;知识的获取与分享方式正在发生深刻变革。传统的知识传递模式逐渐被知识付费开发的新模式所取代&#xff0c;它以其独特的魅力和巨大的潜力&#xff0c;正在引领着智慧的新潮流。 知识付费开发&#xff0c;是以用户为中心&#xff0c;以知识为…

Spring Boot工程集成验证码生成与验证功能教程

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

基于SSM技术的宠物寄存系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术介绍 3 1.1 开发技术语言 3 1.1.1 Java 3 1.1.2 Ajax 3 1.1.3 JavaScript 3 1.2 开发框架 4 1.2.1 Spring 4 1.2.2 Spring MVC 4 1.2.3 Mybatis 4 1.2.4 Bootstrap 5 1.3 MySQL数据库 5 1.4 本章小结 6 2 系统分析 7 2.1 系统的需…

针对ETC系统的OBE-SAM模块设计方案

ETC&#xff08;Electrical Toll Collection&#xff09;不停车收费是目前世界上最先进的路桥收费方式。通过安装在车辆挡风玻璃上的车载单元与安装在收费站 ETC 车道上的路侧单元之间的微波专用短程通讯&#xff0c;利用计算机联网技术与银行进行后台结算处理&#xff0c;从而…