我是靠谱客的博主 甜甜发卡,这篇文章主要介绍STM32单片机PWM输出学习,现在分享给大家,希望可以做个参考。

STM32单片机PWM输出学习

PWM原理:
PWM表示脉冲宽度调制,它是一系列脉冲,这些脉冲将以方波的形式出现。也就是说,在任何给定的时间点,波型要么是高电平或者是低电平。对于PWM信号我们需要关注两个与之相关的重要参数,一个是PWM占空比,另一个是PWM信号的频率。
在这里插入图片描述占空比 =接通时间 / (接通时间 + 断开时间)

也就是说,通过控制从0%到100%的占空比,我们可以控制PWM信号的“接通时间”,从而控制信号的宽度。由于我们可以通过调节脉冲信号的宽度控制接通时间,所以将这种控制方式称为“脉冲宽度调制”。

频率 = 1 / 总持续时间
总持续时间 = 接通时间 + 断开时间

PWM信号的频率决定了PWM完成一个信号周期的速度。周期是指PWM信号完成一个接通和关闭的时间。

【单片机STM32】通用定时器的PWM输出原理

在这里插入图片描述 在PWM输出模式下,除了CNT(计数器当前值)、ARR(自动重装载值)之外,还多了一个值CCRx(捕获/比较寄存器值)。

当CNT小于CCRx时,TIMx_CHx通道输出低电平;
当CNT等于或大于CCRx时,TIMx_CHx通道输出高电平。

PWM的通道概览 未写完

PWM输出的模式区别
通过设置寄存器TIMx_CCMR1的OC1M[2:0]位来确定PWM的输出模式:

复制代码
1
2
3
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为有效电平,否则为无效电平。

注意:PWM的模式只是区别什么时候是有效电平,但并没有确定是高电平有效还是低电平有效。这需要结合CCER寄存器的CCxP位的值来确定。

***PWM的计数模式***向上或向下计数

自动加载的预加载寄存器

PWM相关配置寄存器
捕获/比较模式寄存器1(TIMx_CCMR1)

捕获/比较使能寄存器(TIMx_CCER)

PWM相关配置库函数

复制代码
1
2
3
4
5
6
7
1个输出初始化函数 void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

作用:在四个通道中选择一个,初始化PWM输出模式、比较输出极性、比较输出使能、比较值CCRx的值。

复制代码
1
2
3
4
5
6
7
1个参数设置函数 void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1); void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2); void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3); void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

作用:在四个通道中选择一个,设置比较值。通常在初始化函数中已经设置了比较值,此函数用于除初始化之外的修改。

复制代码
1
2
3
4
5
6
7
8
2个使能函数 void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

作用:前者在四个通道中选择一个,使能输出比较预装载,后者使能自动重装载的预装载寄存器允许位。

PWM的一般步骤

  1. 使能定时器和相关IO口时钟。调用函数:RCC_APB1PeriphClockCmd();RCC_APB2PeriphClockCmd();

  2. 初始化IO口为复用功能输出。调用函数:GPIO_Init();

  3. 这里我们是要把PB5用作定时器的PWM输出引脚,所以要重映射配置,所以需要开启AFIO时钟。同时设置重映射。调用函数:RCC_APB2PeriphClockCmd();GPIO_PinRemapConfig();

  4. 初始化定时器。调用函数:ARR,PSC等:TIM_TimeBaseInit();

  5. 初始化输出比较参数。调用函数:TIM_OC2Init();

  6. 使能预装载寄存器。调用函数:TIM_OC2PreloadConfig();

  7. 使能定时器。调用函数:TIM_Cmd();

  8. 不断改变比较值CCRx,达到不同的占空比效果。调用函数:TIM_SetCompare2()。

下面按照这个一般步骤来进行一个简单的PWM输出程序:

//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
//psc:时钟预分频数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
void TIM3_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5 //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形 GPIOB.5 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO //初始化TIM3 TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 //初始化TIM3 Channel2 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器 TIM_Cmd(TIM3, ENABLE); //使能TIM3 }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main(void) { u16 led0pwmval=0; u8 dir=1; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为115200 LED_Init(); //LED端口初始化 TIM3_PWM_Init(899,0); //不分频。PWM频率=72000000/900=80Khz while(1) { delay_ms(10); if(dir)led0pwmval++; else led0pwmval--; if(led0pwmval>300)dir=0; if(led0pwmval==0)dir=1; TIM_SetCompare2(TIM3,led0pwmval); } }

NOTE:
关键参数设置:
初始化时钟参数结构体中:

TIM_TimeBaseStructure.TIM_Period = arr
自动重装载寄存器的值arr

TIM_TimeBaseStructure.TIM_Prescaler =psc
分频系数

输出的PWM频率 Hz在这里插入图片描述72M为STM32最高晶振频率

PWM输出舒适化函数
TIM_OCInitStructure.TIM_Pulse =arr * Duty (Pluse脉宽)

PWM占空比 = Duty(≤100%)

最后

以上就是甜甜发卡最近收集整理的关于STM32单片机PWM输出学习的全部内容,更多相关STM32单片机PWM输出学习内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部