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
/* 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
|
extern "C" {
/* Includes ------------------------------------------------------------------*/
/* 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 */
}
|
实例
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
|
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); } }
|