- PWM
1、PWM概述
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出(1或0)来对模拟电路进行控制的一种非常有效的技术。PWM应用场景如下
- 使用PWM信号控制温度。
- 使用PWM信号控制比例阀的开度
- 使用PWM信号控制电机的转速(直流电机 步进电机 伺服电机)
- 使用PWM信号控制舵机的转向
占空比:占空比是指在一个脉冲循环内,通电时间(可能是高电平,可以低电平)相对于总时间所占的比例。
2、STM32的PWM分析
PWM产生框架图
输出极性:程序设置默念输出的电平。当通道有效,则输出默认的设置电平;通道无效,输出与设置的极性相反的电平
PWM 模式 1–– 在递增计数模式下,只要 TIMx_CNT<TIMx_CCR1,通道 1 便为有效状态,否则为无效状态。在递减计数模式下,只要 TIMx_CNT>TIMx_CCR1,通道 1 便为无效状态( OC1REF=“0”),否则为有效状态( OC1REF=“1”)。
PWM 模式 2–– 在递增计数模式下,只要 TIMx_CNT<TIMx_CCR1,通道 1 便为无效状态,否则为有效状态。在递减计数模式下,只要 TIMx_CNT>TIMx_CCR1,通道 1 便为有效状态,否则为无效状态。
3、PWM产生的流程
通用定时器需要添加的库函数文件:stm32f4xx_tim.c
- 理解电路原理图
LED0连接在PF9,低电平灯亮;高电平,灯灭
TIM14_CH1(TIM14 -- APB1 16位 84MHZ)
(2)使能定时器14和相关IO口时钟。
使能定时器14时钟:RCC_APB1PeriphClockCmd();
使能GPIOF时钟:RCC_AHB1PeriphClockCmd ();
(3)初始化IO口为复用功能输出。
函数:GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
(4)GPIOF9复用映射到定时器14
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);
- 初始化定时器:ARR,PSC等:
TIM_TimeBaseInit();
- 初始化输出比较参数:
TIM_OC1Init();
- 使能预装载寄存器:
TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);
- 使能自动重装载的预装载寄存器允许位
TIM_ARRPreloadConfig(TIM14,ENABLE);
(9)使能定时器。
(10)不断改变比较值CCRx,达到不同的占空比效果:
TIM_SetCompare1();
4、函数说明
void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)
函数说明:复用引脚配置
返回值:无
GPIO_TypeDef* GPIOx:哪组GPIO
uint16_t GPIO_PinSource:哪个引脚
uint8_t GPIO_AF:复用功能
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
函数说明:通道1初始化
返回值:无
TIM_TypeDef* TIMx:哪个定时器
TIM_OCInitTypeDef* TIM_OCInitStruct:通道1结构体
typedef struct
{
uint16_t TIM_OCMode; //通道模式选择
uint16_t TIM_OutputState; //通道使能
uint32_t TIM_Pulse; //设置CCR的值
uint16_t TIM_OCPolarity; //输出极性设置
} TIM_OCInitTypeDef;
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1)
函数说明:设置比较寄存器1
返回值:无
TIM_TypeDef* TIMx:哪个定时器
uint32_t Compare1:设置比较寄存器1的值
- 技术应用
1 呼吸灯,应用舞台、手机、产品效果等
- 无人机
无人机的电机采用PWM进行调速
- 大疆机甲大师
大疆机甲大师采用麦克纳姆轮,可任意方向,任意速度,速度采用PWM进行控制
pwm
#include "pwm.h"
/*****************************************
引脚说明
LED0连接在PF9,低电平灯亮;高电平,灯灭
TIM14_CH1(TIM14 -- APB1 16位 84MHZ)
******************************************/
void Pwm_PF9_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
//使能定时器14时钟:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
//使能GPIOF时钟:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; //引脚9
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; //复用模式
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽式输出
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //50MHZ
GPIO_Init(GPIOF,&GPIO_InitStruct);
//GPIOF9复用映射到定时器14 引脚选定复用的功能
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);
TIM_TimeBaseInitStruct.TIM_Prescaler = 83; //84分频 84MHZ/84 = 1MHZ
TIM_TimeBaseInitStruct.TIM_Period = (1000-1); //ARR的值,在1MHZ计1000个数,周期为1ms
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //计数模式:向上计数
TIM_TimeBaseInitStruct.TIM_ClockDivision= TIM_CKD_DIV1; //分频因子
//2、初始化定时器,配置ARR,PSC。
TIM_TimeBaseInit(TIM14, &TIM_TimeBaseInitStruct);
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; //PWM1模式
TIM_OCInitStruct.TIM_OutputState= TIM_OutputState_Enable; //输出通道使能
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性为低电平
//初始化输出比较参数:
TIM_OC1Init(TIM14, &TIM_OCInitStruct);
//使能预装载寄存器:
TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);
//使能自动重装载(ARR)的预装载寄存器允许位
TIM_ARRPreloadConfig(TIM14,ENABLE);
//使能定时器
TIM_Cmd(TIM14, ENABLE);
}
#ifndef __PWM_H
#define __PWM_H
#include "stm32f4xx.h"
void Pwm_PF9_Init(void);
#endif
#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "delay.h"
#include "tim.h"
#include "pwm.h"
void delay(int n)
{
int i, j;
for(i=0; i<n; i++)
for(j=0; j<20000; j++);
}
int main(void)
{
int key_count = 0;
//设置NVIC分组(一个工程只能设置一个分组)
//第二分组;抢占优先组取值范围:0~3 响应先组取值范围:0~3
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Led_Init();
Delay_Init();
Pwm_PF9_Init();
//设置的值范围:0~999
TIM_SetCompare1(TIM14, 666);
GPIO_ResetBits(GPIOE, GPIO_Pin_14);
while(1)
{
delay_s(1);
}
}
呼吸灯
#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "delay.h"
#include "tim.h"
#include "pwm.h"
void delay(int n)
{
int i, j;
for(i=0; i<n; i++)
for(j=0; j<20000; j++);
}
int main(void)
{
int z=0;
int flag=1;
int key_count = 0;
//设置NVIC分组(一个工程只能设置一个分组)
//第二分组;抢占优先组取值范围:0~3 响应先组取值范围:0~3
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Led_Init();
Delay_Init();
Pwm_PF9_Init();
while(1)
{
//渐亮
if(flag==1)
{
//设置的值范围:0~999
TIM_SetCompare1(TIM14, z++);
if(z==999)
{
flag=2;
}
}
//渐灭
if(flag==2)
{
TIM_SetCompare1(TIM14, z--);
if(z==0)
{
flag=1;
}
}
//GPIO_ResetBits(GPIOE, GPIO_Pin_14);
delay_ms(3);
}
}