开发板:野火霸道V1
芯片:stm32f103ZET6
定时器:TIM3
输出通道:CH3
GPIO:PB0
PWM
PWM即脉冲宽度调制,是利用微处理器的数字输出来对模拟电路进行控制的
一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领
域中。
在stm32中,除了基本定时器TIM6、TIM7,其他的都可以用来产生PWM输出。其中高级定时器TIM1、TIM8可以产生7路的PWM输出;而通用定时器TIM2~TIM5可以产生4路的PWM输出。
频率
F = 72M / ((ARR+1)*(PSC+1))
单位:Hz
占空比
Duty_Cycle = ((TIMx->CCRx) / ARR)*100
单位:%
下面的试验是通过调节PWM占空比来观察LED小灯的亮度变化
LED小灯电路
TIM3通道对应的GPIO
通道 | GPIO |
---|---|
CH1 | PA6 |
CH2 | PA7 |
CH3 | PB0 |
CH4 | PB1 |
由于小灯连接到了PB0 所以使用TIM3的通道3
输出比较
输出比较模式由寄存器 CCMRx 的位 OCxM[2:0] 配置
PWM模式有2种
输出比较结构体
1
2
3
4
5
6
7
8
9
10
11typedef struct { uint16_t TIM_OCMode; // 比较输出模式 uint16_t TIM_OutputState; // 比较输出使能 uint16_t TIM_OutputNState; // 比较互补输出使能 uint32_t TIM_Pulse; // 脉冲宽度 uint16_t TIM_OCPolarity; // 输出极性 uint16_t TIM_OCNPolarity; // 互补输出极性 uint16_t TIM_OCIdleState; // 空闲状态下比较输出状态 uint16_t TIM_OCNIdleState; // 空闲状态下比较互补输出状态 } TIM_OCInitTypeDef;
通用定时器输出PWM只需配置部分成员即可
1、TIM_OCMode:比较输出模式选择,总共有八种,常用的为 PWM1/PWM2。它设定 CCMRx 寄存器 OCxM[2:0] 位的值
2、TIM_OutputState:比较输出使能,决定最终的输出比较信号 OCx 是否通过外部引脚输出。它设定 TIMx_CCER 寄存器 CCxE/CCxNE 位的值
3、TIM_OCPolarity:比较输出极性,可选 OCx 为高电平有效或低电平有效。它决定着定时器通道有效电平。它设定 CCER 寄存器的 CCxP 位的值
时基单元结构体
1
2
3
4
5
6
7
8
9typedef struct { uint16_t TIM_Prescaler; // 预分频器 uint16_t TIM_CounterMode; // 计数模式 uint32_t TIM_Period; // 定时器周期 uint16_t TIM_ClockDivision; // 时钟分频 uint8_t TIM_RepetitionCounter; // 重复计算器 } TIM_TimeBaseInitTypeDef;
1、TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器计数时钟 CK_CNT,它设定 PSC 寄存器的值。计算公式为:计数器时钟频率 (fCK_CNT) 等于 fCK_PSC / (PSC[15:0] + 1),可实现 1 至 65536 分频。
2、TIM_CounterMode:定时器计数方式,可设置为向上计数、向下计数以及中心对齐。高级控制定时器允许选择任意一种。
3、TIM_Period:定时器周期,实际就是设定自动重载寄存器 ARR 的值, ARR 为要装载到实际自动重载寄存器(即影子寄存器)的值,可设置范围为 0 至 65535。
4、TIM_ClockDivision:时钟分频,设置定时器时钟 CK_INT 频率与死区发生器以及数字滤波器采样时钟频率分频比。可以选择 1、 2、 4 分频。
5、 TIM_RepetitionCounter:重复计数器,只有 8 位,只存在于高级定时器
TIM3复用功能重映像
使用到的函数
输出比较寄存器
1
2
3
4
5void 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);
预装载寄存器
1
2
3
4
5void 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);
配置的是CCMRx寄存器的OCxPE位
设置占空比
1
2
3
4
5
6//可以用于输出PWM时改变占空比 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);
配置的是CCRx寄存器
上面的函数是与我们选择的通道相对应的
比如本次实验使用的是通道3,所以我们选择
TIM_OC3PreloadConfig()、TIM_SetCompare3()、TIM_OC3Init这三 个函数
编程步骤
- 初始化定时器通道的GPIO
- 配置时基单元
- 配置输出比较寄存器
- 使能预装寄存器
- 使能定时器
- 设置占空比
代码实现
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53#include "bsp_GeneralTimer.h" //初始化用到的 GPIO static void GENERALTIMER_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APBxPeriphClockCmd(GENERALTIMER_CHANNEL_GPIO_CLOCK | RCC_APB2Periph_AFIO,ENABLE); //使能GPIO外设和AFIO复用功能时钟 GPIO_InitStruct.GPIO_Pin = GENERALTIMER_CHANNEL_GPIO_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GENERALTIMER_CHANNEL_GPIO_PORT,&GPIO_InitStruct); } //初始化定时器模式 static void GENERALTIMER_MODE_Config(void) { //时基 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; //输出比较 TIM_OCInitTypeDef TIM_OCInitStruct; GENERALTIMER_TIMx_CLOCK_FUN(GENERALTIMER_TIMx_CLOCK,ENABLE); //配置时基单元 TIM_TimeBaseInitStruct.TIM_Prescaler = GENERALTIME_PSC; //预分频值 TIM_TimeBaseInitStruct.TIM_Period = GENERALTIME_Period; //自动重装载寄存器周期的值 ARR TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //向上计数 TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(GENERAL_TIMEx,&TIM_TimeBaseInitStruct); //配置输出比较 TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2; //PWM模式配置为2 TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; //输出使能 TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; //定时器通道有效电平 TIM_OCxInit(GENERAL_TIMEx,&TIM_OCInitStruct); //使能预装载寄存器 TIM_OCxPreloadConfig(GENERAL_TIMEx,TIM_OCPreload_Enable); //使能寄存器 TIM_Cmd(GENERAL_TIMEx,ENABLE); } void GENERALTIME_Config(void) { GENERALTIMER_GPIO_Config(); GENERALTIMER_MODE_Config(); }
.h文件
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#ifndef _BSP_GENERALTIMER_H #define _BSP_GENERALTIMER_H //TIM3 -> CH3 PB0 #include "stm32f10x.h" //定时器 GPIO #define RCC_APBxPeriphClockCmd RCC_APB2PeriphClockCmd #define GENERALTIMER_CHANNEL_GPIO_CLOCK RCC_APB2Periph_GPIOB #define GENERALTIMER_CHANNEL_GPIO_PORT GPIOB #define GENERALTIMER_CHANNEL_GPIO_PIN GPIO_Pin_0 //定时器 #define GENERAL_TIMEx TIM3 #define GENERALTIMER_TIMx_CLOCK_FUN RCC_APB1PeriphClockCmd #define GENERALTIMER_TIMx_CLOCK RCC_APB1Periph_TIM3 #define GENERALTIME_PSC (36-1) #define GENERALTIME_Period (100-1) //PWM相关函数 #define TIM_OCxInit TIM_OC3Init #define TIM_OCxPreloadConfig TIM_OC3PreloadConfig #define TIM_SetComparex TIM_SetCompare3 void GENERALTIME_Config(void); #endif
在主函数中改变占空比来观察小灯的亮度变化
1
2
3
4
5
6
7
8
9
10
11
12
13#include "bsp_GeneralTimer.h" int main() { GENERALTIME_Config(); while (1) { TIM_SetComparex(TIM3,10); } }
由占空比计算公式得知此时占空比为:10%
最后
以上就是糟糕钢笔最近收集整理的关于stm32输出PWM的全部内容,更多相关stm32输出PWM内容请搜索靠谱客的其他文章。
发表评论 取消回复