一、PWM概念
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制,PWM原理如图1所示:
图1:PWM原理示意图
二、配置PWM模式介绍
脉冲宽度调制模式可以生成一个信号,该信号频率由TIMx_ARR寄存器值决定,其占空比则由TIMx_CCRx寄存器值决定。
通过向TIMx_CCMRx寄存器中的OCxM位写入110(PWM模式1)或111(PWM模式2),可以独立选择各通道(每个OCx输出对应一个PWM)的PWM模式。必须通过将TIMx_CCMRx寄存器中的OCxPE位置1使能相应预装载寄存器,最后通过将TIMx_CR1寄存器中的ARPE位置1使能自动重载预装载寄存器。
由于只有在发生更新事件时预装载寄存器才会传送到影子寄存器,因此启动计数器之前,必须通过将TIMx_EGR寄存器中的UG位置1来初始化所有寄存器。
OCx极性可使用TIMx_CCER寄存器的CCxP位来编程。既可以设为高电平有效,也可以设为低电平有效。OCx输出通过将TIMx_CCER寄存器中的CCxE位置1来使能。详细信息内容,可参见TIMx_CCERx寄存器说明。
三、PWM边沿对齐模式介绍
下面图2展示了PWM边沿对齐模式的相关内容信息。
图2:PWM边沿对齐模式图
四、PWM代码配置步骤
- 开启TIM14和GPIO时钟,配置PF9选择复用功能AF9(TIM14)输出
- 初始化TIM14,设置TIM14的ARR和PSC等参数
- 设置TIM14_CH1的PWM模式,使能TIM14的CH1输出
- 使能TIM14
- 修改TIM14_CCR1来控制占空比
五、结构体TIM_OCInitTypeDef的定义及相关参数说明
typedef struct{
uint16_t TIM_OCMode;
uint16_t TIM_OutputState;
uint16_t TIM_OutputNState;
uint16_t TIM_Pulse;
uint16_t TIM_OCPolarity;
uint16_t TIM_OCNPolarity;
uint16_t TIM_OCIdleState;
uint16_t TIM_OCNIdleState;
} TIM_OCInitTypeDef;
涉及PWM定时器中所用到的参数要求相关的几个成员变量如下:
参数TIM_OCMode设置模式是PWM还是输出比较,这里我们选择PWM模式。
参数TIM_OutputState用来设置比较输出使能,也就是使能PWM输出到端口。
参数TIM_OCPolarity用来设置极性是高还是低。
而其他的参数TIM_OutputNState,TIM_OCNPolarity,TIM_OCIdleState和TIM_OCNIdleState是高级定时器才会用到。
六、代码示例
1、tim14.c
//TIM14 PWM部分初始化//PWM输出初始化
//arr:自动重装值psc:时钟预分频数
void TIM14_PWM_Init(u32 arr,u32 psc){
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);//TIM14时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); //使能PORTF时钟
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //GF9复用为TIM14
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化PF9
TIM_TimeBaseStructure.TIM_Prescaler=psc; //定时器分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM14,&TIM_TimeBaseStructure);//初始化定时器14
//初始化TIM14 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWM调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性低
TIM_OC1Init(TIM14, &TIM_OCInitStructure); //初始化外设TIM1 4OC1
TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); //使能预装载寄存器
TIM_ARRPreloadConfig(TIM14,ENABLE);//ARPE使能
TIM_Cmd(TIM14, ENABLE); //使能TIM14
}
2、tim14.h
#ifndef _TIM14_H_
#define _TIM14_H_
#include "stm32f4xx.h"
#include "stdio.h"
#include "led.h"
void TIM14_PWM_Init(u32 arr,u32 psc);
#endif
3、main.c
int main(void){
u16 led0pwmval=0;
u8 dir=1;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
SsyTick_Init(168);//初始化延时函数
usart1_init(115200);//初始化串口波特率为115200
TIM14_PWM_Init(500-1,84-1);//定时器时钟为84M,分频系数为84,所以计数频率
//为84M/84=1Mhz,重装载值500,所以PWM频率为1M/500=2Khz.
while(1){
Delay_ms(10);
if(dir)led0pwmval++; //dir==1 led0pwmval递增
else led0pwmval--; //dir==0 led0pwmval递减
if(led0pwmval>300)dir=0;//led0pwmval到达300后,方向为递减
if(led0pwmval==0)dir=1;//led0pwmval递减到0后,方向改为递增
TIM_SetCompare1(TIM14,led0pwmval);//修改比较值,修改占空比
}
}
七、下载结果验证说明
我们将编译好的文件下载到我们的硬件设备上,观看其运行结果是否与我们编写的一致。如若没有错误我们将看DS0不停的由暗变到亮,然后又从亮变到暗。每个过程持续时间大概为3秒钟左右。实际运行结果如下图3所示:
图3:PWM控制DS0亮度
八、总结
1、确定硬件连接,将 DS01 连接到微控制器的一个可用的 GPIO 引脚。
2、初始化并配置 PWM 模块,设置时钟源、预分频器和计数周期等。
3、选择一个 PWM 通道,配置周期和占空比,确定 PWM 信号的频率和亮度级别。
4、启动 PWM 模块和所选择的 PWM 通道,开始生成 PWM 信号。
5、通过调整 PWM 通道的占空比来调整 DS01 的亮度级别,较高的占空比意味着更亮的亮度,较低的占空比意味着更暗的亮度。
6、若要实现自动亮度调节,可以使用传感器或其他输入信号来监测环境亮度,并使用反馈控制算法实时调整 PWM 通道的占空比。
注意:本人所写文章内容均用于记录自己在学习嵌入式的成长过程!!!!!