STM32Cube初期化コードジェネレータを使用して、初期化されたタイマ機能を生成しました。固定デューティサイクルの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();
}
}
Iハードコード右の値がsConfigOC.Pulse = pulse_width
でpulse_width
値を交換する際にこれが上記のコメントに指定された固定デューティ・サイクルでPWMを実行するのに十分です。 別の関数では、グローバル変数pulse_width
を更新するアルゴリズムがあります。関数はadjust_PWM();
と呼ばれます。アルゴリズムは、ADCから測定され、グローバル変数として格納された値を計算します。その関数はData_Update();
と呼ばれます。 main()
では、すべての関数が初期化された後です。私はそれを試してオシロスコープ上で奇妙な波形を得無限
Data_Update();
adjust_PWM();
MX_TIM1_Init();
これら3つの機能を呼び出し、それはかもしれないアルゴリズムによってデューティ・サイクルを妨害するフローティング測定を引き起こし、フローティングADCピンため。また、タイマーの初期化を連続的に呼び出すと、PWM信号が中断されます。グローバル変数を使用せずに、またはデューティサイクルを更新するたびにタイマを初期化せずに、コードを実行している間にデューティサイクルを変更するより良い方法はありますか?すべてのリンクが評価されます。
最も良い方法は、ST "HAL" bloatwareを取り除き、レジスタを直接プログラムすることです。これにより、コードの半分が実際にはより少ない労力で節約されます。 – Olaf
@Olafはレジスタを直接プログラムしますか?あなたはよりハードウェア指向の誰かのために精緻化できますか? – Nadim
リファレンスマニュアルを読んでください。STのCMSISとレジスタ定義ヘッダーのみを含め、周辺モジュールのレジスタを直接書き込む/読み込みます。ハードウェア指向の人として、これはあなたにさらに適しているはずです。この方法では、このbloatware **と**ハードウェアを使用する必要はありませんが、ハードウェアのみを使用します。 – Olaf