TIMでPWMを出している途中で、TIMの位相を正確に動かしたい、というニッチ(たぶん)な使い方。
1段目がPWMの波形。
2段目がデバッグ用のピン出力。
デバッグ出力がバタバタしたあたりでPWMの位相が50%ほど変化しているのがわかる。
1つ目のエッジで「次の周期で位相を変えなさい」という指示を出す(ループ)。
指示の直後の割り込み(2つ目のエッジ)で周期を調整している(ISR)。
そのままだと以降も周期が短いままなので、その次の割り込み(3つ目のエッジ)で周期を戻している(ISR)。
テストコード
初期化
htim3.Instance->PSC = 0;
htim3.Instance->ARR = tim3_ARR;
htim3.Instance->CCR1 = 500;
HAL_TIM_GenerateEvent(&htim3, TIM_EVENTSOURCE_UPDATE);
HAL_TIM_RegisterCallback(&htim3, HAL_TIM_PERIOD_ELAPSED_CB_ID, TIM3_period);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
osDelay(5);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
__HAL_TIM_CLEAR_IT(&htim3, TIM_IT_UPDATE);
__HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);
osDelay(5);
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
ISR
void TIM3_period(TIM_HandleTypeDef *htim)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_7);
if (htim3.Instance->ARR == tim3_ARR)
{
htim3.Instance->ARR = tim3_ARR / 2;
}
else
{
htim3.Instance->ARR = tim3_ARR;
__HAL_TIM_DISABLE_IT(&htim3, TIM_IT_UPDATE);
}
}
今回は周期・移相量を定数で固定としたが、適当な変数で持たせれば自由に動かせるはず。
また、コールバックを使うので、どこかで#define USE_HAL_TIM_REGISTER_CALLBACKS 1
を定義しておく必要がある。
その他
タイミングクリティカルな処理をゴリゴリやるので、実際に使う際は十分注意すること。今回のテストコードは実環境ではたぶんうまく動かない(低確率でバグる)。