STM32 PWM设置

PWM

通过控制方波中低平信号长度来控制LED亮度或电机速度。

初始化

Timers内选择一个定时器(以TIM1为例)。Clock Source选择Internal Clock, 选择一个Channel(例如Channel 1)选择PWM Generation CH1, 这时PA8就被选定,我们可以用LED0测试PWM效果了

Prescaler: 72-1
Period: 1000-1
Pulse: 500

这样frequency大致为1000hz(PWMf=TIMf/(prescaler+1)*(Period+1))

PWM.c

需自行加入TIM_SetTIM1Compare函数,更改CCR值。
在Init函数结尾加上 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); 开启pwm

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//TIM1 channel 1, works on PA8
//default psc=72-1, arr=1000-1, pulse=500(almost 50%)
//in this case the frequency is 1000hz

#include "PWM\BSP_PWM.h"

/* USER CODE BEGIN 0 */



/* USER CODE END 0 */

TIM_HandleTypeDef htim1;

/* TIM1 init function */
void MX_TIM1_Init(void)
{

/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */

TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

/* USER CODE BEGIN TIM1_Init 1 */

/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = 72-1;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 1000-1;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */

/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

}

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
{

if(tim_pwmHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspInit 0 */

/* USER CODE END TIM1_MspInit 0 */
/* TIM1 clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
/* USER CODE BEGIN TIM1_MspInit 1 */

/* USER CODE END TIM1_MspInit 1 */
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{

GPIO_InitTypeDef GPIO_InitStruct = {0};
if(timHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspPostInit 0 */

/* USER CODE END TIM1_MspPostInit 0 */

__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM1 GPIO Configuration
PA8 ------> TIM1_CH1
*/
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* USER CODE BEGIN TIM1_MspPostInit 1 */

/* USER CODE END TIM1_MspPostInit 1 */
}

}

void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* tim_pwmHandle)
{

if(tim_pwmHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspDeInit 0 */

/* USER CODE END TIM1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM1_CLK_DISABLE();
/* USER CODE BEGIN TIM1_MspDeInit 1 */

/* USER CODE END TIM1_MspDeInit 1 */
}
}

void TIM_SetTIM1Compare(long int compare)
{
TIM1->CCR1=compare;
}

void Compare_Value_Setting(void)
{
static uint8_t pwm_compare_state=0;
static long int PWM_COMPARE=0;

if (PWM_COMPARE==0) pwm_compare_state=1;
if (PWM_COMPARE>htim1.Init.Period) pwm_compare_state=0;

if (pwm_compare_state){
PWM_COMPARE+=10;
TIM_SetTIM1Compare(PWM_COMPARE);
}
else {
PWM_COMPARE-=10;
TIM_SetTIM1Compare(PWM_COMPARE);
}
}

PWM.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
33
34
35
36
37
38
#ifndef __BSP_PWM_H__
#define __BSP_PWM_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

extern TIM_HandleTypeDef htim1;

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

void MX_TIM1_Init(void);

void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);

/* USER CODE BEGIN Prototypes */

void TIM_SetTIM1Compare(long int compare);

void Compare_Value_Setting(void);

/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif

#endif

实例

LED0会缓慢变亮又变暗,LED初始化必须在TIM1之前。

注意: 如果灯长暗或长亮,检查是不是最开channel里没选pwm generation这类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "main.h"
#include "gpio.h"

#include "PWM\BSP_PWM.h"

void SystemClock_Config(void);

int main(void)
{
HAL_Init();

SystemClock_Config();

MX_GPIO_Init();
MX_TIM1_Init();

while (1)
{
Compare_Value_Setting();
HAL_Delay(10);

}
}