我使用STM32Cube初始化代碼生成器來生成初始化的Timer函數。要生成固定佔空比PWM信號,我將HAL_TIM_Base_Start(&htim1); //Starts the TIM Base generation
和HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1)//Starts the PWM signal generation
添加到定時器初始化函數中,如下所示。使用STM32 HAL定時器和調整PWM信號的佔空比
/* Private variables ---------------------------------------------------------*/
int pulse_width=0;
/* TIM1 init function */
static void MX_TIM1_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;//we want a max frequency for timer, so we set prescaller to 0
//And our timer will have tick frequency
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 1066;//max value for timer is 16bit = 65535, TIM_Period = timer_tick_frequency/PWM_frequency - 1
//In our case, for 15Khz PWM_frequency, set Period to TIM_Period = 16MHz/15KHz - 1 = 1066
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)/* to use the Timer to generate a simple time base for TIM1 */
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;//the default clock is the internal clock from the APBx, using this function
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)//Initializes the TIM PWM Time Base according to the specified
//parameters in the TIM_HandleTypeDef and create the associated handle.
{
Error_Handler();
}
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();
}
//sConfig: TIM PWM configuration structure
//set duty cycle: pulse_length = ((1066 + 1) * duty_cycle)/(100 - 1)
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = pulse_width;/* 50% duty cycle is 538, set to 0 initially*///
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();
}
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim1);//output pin assignment
HAL_TIM_Base_Start(&htim1); //Starts the TIM Base generation
if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)//Starts the PWM signal generation
{
/* PWM Generation Error */
Error_Handler();
}
/* Start channel 2 */
if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2) != HAL_OK)
{
/* PWM Generation Error */
Error_Handler();
}
}
這足以運行在上述評論指定的固定的佔空比的PWM,當我硬編碼權值,以在sConfigOC.Pulse = pulse_width
替換pulse_width
值。 在另一個函數中,我有一個算法可以更新pulse_width
全局變量。該功能被稱爲:adjust_PWM();
。該算法計算從ADC測得的值並存儲爲全局變量。該功能稱爲:Data_Update();
。在main()
之後,所有功能都被初始化。我叫這三個功能不休
Data_Update();
adjust_PWM();
MX_TIM1_Init();
我想,和示波器獲得怪異的波形,但可能是因爲ADC引腳,其中浮動,造成浮地測量由算法佔空比干涉。同時調用定時器的初始化會中斷PWM信號。有沒有更好的方法來在不使用全局變量的情況下運行代碼時更改佔空比,或者每次我想更新佔空比時都沒有初始化定時器,是否有更好的方法來改變佔空比。任何鏈接將不勝感激。
最好的方法是擺脫ST「HAL」英國媒體報道並直接編程寄存器。這實際上減少了一半的代碼。 – Olaf
@Olaf直接編程寄存器?你能詳細說明一個更硬件導向的人嗎? – Nadim
閱讀參考手冊(無論如何),只包括來自ST的CMSIS和寄存器定義頭,並直接寫入/讀取外設模塊的寄存器。作爲一個硬件導向的人,這也應該更適合你。這樣你就不必擺弄這個英國媒體報道**和硬件,而只需要硬件。 – Olaf