STM32pwm呼吸灯

开发手册分析

(1)PWM 边沿对齐模式 当 TIMx_CR1 寄存器中的 DIR 位为低时执行递增计数,计数器 CNT 从 0 计 数到自动重载值(TIMx_ARR 寄存器的内容),然后重新从 0 开始计数并生成计 数器上溢事件。 以 PWM 模式 1 为例。只要 TIMx_CNT < TIMx_CCRx, PWM 参考信号 OCxREF 便为有效的高电平,否则为无效的低电平。如果 TIMx_CCRx 中的比较值大于自 动重载值(TIMx_ARR 中),则 OCxREF 保持为“ 1”。如果比较值为 0,则 OCxREF 保持为“ 0”。如下图所示:

当 TIMx_CR1 寄存器中的 DIR 位为高时执行递减计数,计数器 CNT 从自动 重载值(TIMx_ARR 寄存器的内容)递减计数到 0,然后重新从 TIMx_ARR 值开始 计数并生成计数器下溢事件。 以 PWM 模式 1 为例。只要 TIMx_CNT >TIMx_CCRx, PWM 参考信号 OCxREF 便为无效的低电平,否则为有效的高电平。如果 TIMx_CCRx 中的比较值大于自 动重载值(TIMx_ARR 中),则 OCxREF 保持为“ 1”。此模式下不能产生 0%的 PWM 波形。

(2)PWM 中心对齐模式 在中心对齐模式下,计数器 CNT 是工作在递增/递减模式下。开始的时候, 计数器 CNT 从 0 开始计数到自动重载值减 1(ARR-1),生成计数器上溢事件; 然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从 0 开始重 新计数。如下图所示:

我们以 ARR=8,CCRx=4 为例进行介绍。第一阶段计数器 CNT 工作在递增计数 方式,从 0 开始计数,当 TIMx_CNT < TIMx_CCRx 时,PWM 参考信号 OCxREF 为 有效的高电平,当 TIMx_CNT >= TIMx_CCRx 时,PWM 参考信号 OCxREF 为无效的 低电平。第二阶段计数器 CNT 工作在递减计数方式,从 ARR 开始递减计数,当 TIMx_CNT > TIMx_CCRx 时,PWM 参考信号 OCxREF 为无效的低电平,当 TIMx_CNT <= TIMx_CCRx 时,PWM 参考信号 OCxREF 为有效的高电平。 中心对齐模式又分为中心对齐模式 1/2/3 三种,具体由寄存器 CR1 位 CMS[1:0]配置。具体的区别就是比较中断标志位 CCxIF 在何时置 1:中心模式 1 在 CNT 递减计数的时候置 1,中心对齐模式 2 在 CNT 递增计数时置 1,中心 模式 3 在 CNT 递增和递减计数时都置1

开发步骤

(1)使能定时器及端口时钟,并设置引脚复用器映射

因为 PWM 输出也是通用定时器的一个功能,所以需要使能相应定时器时钟。 由于 PWM 输出通道是对应着 STM32F1 芯片的 IO 口,所以需要使能对应的端口时 钟,并将对应 IO 口配置为复用输出功能。例如本章 PWM 呼吸灯实验,我们使用 的是 TIM3 的 CH2 通道输出 PWM 信号,因此需要使能 TIM3 时钟,调用的库函数如 下: 1. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

//使能 TIM3 时钟 而 TIM3 的 CH2 通道对应的管脚是 PA7,但是我们开发板上的 LED 灯并没有接 在 PA7 引脚上,如果要让这个通道映射到 LED 所接的 IO 口上,则需要使用 GPIO 的复用功能重映射,LED 模块的 DS0 就是连接在 PB6 口的,所以可以将 TIM3_CH2 配置为部分重 映像即可映射到 PB5 脚,这样 PB5 就可以输出 PWM 了。使用到外设的复用功能重 映射就需要开启 AFIO 时钟,所以开启 AFIO 时钟函数如下: 1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

