STM32——PWM基本知识及配置过程
将通用定时器分为四个部分:
1,选择时钟
2,时基电路
3,输入捕获
4,输出比较
本节定时器PWM输出主要涉及到定时器框图右下方部分,即输出比较部分
和上一讲相同,时基时钟来源于内部默认时钟
对此有疑问请参考 : 定时器中断实验 中 定时器时钟选择部分 和 定时器时钟来源部分
什么是PWM
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
PWM工作过程
每个定时器有四个通道,每一个通道都有一个捕获比较寄存器,
将寄存器值和计数器值比较,通过比较结果输出高低电平,实现PWM信号
先简单说明一下:
如图为向上计数:
定时器重装载值为ARR,比较值CCRx
t时刻对计数器值和比较值进行比较
如果计数器值小于CCRx值,输出低电平
如果计数器值大于CCRx值,输出高电平
PWM的一个周期
定时器从0开始向上计数
当0-t1段,定时器计数器TIMx_CNT值小于CCRx值,输出低电平
t1-t2段,定时器计数器TIMx_CNT值大于CCRx值,输出高电平
当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数...循环此过程
至此一个PWM周期完成
影响因素
ARR : 决定PWM周期(在时钟频率一定的情况下,当前为默认内部时钟CK_INT)
CCRx : 决定PWM占空比(高低电平所占整个周期比例)
PWM工作过程(以通道1为例)
1,TIMx_CCMR1寄存器的OC1M[2:0]位,设置输出模式控制器
110:PWM模式1
111:PWM模式2
2,计数器值TIMx_CNT与通道1捕获比较寄存器CCR1进行比较,通过比较结果输出有效电平和无效电平
OC1REF=0 无效电平
OC1REF=1 无效电平
3,通过输出模式控制器产生的信号
TIMx_CCER寄存器的CC1P位,设置输入/捕获通道1输出极性
0:高电平有效
1:低电平有效
4,TIMx_CCER:CC1E位控制输出使能电路,信号由此输出到对应引脚
0:关闭
1:开启
PWM如何输出高低电平
计数器值TIMx_CNT与捕获比较寄存器值CCRx比较后,最终输出高电平还是低电平,
由TIMx_CCMR1:OC1M位和TIMx_CCER:CC1P位共同决定
1,TIMx_CCMR1寄存器的OC1M[2:0]位,设置PWM模式1或模式2
通过设置模式1或模式2,决定了比较结果输出有效或无效电平
2,TIMx_CCER寄存器的CC1P位,设置输入/捕获通道1输出极性
通过设置输出极性,确定有效或无效电平为最终输出的高电平或低电平
总结:
模式1:
CNT<CCR为有效电平 //(OC1REF = 1)
CNT>CCR为无效电平 //(OC1REF = 0)
模式2:
CNT<CCR为无效电平 //(OC1REF = 0)
CNT>CCR为有效电平 //(OC1REF = 1)
CC1P:
0:高电平有效
1:低电平有效
PWM模式配置
TIM_OC1PreloadConfig函数:
作用:TIM_CCMRx寄存器OCxPE位使能相应的预装在寄存器
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
TIM_ARRPreloadConfig函数:
作用:操作TIMx_CR1寄存器ARPE位,使能自动重装载的预装载寄存器
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
ARPE的使能-ARR变更生效配置
ARPE=1,ARR立即生效
ARPE=0,ARR下周期生效
定时器3输出通道引脚
定时器3的4个通道对应的引脚及重映射
PWM输出库函数
1,定时器通道初始化-TIM_OC1Init
经过上面的讲解,我们知道了要想使用PWM需要配置
配置参数对应框图位置如下:
1,TIMx_CCMR1寄存器的OC1M[2:0]位,设置输出模式控制器
2,TIMx_CCER寄存器的CC1P位,设置输入/捕获通道1输出极性
3,TIMx_CCER:CC1E位控制输出使能电路,信号由此输出到对应引脚
初始化定时器输出比较通道
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
- 1
TIM_OCInitTypeDef结构体
typedef struct
{
uint16_t TIM_OCMode; // PWM模式1或者模式2
uint16_t TIM_OutputState; // 输出使能 OR失能
uint16_t TIM_OutputNState; // PWM输出不需要
uint16_t TIM_Pulse; // 比较值,写CCRx,可以有次函数void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
写入,这里暂时不设置。
uint16_t TIM_OCPolarity; // 比较输出极性
uint16_t TIM_OCNPolarity; // PWM输出不需要
uint16_t TIM_OCIdleState; // PWM输出不需要
uint16_t TIM_OCNIdleState; // PWM输出不需要
} TIM_OCInitTypeDef;
2,设置比较值函数-TIM_SetCompare1
作用:外部改变TIM_Pulse值,即改变CCR的值
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
- 1
3,使能输出比较预装载-TIM_OC1PreloadConfig
作用:TIM_CCMRx寄存器OCxPE位使能相应的预装在寄存器
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
- 1
4,使能自动重装载的预装载寄存器允许位-TIM_ARRPreloadConfig
作用:操作TIMx_CR1寄存器ARPE位,使能自动重装载的预装载寄存器
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
- 1
5,修改通道极性
作用:操作TIMx_CCER的CC1P位,修改通道极性
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
- 1
PWM输出实验
使用定时器3初始PWM信号,输出占空比可变的PWM波驱动LED(PB5引脚),实现LED亮度变换
LED:低电平点亮,高电平熄灭,占空比越大,一个周期中高电平持续时间越长,亮度越大,反之越暗.
查找手册PB5引脚为定时器3的通道2,需要部分重映射
PWM输出实验步骤
1,使能定时器3和相关IO时钟(LED-PB5)
使能定时器3时钟:RCC_APB1PeriphClockCmd();
使能GPIOB时钟:RCC_APB2PeriphClockCmd();
2,初始化IO口为复用功能输出 GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
3,PB5输出PWM(定时器3通道2),需要部分冲突映射
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟设置
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);//部分重映射
4,初始化定时器 (重装载值ARR,与分频系数PSC等)
TIM_TimeBaseInit();//决定PWM周期
5,初始化输出比较参数:
TIM_OC2Init();//通道2输出比较初始化
6,使能预装载寄存器
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);//定时器3 通道2
7,使能定时器
TIM_Cmd();
8,不断改变比较值CCRx,达到不同的占空比效果
TIM_SetCompare2(); //通道2,改变比较值CCRx
代码实现
基于 定时器中断实验 代码进行编写
timer.h添加PWM初始化函数定义 void TIM3_PWM_Init(u16 arr,u16 psc);
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h" void TIM3_PWM_Init(u16 arr,u16 psc); #endif
timer.c 实现定时器PWM初始化函数
#include "timer.h" //TIM3 PWM初始化
//arr 重装载值
//psc 预分频系数
void TIM3_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStrue;
TIM_OCInitTypeDef TIM_OCInitStrue;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrue; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //使能TIM3和相关GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);// 使能GPIOB时钟(LED在BP5引脚),使能AFIO时钟(定时器3通道2需要重映射到BP5引脚)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStrue.GPIO_Pin=GPIO_Pin_5; // TIM_CH2
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP; // 复用推挽
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz; //设置最大输出速度
GPIO_Init(GPIOB,&GPIO_InitStrue); //GPIO端口初始化设置 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE); TIM_TimeBaseInitStrue.TIM_Period=arr; //设置自动重装载值
TIM_TimeBaseInitStrue.TIM_Prescaler=psc; //预分频系数
TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up; //计数器向上溢出
TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1; //时钟的分频因子,起到了一点点的延时作用,一般设为TIM_CKD_DIV1
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStrue); //TIM3初始化设置(设置PWM的周期) TIM_OCInitStrue.TIM_OCMode=TIM_OCMode_PWM2; // PWM模式2:CNT>CCR时输出有效
TIM_OCInitStrue.TIM_OCPolarity=TIM_OCPolarity_High;// 设置极性-有效为高电平
TIM_OCInitStrue.TIM_OutputState=TIM_OutputState_Enable;// 输出使能
TIM_OC2Init(TIM3,&TIM_OCInitStrue); //TIM3的通道2PWM 模式设置 TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能预装载寄存器 TIM_Cmd(TIM3,ENABLE); //使能TIM3 }
main.c 改变CCR值实现PWM占空比变化,小灯亮暗变化
int main(void)
{
u8 i=; // 设置方向 0:变暗 1:变亮
u16 led0pwmval; // 设置CCR值
delay_init(); // 延时函数初始化
LED_Init(); // LED初始化
TIM3_PWM_Init(,); //设置频率为80KHz,公式为:溢出时间Tout=(arr+1)(psc+1)/Tclk
//Tclk为通用定时器的时钟,如果APB1没有分频,则就为系统时钟,72MHZ
//PWM时钟频率=72000000/(899+1) = 80KHZ,设置自动装载值899,预分频系数0(不分频)
while()
{
delay_ms();
if(i)led0pwmval++; // 由暗变亮
else led0pwmval--; // 由亮变暗 if(led0pwmval==)i=; // 已达到最亮,开始变暗
if(led0pwmval>)i=; // 已达到最暗,开始变亮 TIM_SetCompare2(TIM3,led0pwmval); //改变比较值TIM3->CCR2达到调节占空比的效果 }
}
//此处led0pwmval值最大可以设置到899,输出pwm波基本全为1,大小随意设定。
STM32——PWM基本知识及配置过程的更多相关文章
- STM32CubeMX软件工程描述_USART配置过程
推荐 分享一个朋友的人工智能教程,零基础!通俗易懂!希望你也加入到人工智能的队伍中来! http://www.captainbed.net/strongerhuang Ⅰ.写在前面 学习本文之前可以查 ...
- 大疆M3508、M2006必备CAN总线知识与配置方法
使用大疆M3508.M2006的CAN总线知识与配置方法 目录 使用大疆M3508.M2006的CAN总线知识与配置方法 前言: 0x00 需要额外的CAN收发器!!! 0x01 硬件层面分析 为什么 ...
- Linux LVM逻辑卷配置过程详解
许多Linux使用者安装操作系统时都会遇到这样的困境:如何精确评估和分配各个硬盘分区的容量,如果当初评估不准确,一旦系统分区不够用时可能不得不备份.删除相关数据,甚至被迫重新规划分区并重装操作系统,以 ...
- Hadoop的配置过程(虚拟机中的伪分布模式)
1引言 hadoop如今已经成为大数据处理中不可缺少的关键技术,在如今大数据爆炸的时代,hadoop给我们处理海量数据提供了强有力的技术支撑.因此,了解hadoop的原理与应用方法是必要的技术知识. ...
- STM32CubeMX新建工程+基本IO配置过程
Ⅰ.写在前面 学习本文之前可以查看我前面的文章: STM32CubeMX介绍.下载与安装 STM32CubeMX使用方法及功能介绍 本文接着上一篇文章结合基本IO配置实例,讲述关于STM32CubeM ...
- STM32 PWM的输出与Keil软件仿真
导读:PWM(Pulse Width Modulation)控制——脉冲宽度调制技术,通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形(含形状和幅值). PWM控制技术在逆变电路中应用最广,应用 ...
- Linux随笔 - Linux LVM逻辑卷配置过程详解[转载]
许多Linux使用者安装操作系统时都会遇到这样的困境:如何精确评估和分配各个硬盘分区的容量,如果当初评估不准确,一旦系统分区不够用时可能不得不备份.删除相关数据,甚至被迫重新规划分区并重装操作系统,以 ...
- elasticsearch5.0.0 安装插件及配置过程
elasticsearch5.0.0 安装插件及配置过程 由于es5.0是里程碑式的更新,所以很多变化的地方,暂时我就插件安装遇到的问题记录一下. 插件安装命令 2.3版本的安装命令 安装Marvel ...
- synergy 两台Windows电脑配置过程
Synergy 介绍 软件作用 Synergy 两台独立电脑,共享一套鼠标和键盘的工具, 软件原理(我自己想的) 保证两台电脑在一个局域网内,可以相互Ping通的电脑(这样才能直接通过TCP连接) 将 ...
随机推荐
- java颜色代码对照表
LightPink 浅粉色 #FFB6C1 255,182,193 Pink 粉红 #FFC0CB 255,192,203 Crimson 猩红 #DC143C 220,20,60 LavenderB ...
- HttpHelper使用记录
重新载入页面以获取源代码 var item = new HttpItem() { URL = @"http://www.xxx.com/msg/basic/?a=sendmsg", ...
- 超全面的vue.js使用总结
一.Vue.js组件 vue.js构建组件使用 Vue.component('componentName',{ /*component*/ }): 这里注意一点,组件要先注册再使用,也就是说: Vue ...
- 再谈WPF
前几天初步看了一下WPF,按照网上说的一些方法,实现了WPF所谓的效果.但,今天我按照自己的思路设计了一个登陆界面,然后进行登陆验证,对WPF算是有进一步的理解,记录下来,以备后期查看. 首先,在WP ...
- c#线程倒计时器源码
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...
- spring项目后台中打印sql语句
配置方法很简单,只要在配置文件application.yml加入以下语句 logging: level: main.java.iReview.dao: debug 其中包的位置应为dao层的包位置,不 ...
- 【Java】 Maven多模块项目上传到Sonar扫描问题合集
上传到Soanr时,项目有单元测试数,但是覆盖率为0 修改pom.xml <plugin> <groupId>org.apache.maven.plugins</grou ...
- If you can't take it, don't dish it out.
If you can't take it, don't dish it out.己所不欲,勿施于人.
- My sql之存储过程+游标
sql 实例如下: /**************定义更改car_station_user_acct_his new_balance old_balance存储过程**************/ cr ...
- (转)在SQL Server 2016,Visual Studio 2017环境下,连接数据库屡屡失败,在connectionString上出的问题
适用情景: 1,ServerVersion出了问题,“SqlCnt.ServerVersion”引发了类型“System.InvalidOperationException”的异常 2,在String ...