STM32之PWM

STM32之PWM

  • 开发环境:Window 10
  • 开发工具:Keil uVision5 MDK
  • 硬件:STM32F103

资料参考:

【正点原子】STM32F103开发板资料(A盘);

  • STM32F1开发指南(精英版)-库函数版本.pdf
  • STM32固件库使用手册的中文翻译版.pdf
  • STM32中文参考手册.pdf


STM32F103ZE 简介

https://www.keil.com/dd2/stmicroelectronics/stm32f103ze/

内核:ARM Cortex-M3,72MHz

内存:64kB RAM,512kB ROM

时钟和电源:2.00V—3.60V,72 MHz

通信 :SPI、I2C、UART、I2S、CAN、USART、USB、Device

定时器/计数器/PWM :8 × 16 位定时器

模拟:2通道 12位DAC,21通道 12位ADC

I/O 和封装: -40℃—85℃,144-QFP,144-BGA


PWM简介

PWM 全称是 Pulse Width Modulation(脉冲宽度调制),即可以实现占空比可以调节的矩形脉冲,当其占空比固定为50%时便是方波。

STM32的定时器除了TIM6和7,其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生 7 路的 PWM 输出。而通用定时器也能同时产生 4路的 PWM 输出(F103系列有4个通用定时器),注意,STM32可以同时产生30路PWM输出


PWM产生的原理

了解PWM的产生,需要理清以下几个参数之间的关系:定时器的自动重装载值ARR和计数值CNT;捕获/比较寄存器的比较值CCR;PWM模式1和模式2;有效电平

当定时器为向上计数模式时,计数值CNT从0增加到ARR,而比较值CCR是一个介于0~ARR之间的一个值。当CNT<CCR时,输出一种电平;当CNT>CCR时,输出另一种电平,而输出电平是高是低取决于PWM的模式以及有效电平。

  • PWM模式1时,当CNT<CCR时,输出有效电平;当CNT>CCR时,输出无效电平;
  • PWM模式2时,当CNT<CCR时,输出无效电平;当CNT>CCR时,输出有效电平;

注意:这里都是采用定时器向上计数的情况,列出向下计数情况容易混淆而且其应用较少,这边就不赘述了。

两种PWM模式与两种有效电路的组合输出如下图:(图是用PPT手绘原创的,加个水印哈)

在这里插入图片描述

同时,调节CCR的值可以实现占空比的改变。


PWM的使用步骤

以一个实例为基础对PWM的使用进行解析,实例要求如下:

  • 用定时器TIM3的通道2在重映射的PB5引脚输出
  • 占空比自变化(由小变大,再由大变小)的PWM脉冲。

(正点原子的例程-PWM输出中还包括了定时器中断控制小灯闪烁,但本篇只介绍PWM的使用,故此处不赘述定时器中断部分)

1)使能时钟,配置输出引脚

2)初始化GPIO

3)初始化定时器

4)初始化PWM模式

5)使能TIM-定时器

6)配置占空比


1)使能时钟,配置输出引脚

在使用外设前,必须要开启相应外设的时钟!

  1. 定时器TIM3来自于APB1时钟总线:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器 3 时钟
  1. 重映射的PB5口以及复用IO口(AFIO)来自于APB2时钟总线:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
  1. 同时,对定时器TIM3通道2启用部分重映射到PB5口

注意:定时器设置了重映射,所有的通道都会启动重映射,因此开启重映射只需选择定时器,而不需要选择具体通道,重映射的对应引脚可以查看参考手册,搜索TIM3_REMAP。

void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState)

第一个参数:开启重映射的定时器

第二个参数:是否使能

范例:

GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5

2)初始化GPIO

GPIO的配置太过普遍就不展开叙述,主要解释两个点:部分重映射和完全重映射;PB5为什么是复用推挽输出模式

部分重映射和完全重映射

  • 部分重映射:功能外设的部分引脚重新映射,还有一部分引脚是原来的默认引脚。
  • 完全重映射:功能外设的所有引脚都重新映射。

也就是说,不起用重映射的引脚,只具有默认连接的外设的功能;启用部分重映射的引脚,在保留原有功能的基础上新设置外设的功能;启用完全重映射的引脚,只具有新设置外设的功能。

PB5为什么是复用推挽输出模式:

  • 只要开启了重映射功能,就要设置为复用模式。
  • PWM是要产生数字量表示0和1的矩形脉冲,而推挽模式可以输出高(3.3V)、低电平(0V),符合需要

对PB5口的配置范例:

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO

3)初始化定时器

所有初始化的定义格式基本固定,第一次遇到时了解下就能懂,这里也不详细介绍

对定时器TIM3初始化的范例:

TIM_TimeBaseStructure.TIM_Period = arr; //自动重装载值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //TIMx时钟的预分频值 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割,不分割
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx

4)初始化PWM模式

PWM 通道设置是通过函数TIM_OC1Init~TIM_OC4Init()来设置的,以通道2为例:

void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct

第一个参数:待配置的定时器

第二个参数:配置PWM相关参数的结构体,下面仅列出3个常用的参数

typedef struct
{
uint16_t TIM_OCMode;
uint16_t TIM_OutputState;
uint16_t TIM_OCPolarity; 
} TIM_OCInitTypeDef;
  1. TIM_OCMode:定时器的模式,共有6中模式,与PWM有关的有TIM_OCMode_PWM1、TIM_OCMode_PWM2两种
  2. TIM_OutputState:比较输出使能,也就是使能PWM 输出到端口
  3. TIM_OCPolarity:设置有效电平为高还是低

对TIM3 Channe2 设置PWM的范例,采用PWM模式2,有效电平为高,即输出先低后高

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2

TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器

5)使能TIM-定时器

一系列的初始化配置完成后一定不要忘记开启定时器

TIM_Cmd(TIM3, ENABLE); // 使能 TIM3

6)配置占空比

本文开篇就介绍PWM就是占空比可调的矩形脉冲,而占空比的调节需要通过TIM_SetCompare()函数来实现

void TIM_SetComparex(TIM_TypeDef* TIMx, uint16_t Compare2)

每个通道都有不同的函数名字,其函数格式是TIM_SetComparex(x=1,2,3,4)

第一个参数:待控制的定时器

第二个参数:与寄存器计数值arr进行比较的值,即控制占空比

对占空比设置的范例:

根据PWM的设定,输出先低后高,CCR的值(代码中的led0PWMval)控制的是低电平的时间,所以实现的是占空比由大变小再由小变大的过程

u16 led0pwmval++=0;
TIM3_PWM_Init(900-1,0);		//TIM3的计数值为900
while(1)	
{
 	if(dir)led0pwmval++;//占空比由大变小时,低电平时间加长
	else led0pwmval--;//占空比由小变大时,低电平时间减小

	if(led0pwmval>300)dir=0;//占空比最小为1-300/900 = 2/3
	if(led0pwmval==0)dir=1;	//这两行实现占空比变化模式的切换									 
	TIM_SetCompare2(TIM3,led0pwmval);	//将参数给到相应寄存器
}

注释:创作时尚且处于学习初期,对程序只有能用就行的要求,若理解有误或不全面之处后续仍会改进…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值