从图中可以看到,TIM3_CH2 有部分重映像和完全重映像选择,那么就需要 调用引脚复用映射功能函数:

1. void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);

第二个参数很好理解,用来使能还是失能;第一个参数是选择是部分重映射 还是完全重映射

(2)初始化定时器参数,包含自动重装值,分频系数,计数方式等 要使用定时器功能,必须对定时器内相关参数初始化,其库函数如下: 1. voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseI nitStruct);

(3)初始化 PWM 输出参数,包含 PWM 模式、输出极性、使能等 初始化定时器后,需要设置对应通道 PWM 的输出参数,比如 PWM 模式、输出 极性、是否使能 PWM 输出等。PWM 通道设置函数如下

1. void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

 (4)开启定时器 前面几个步骤已经将定时器及 PWM 配置好,但 PWM 还不能正常使用,只有开 启定时器了才能让它正常工作,开启定时器的库函数如下:

1. void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

(5)修改 TIMx_CCRx 的值控制占空比

其实经过前面几个步骤的配置,PWM 已经开始输出了,只是占空比和频率是 固定的,例如本章要实现呼吸灯效果,那么就需要调节 TIM3 通道 2 的占空比, 通过修改 TIM3_CCR2 值控制。调节占空比函数是:

1. void TIM_SetCompare2(TIM_TypeDef* TIMx, uint32_t Compare1)

(6)使能 TIMx 在 CCRx 上的预装载寄存器 使能输出比较预装载库函数是:

1. void TIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

 (7)使能 TIMx 在 ARR 上的预装载寄存器允许位

使能 TIMx 在 ARR 上的预装载寄存器允许位库函数是:

1. void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState); 第一个参数用于选择定时器,第二个参数用于选择使能还是失能

pwm.h

#ifndef _pwm_H
#define _pwm_H
#include "system.h"

void TIM3_CH2_PWM_Init(u16 per, u16 psc);

#endif

pwm.c

#include "pwm.h"
#include "led.h"

void TIM3_CH2_PWM_Init(u16 per, u16 psc)//周期值和预分频器的值
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出,复用pwm和gpiob
	GPIO_InitStructure.GPIO_Pin=LED1_PIN;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(LED1_PORT,&GPIO_InitStructure);
	
	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);//将TIM3—CH2映射到GPIO中

	
	TIM_TimeBaseInitStructure.TIM_Period=per;//周期值(与预分频值决定计时时间)
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc;//预分频值
	//72000k/预分频值+1=Nk,1k=0.5ms,Nk=1/N ms,再乘周期值等于计数值
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//时钟分频因子
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数模式
	
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//输出模式
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//使能
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;//输出极性
	TIM_OC2Init(TIM3, &TIM_OCInitStructure);
	
	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
	TIM_ARRPreloadConfig(TIM3, ENABLE);
	
	TIM_Cmd(TIM3, ENABLE);
}

main.c

#include "stm32f10x.h"
#include "led.h"
#include "system.h"
#include "SysTick.h"
#include "beep.h"
#include "key.h"
#include "exti.h"
#include "time.h"
#include "pwm.h"
int main()
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置优先级分组
	u16 i=0;
	u8 fx=0;//设置方向标志位
  SysTick_Init(72);
	LED_Init();
	TIM3_CH2_PWM_Init(500,72-1);//0.5ms 2khz//500是自动重装载值
	
	while(1)
	{
//代码解释
//比较值先慢慢加到300,呼吸灯逐步变亮,然后通过fx调节i改变的方向,使其递减,然后呼吸灯逐渐变暗
		if(fx==0)
		{
			i++;
			if(i==300)fx=1;
		}
		else
		{
			i--;
			if(i==0)fx=0;
		}
		TIM_SetCompare2(TIM3,i);
		delay_ms(10);
		
	}
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值