STM32 PWM

发布于: 2018年06月06日 20:34:57 | 分类: STM32 | 浏览: 96

    终于有时间更新博客啦,前些日子一直在写一个Java小框架还由于一些原因未写完,今天终于得空于是就想来说说stm32如何输出pwm

STM32 PWM简介

    PWM 是'Pulse Width Modulation'的缩写,即脉冲宽度调制.

脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中


STM32 的定时器除了 TIM6TIM7。其他的定时器都可以用来产生PWM输出。其中高级定器 TIM1TIM8可以同时产生多达 7 路的 PWM输出。而通用定时器也能同时产生多达4PWM输出。

Today Blog

    上图就是一个简单的PWM原理图。图中假定定时器工作在向上计数PWM模式,就可以得到当定时器的CNT寄存器值小于CCRx寄存器时,对应通道IO输出低电平,反之为高电平。当定时器CNT值达到ARR寄存器时,会重新归零,重新向上计数,周而复始。所以当改变CCRx寄存器的值,就会改变对应通道IO输出波形的占空比。改变AAR寄存器的值就会改变输出波形的频率。这就是PWM(脉冲宽度调制)原理。

    除了上面提到的寄存器之外,还会用到4个寄存器(通用定时器则只需要3个) 控制PWM的输出。它们分别是:捕获/比较模式寄存器(IMx_CCMR1/2)、捕获/比较使能寄存器)、捕获/比较寄存器(TIMx_CCR1~4) 以及刹车和死区寄存器(TIMx_BDTR)。

    捕获/比较模式寄存器

    该寄存器总共有两个TIMx_CCMR1控制通道一(CH1)和通道二(CH2),TIMx_CCMR2控制通道三(CH3)和通道四(CH4)。下图为该寄存器各个位描述。

    该寄存器的有些位在不同模式下,功能不一样。上面一层对应输出时的设置而下面的则对应输入时的设置。需要说明的是模式设置位OCxM,此部分由3位组成。总共可以配置成7种模式,我们使用的是PWM模式,这3位必须设置为110或者111。这两种PWM模式的区别是输出的电平的极性相反。另外CCxS用于设置通道的方向(输入/输出)默认设置为0,就是设置通道作为输出使用。

    我们介绍捕获/比较使能寄存器(TIMx_CCER),该寄存器控制着各个输入输出通道的开关。该寄存器的各位描述如下图

    该寄存器比较简单,我们这里只用到了CC1E位,该位是输入/捕获1输出使能位,要想PWMIO口输出,这个位必须设置为1,所以我们需要设置该位为1

    最后,介绍一下捕获/比较寄存器(TIMx_CCR1~4),该寄存器总共有4个,对应4个输通道CH1~4。因为这4个寄存器都差不多,我仅以TIMx_CCR1为例介绍,该寄存器的各位描述如下图。

    在输出模式下,该寄存器的值与CNT的值比较,根据比较结果产生相应动作。利用这点,我们通过修改这个寄存器的值,就可以控制PWM的输出脉宽了。如果使用通用定时器,则配置以上三个寄存器就够了,但是如果使用高级定时器,则还需要配置:刹车和死区寄存器(TIMx_BDTR),该寄存器各位描述如下图。 

    该寄存器,我们只需要关注最高位:MOE位,要想高级定时器的PWM正常输出,则必须设置MOE位为1,否则不会有输出。

硬件设计

    至此,我把要用的几个相关寄存器都介绍完了,本次实验要实现通过TIM3_CH2输出PWM。

软件设计

    main.c

#include <stm32f10x.h>
#include <stm32f10x_tim.h>

#include "delay/delay.h"
#include "led/led.h"
#include "pwm/pwm.h"

int main(int argc, char **argv) {

	u16 _CCR2__ = 0;
	u8 dir	 = 1;
	delay_init();	    	 		//延时函数初始化
	TIM3_PWM_INIT(899, 0);	//不分频。PWM频率=72000/(899+1)  -> 80KHZ
	while (1)
	{
		delay_ms(5);
		if(dir) {
			_CCR2__ ++;
		} else {
			_CCR2__ --;
		}
		if(_CCR2__ > 900) {
			dir = 0;
		}
		if (_CCR2__ == 0) {
			dir = 1;
		}
		TIM_SetCompare2(TIM3, _CCR2__); //TIM3 -> CCR2 = _CCR2__;
	}
}

    pwm.h

#ifndef PWM_PWM_H_
#define PWM_PWM_H_

#include <stm32f10x.h>

void TIM3_PWM_INIT(u16 arr, u16 prescaler);

#endif /* PWM_PWM_H_ */

    pwm.h

#include "pwm.h"

#include <stm32f10x_gpio.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_tim.h>

void TIM3_PWM_INIT(u16 arr, u16 prescaler){

	GPIO_InitTypeDef GPIO_InitTypeDef;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
	GPIO_InitTypeDef.GPIO_Mode  = GPIO_Mode_AF_PP;
	GPIO_InitTypeDef.GPIO_Pin   = GPIO_Pin_5;
	GPIO_InitTypeDef.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitTypeDef);

	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);				  //部分重映射


	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeDef;

	TIM_TimeBaseInitTypeDef.TIM_Period 		 = arr; 				   //自动装载值
	TIM_TimeBaseInitTypeDef.TIM_ClockDivision   = TIM_CKD_DIV1;  		 //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseInitTypeDef.TIM_CounterMode 	= TIM_CounterMode_Up; 	//向上计数
	TIM_TimeBaseInitTypeDef.TIM_Prescaler 	  = prescaler; 			 //预分频系数
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitTypeDef);

	TIM_OCInitTypeDef TIM_OCInitTypeDef;
	TIM_OCInitTypeDef.TIM_OCMode 		= TIM_OCMode_PWM2;
	TIM_OCInitTypeDef.TIM_OCPolarity 	= TIM_OCPolarity_High;			//输出极性
	TIM_OCInitTypeDef.TIM_OutputState	= TIM_OutputState_Enable;
	TIM_OCInitTypeDef.TIM_Pulse 		 = 0; 							 //设置待装入捕获比较寄存器的脉冲值

	TIM_OC2Init(TIM3, &TIM_OCInitTypeDef);
	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);   //CH1预装载使能
	TIM_CtrlPWMOutputs(TIM3, ENABLE);				   //MOE 主输出使能
	TIM_ARRPreloadConfig(TIM3, ENABLE); 				//使能TIMx在ARR上的预装载寄存器

	TIM_Cmd(TIM3, ENABLE);							  //使
}

实验效果

标签: STM32
本文为作者原创文章,转载时请务必声明出处并添加指向此页面的链接。
分享:
发表评论

目前您尚未登录,请 登录 后进行评论

评论信息