こんにちは、
S32K1xxとFTM 入力キャプチャを使用して PWM 信号を測定しています。
現在、1 つのチャネル (例: FTM0_CH1) を使用して周波数を取得できます。
同じチャネルを使用して周波数とデューティ サイクルの両方を測定するにはどうすればよいでしょうか?
SDK またはプロセッサ Expert 構成を使用して、同じ FTM チャネル内でエッジ (立ち上がり/立ち下がり) を切り替えることは可能ですか?
例や推奨方法があれば教えていただけると幸いです。
よろしくお願いします!
こんにちは、レオさん。返信ありがとうございます。
現在のプロジェクトでは、 S32 Design Studio for Arm v2.2 そして S32SDK_S32K1xx_RTM_3.0.0なので、最新の IDEs または SDKs バージョンにアップグレードするのは便利ではありません。
ご提供いただいたサンプルをダウンロードし、それをどのように設定すれば良いか理解しました。 デューティサイクル そして 周期測定。しかし、私の主な疑問は、どのように使用するかということです 単一チャネル 両方を測定する PWMデューティサイクルと周期 同時に、つまり、両方の例を 1 つに結合する方法です。
デューティ サイクルと周期測定の両方の例を一緒に実装する方法が見つからなかったSO、コード内のキャプチャ エッジ (立ち上がり/立ち下がり) を切り替えて測定を実行してみました。
このアプローチが許容可能または推奨されるかどうかを確認してください。
static uint32_t read_ts32_ch2(void)
{
uint32_t ovf_before = g_ftm_ovf;
(void)FTM0->CONTROLS[2].CnSC; // Clear CHF step 1
uint32_t cap32 = FTM0->CONTROLS[2].CnV; // Clear CHF step 2 & get timestamp
uint16_t cap16 = (uint16_t)(cap32 & 0xFFFFu); // Only the lower 16 bits are valid
uint32_t ovf_after = g_ftm_ovf;
// If overflow occurred after capture and cap16 is small,
// assume the capture happened before the overflow and apply compensation
if ((ovf_after != ovf_before) && (cap16 < 0x8000u)) {
ovf_before++;
}
return (ovf_before << 16) | cap16;
}
#if 1 // Function works but sometimes has errors due to edge-switching jitter
void FTM0_CH2_Input_Detect(void)
{
uint32_t cap_ts = read_ts32_ch2(); // Captured channel counter value
//bool PwmIOStatus = FTM_DRV_GetChnEventStatus(FTM0,2);
// ---------- Rising edge ----------
//if (PwmIOStatus & (1u << 2))
//{
if(!waiting_fall)
{
/* ---------- Rising edge ---------- */
rise_prev = rise_curr;
rise_curr = cap_ts;
/* Arm the next edge: falling edge */
waiting_fall = 1;
FTM0->CONTROLS[2].CnSC =
(FTM0->CONTROLS[2].CnSC & ~(FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK)) |
(FTM_CnSC_ELSB_MASK);
if (got_first_rise)
{
period_cnt = (uint32_t)(rise_curr - rise_prev);
if (period_cnt == 0u)
{
got_first_rise = 0;
} /* Protection */
else
{
pwm_freq_hz = frequency / period_cnt;
}
}
else
{
got_first_rise = 1;
}
}
else
{
/* ---------- Falling edge ---------- */
fall_curr = cap_ts;
/* Switch back to rising edge */
waiting_fall = 0;
FTM0->CONTROLS[2].CnSC =
(FTM0->CONTROLS[2].CnSC & ~(FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK)) |
(FTM_CnSC_ELSA_MASK);
if (got_first_rise && (fall_curr >= rise_curr))
{
high_cnt = (uint32_t)(fall_curr - rise_curr);
if ((period_cnt != 0) && (pwm_freq_hz != 0))
{
// duty_pct = ((float)high_cnt * 100.0f) / (float)period_cnt;
new_sample = 1;
}
}
}
/* Redundant flag clear */
// FTM0->STATUS = (1u << 2);
//}
}こんにちは、レオさん。返信ありがとうございます。
現在のプロジェクトでは、 S32 Design Studio for Arm v2.2とS32SDK_S32K1xx_RTM_3.0.0を使用しているSO、最新の IDEs または SDKs バージョンにアップグレードするのは便利ではありません。
ご提供いただいた例をダウンロードし、デューティ サイクルと周期の測定を取得するように構成する方法を理解しました。しかし、私の主な疑問は、 1 つのチャネルを使用してPWM デューティ サイクルと周期の両方を同時に測定する方法、つまり、両方の例を 1 つに組み合わせる方法です。
デューティ サイクルと周期測定の両方の例を一緒に実装する方法が見つからなかったSO、コード内のキャプチャ エッジ (立ち上がり/立ち下がり) を切り替えて測定を実行してみました。
このアプローチが許容可能または推奨されるかどうかを確認してください。
static uint32_t read_ts32_ch2(void)
{
uint32_t ovf_before = g_ftm_ovf;
(void)FTM0->CONTROLS[2].CnSC; // Clear CHF step 1
uint32_t cap32 = FTM0->CONTROLS[2].CnV; // Clear CHF step 2 & get timestamp
uint16_t cap16 = (uint16_t)(cap32 & 0xFFFFu); // Only the lower 16 bits are valid
uint32_t ovf_after = g_ftm_ovf;
// If overflow occurred after capture and cap16 is small,
// assume the capture happened before the overflow and apply compensation
if ((ovf_after != ovf_before) && (cap16 < 0x8000u)) {
ovf_before++;
}
return (ovf_before << 16) | cap16;
}
#if 1 // Function works but sometimes has errors due to edge-switching jitter
void FTM0_CH2_Input_Detect(void)
{
uint32_t cap_ts = read_ts32_ch2(); // Captured channel counter value
//bool PwmIOStatus = FTM_DRV_GetChnEventStatus(FTM0,2);
// ---------- Rising edge ----------
//if (PwmIOStatus & (1u << 2))
//{
if(!waiting_fall)
{
/* ---------- Rising edge ---------- */
rise_prev = rise_curr;
rise_curr = cap_ts;
/* Arm the next edge: falling edge */
waiting_fall = 1;
FTM0->CONTROLS[2].CnSC =
(FTM0->CONTROLS[2].CnSC & ~(FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK)) |
(FTM_CnSC_ELSB_MASK);
if (got_first_rise)
{
period_cnt = (uint32_t)(rise_curr - rise_prev);
if (period_cnt == 0u)
{
got_first_rise = 0;
} /* Protection */
else
{
pwm_freq_hz = frequency / period_cnt;
}
}
else
{
got_first_rise = 1;
}
}
else
{
/* ---------- Falling edge ---------- */
fall_curr = cap_ts;
/* Switch back to rising edge */
waiting_fall = 0;
FTM0->CONTROLS[2].CnSC =
(FTM0->CONTROLS[2].CnSC & ~(FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK)) |
(FTM_CnSC_ELSA_MASK);
if (got_first_rise && (fall_curr >= rise_curr))
{
high_cnt = (uint32_t)(fall_curr - rise_curr);
if ((period_cnt != 0) && (pwm_freq_hz != 0))
{
// duty_pct = ((float)high_cnt * 100.0f) / (float)period_cnt;
new_sample = 1;
}
}
}
/* Redundant flag clear */
// FTM0->STATUS = (1u << 2);
//}
}当社製品にご興味をお持ちいただき、また当社コミュニティに貢献していただき、ありがとうございます。
RTD の最新バージョンに更新すると、最近のバグ修正とパフォーマンスの向上のメリットが得られます。現在使用しているバージョンは数リリース前のものなので、安定性と互換性に影響する可能性があります。RTD を最新の状態に保つことで、最新の機能や拡張機能にアクセスできるようになります。
S32K1xx シリーズを使用した開発では、最新の S32DS および RTD バージョンを使用することをお勧めします。
• S32 Design Studio 3.6.4 – Windows/Linux
• S32K1_S32M24X リアルタイム・ドライバ AUTOSAR R21-11 バージョン 3.0.0
IDEをダウンロードするには、 S32プラットフォーム用のS32 Design Studioページにアクセスしてください-> ダウンロード ->
S32 Design Studio 3.6.4 – Windows/Linux
RTD をダウンロードするには、 S32K1ページ-> デザイン リソース -> ソフトウェア -> S32K1 用リアルタイム・ドライバ -> オートモーティブ SW - S32K1_S32M24x - Cortex-M 用リアルタイム・ドライバにアクセスしてください。
各SWへのインストールフロー/詳細についてはリリースノートをご確認ください。
…
SW をインストールしたら、デューティ サイクルと周期の測定については添付の例を参照できます。
ftm0_ch0 (PTD15) を PWM として、ftm1_ch2 (PTC14) を ICU として設定します。SO、テストのために接続してください。さらに、PTD16 はデバッグ目的のためだけに、測定開始前と測定停止後に切り替わります。
式タブで結果を確認します:
次の RTD を使用して例が構築およびテストされました。
- S32K1_S32M24X リアルタイム・ドライバ AUTOSAR R21-11 バージョン 3.0.0
この情報が役に立つことを願います。リアルタイム・ドライバ (RTD) の使用に関してさらに質問がある場合は、お気軽にお問い合わせください。