.耐思尼克官方网站,北京华昊网站建设,网站建设渠道合作,钮奇网站建设STM32 学习10 PWM输出 一、PWM简介1. PWM的概念2. PWM的工作原理3. PWM 常用的应用场景 二、一些概念1. 频率2. 占空比 三、STM32F1 PWM介绍1. 定时器与寄存器#xff08;1#xff09;**自动重装载寄存器#xff08;ARR#xff09;**#xff1a;#xff08;2#xff09;… STM32 学习10 PWM输出 一、PWM简介1. PWM的概念2. PWM的工作原理3. PWM 常用的应用场景 二、一些概念1. 频率2. 占空比 三、STM32F1 PWM介绍1. 定时器与寄存器1**自动重装载寄存器ARR**2**比较寄存器CCR** 2. PWM的输出模式1PWM模式12PWM模式2 3. 边沿对齐与中心对齐1边沿对齐模式2中心对齐模式 四、PWM输出配置步骤1. 使能定时器及端口时钟2. 定时器的重映像1定时器4复用功能重映像2定时器3复用功能重映像3 定时器2复用功能重映像 3. 输出端口复用4. 初始化定时器参数5. 初始化PWM输出参数6. 开启定时器7. 修改TIMx_CCRx的值控制占空比8. 使能 TIMx 在 CCRx 上的预装载寄存器9. 使能 TIMx 在 ARR上的预装载寄存器允许位10. 设置 MOE位 五、代码示例1. pwm_utils.h2. pwm_utils.c3. main函数实现 一、PWM简介
1. PWM的概念
PWM的全称是脉冲宽度调制Pulse Width Modulation是一种控制模拟信号的方法。它通过改变脉冲的宽度来控制模拟信号的平均值。
2. PWM的工作原理
PWM的工作原理是将一个周期性的脉冲信号与一个控制信号进行比较。当控制信号大于脉冲信号时输出高电平当控制信号小于脉冲信号时输出低电平。通过改变脉冲信号的宽度可以控制输出信号的平均值。
输出信号的平均值连在一起可以达到模拟信号的效果如下图所示
3. PWM 常用的应用场景
电机控制用于控制电机的速度和方向照明控制用于控制灯光的亮度电源管理用于控制电源的输出电压音频控制用于控制声音的大小。
二、一些概念
1. 频率
PWM波形在单位时间内重复出现的次数。
2. 占空比
PWM波形中高电平信号所占的比例。
三、STM32F1 PWM介绍
1. 定时器与寄存器
STM32F1除了基本定时器TIM6和TIM7其它定时器都可以产生PWM输出。其中
TIM1和TIM8均可同时产生7路PWM输出其它通用定时器均可同时产生4路PWM输出。
在STM32微控制器中生成PWM信号通常涉及到自动重装载寄存器ARR和比较寄存器CCR两个重要的寄存器。
1自动重装载寄存器ARR
通过修改ARR的值可以调节PWM信号的周期从而改变PWM信号的频率。当ARR增加时整个PWM信号的周期增加导致PWM信号的频率降低。
2比较寄存器CCR
通过修改CCR的值可以调节PWM信号的占空比从而改变PWM信号的高电平持续时间。CCR的值通常应该小于ARR的值以确保PWM信号的占空比在0到100%之间。当CCR增加时高电平部分的持续时间增加导致PWM信号的占空比增加。
2. PWM的输出模式
PWM输出模式一共8种常用的是PWM1和PWM2其用法差不多区别如下 下表是PWM1和PWM2的区别
1PWM模式1
在该模式下定时器的计数器从0开始递增
当计数器的值小于CCR时输出为高电平当计数器的值大于等于CCR时输出为低电平在计数器达到ARR时产生一个更新事件计数器重新从0开始计数。
这种模式下PWM信号的周期由ARR决定占空比由CCR决定。
2PWM模式2
与PWM模式1相比PWM模式2输出有效性正好是相反的。
下表是PWM1和PWM2的比较
模式CNT 计算方式CNTCCRCNTCCRPWM1递增通道CH有效通道CH无效PWM1递减通道CH无效通道CH有效PWM2递增通道CH无效通道CH有效PWM2递减通道CH有效通道CH无效
3. 边沿对齐与中心对齐
1边沿对齐模式
在边沿对齐模式下PWM信号的起始位置位于PWM周期的起始边沿即ARR然后递增至CCR再递增至ARR最后重复此过程。PWM信号的高电平和低电平都与PWM周期的边沿对齐即从PWM周期的起始边沿开始。边沿对齐模式通常用于需要高精度输出的应用例如需要精确控制PWM信号的起始和终止时间的应用场景。 以上图为例TIMx_CR1寄存器的DIR位为低时递增计数设ARR8当CCRx4时CNT从0增至3的时候输出PWM参考信号0CxREF为有效的高电平CNT从4到8的时候0CxREF输出为低电平
0CXREF表示定时器的比较器
2中心对齐模式
在中心对齐模式下PWM信号的起始位置位于PWM周期的中间然后递增至CCR再递减至0再重复此过程。PWM信号的高电平和低电平都与PWM周期的中心对齐即从PWM周期的中间开始。中心对齐模式通常用于需要调节占空比范围较大的应用例如需要在PWM周期内任意调节占空比的应用场景。由于PWM信号的起始位置位于PWM周期的中间因此可以实现更宽范围的占空比调节。 以上图为例设ARR8当CCRx4时
当CNTCCRx输出为有效信号高电平 当CNTCCRx输出为有效信号低电平
四、PWM输出配置步骤
PWM 的配置在库文件 time.c 中。
1. 使能定时器及端口时钟
下面是使能设置代码
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
2. 定时器的重映像
后面示例的 PWM 需要配置引脚的复用功能重映像定时器的重映像可在《STM32F10x参考手册》查询摘录如下
1定时器4复用功能重映像 2定时器3复用功能重映像 3 定时器2复用功能重映像 以使用 TIM3 的通道1为例它默认是在PA6引脚上它完全重映像是在PC6后面使用的开发板上原理图示 示例代码将使用PC6输出TIM3的通道1 PWM波。
代码示例
// 设置 TIM3 完全重映像
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);3. 输出端口复用
在输出PWM信号时通常需要考虑信号的稳定性、噪声抑制以及输出电流的能力等因素。复用推挽输出是一种常见的配置方式。
// 复用推挽输出
GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF_PP; 4. 初始化定时器参数
包括 自动重载值、分频系数、计数方式等。
void TIM_TimeBaseInit(TIM_TypeDef*TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStructure)5. 初始化PWM输出参数
包括 PWM 模式、输出极性、使能等。
void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStructure);// 结构体定义
typedef struct
{uint16_t TIM_OCMode; // 比较输出模式uint16_t TIM_OutputState; // 比较输出使能uint16_t TIME_OutputNState: // 比较互补输出使能uint32_t TIM_Pulse; // 脉冲宽度 0~65535/*** 输出极性* * TIM_OCPolarity_High: 高电平有效* * TIM_OCPolarity_Low: 低电平有效*/uint16_t TIM_OCPolarity;/*** 互补比较输出极性* * TIM_OCNPolarity_High: 高电平有效* * TIM_OCNPolarity_Low: 低电平有效*/ uint16_t TIM_OCNPolarity;/*** 空闲状态下比较输出状态* * TIM_OCIdleState_Set: 置位* * TIM_OCIdleState_Reset: 复位*/ uint16_t TIM_OCIdleState;/*** 空闲状态下比较输出状态* * TIM_OCNIdleState_Set: 置位* * TIM_OCNIdleState_Reset: 复位*/uint16_t TIM_OCNIdleState;
} TIM_OCInitTypeDef;
6. 开启定时器
// NewState: 新的状态可以是 ENABLE 或 DISABLE。
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState) 7. 修改TIMx_CCRx的值控制占空比
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1);8. 使能 TIMx 在 CCRx 上的预装载寄存器
// 参数 TIM_OCPreload 可为 TIM_OCPreload_Enable、TIM_OCPreload_Disable
void TIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);9. 使能 TIMx 在 ARR上的预装载寄存器允许位
// NewState: 新的状态可以是 ENABLE 或 DISABLE。
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);10. 设置 MOE位
对于高级定时器需要设置MOE位。 MOE 位全称 Master Output Enable是定时器控制寄存器 1 (TIMx-CR1) 中的一个控制位(15位)用于使能或禁用定时器主输出。
MOE 位可以用于控制 PWM 输出的使能和禁用。可以使用 MOE 位来实现软启动和软停止功能。可以使用 MOE 位来实现故障保护功能。
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);五、代码示例
本实验对TIM3控制使用通道1 对TIM3_CH1重映像到PC6引脚控制PC6上接的LED亮度。 示例程序控制LED呼吸灯效果渐渐变亮再渐渐变暗。
1. pwm_utils.h
#ifndef __PWM_UTILS_H__
#define __PWM_UTILS_H__#include stm32f10x.hvoid tim3_ch1_pwm_init(u16 preriod, u16 prescaler);
void tim3_ch1_pwm_set_duty(u16 duty);
#endif
2. pwm_utils.c
#include pwm_utils.h
#include led_utils.h/*** brief 定时器3初始化
*/
void tim3_ch1_pwm_init(u16 preriod, u16 prescaler){// 使能TIM3时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);// 使能LED所在端口的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);// 使能AFIORCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体GPIO_InitStructure.GPIO_Pin GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //设置输出速度为50MHzGPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; //设置为推挽输出模式GPIO_Init(LED_PORT, GPIO_InitStructure); //初始化 LED_PORT// 管脚重映像GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);// 定时器初始化TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Period preriod; //设置自动重装载寄存器周期值TIM_TimeBaseStructure.TIM_Prescaler prescaler; //设置时钟预分频数TIM_TimeBaseStructure.TIM_ClockDivision TIM_CKD_DIV1; //设置时钟分频因子TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up;// 初始化TIM_TimeBaseInit(TIM3, TIM_TimeBaseStructure);// PWM模式1TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_Low; //输出极性:TIM输出比较极性高TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; //比较输出使能TIM_OC1Init(TIM3, TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC1// 使能TIM3的CCR1寄存器预装载TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);// 使能TIM3的ARR寄存器预装载TIM_ARRPreloadConfig(TIM3, ENABLE);// 使能TIM3TIM_Cmd(TIM3, ENABLE);
}
void tim3_ch1_pwm_set_duty(u16 duty){// 设置定时器3的PWM占空比TIM_SetCompare1(TIM3, duty);
}
3. main函数实现
#include gpio_utils.h
#include stm32f10x.h
#include sys_tick_utils.h
#include led_utils.h
#include pwm_utils.h// 主函数
int main(void)
{// led 初始化custom_led_init();// tick 初始化sys_tick_init(72);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// PWM 初始化,2Ktim3_ch1_pwm_init(500, 72-1);led_all_off();int i 0;u8 direction0;while (1) //无限循环{tim3_ch1_pwm_set_duty(i);if(direction0){i;}else{i--;}if(i300){direction 1;}else if(i1){direction 0;}delay_ms(10);}
}
实测PC6的波形是一直变化中 本文代码开源地址 https://gitee.com/xundh/stm32_arm_learn