SNSへはこちら

Longan NanoでRISC-Vチャレンジ(7) - エンコーダ・PWM

続いて割り込み以外のタイマー機能である PWM とエンコーダ読み取りを利用してみたいと思います。やっぱり STM32 に似ているなぁという感想。

ところでこの記事シリーズ、STM32 のときと同様にペリフェラルの説明ばかりになっていますが、このような感じで以後やっていきたいと思います。

エンコーダ

通常の割り込みタイマーの設定にチャネルの設定を加えるだけです。
当然、出力レベルやモードの設定不可欠ですが、チャネル出力有効化をしないとどうやっても波形が観測されないのでご注意ください。

以下にコードを示します。TIME_CAR はカウントの上限で、自分の使うエンコーダによって都合のいい値を代入するようにしてください。今回は 1024 カウントで1回転するものを用いていますので、0〜1023 をカウントできるように設定しました。

void timer_encoder_init(void) { // PA0, PA1
    rcu_periph_clock_enable(RCU_GPIOA);
    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1);

    rcu_periph_clock_enable(RCU_TIMER1);
    TIMER_CAR(TIMER1) = 1024 - 1; // maximum value of counting up
    TIMER_SMCFG(TIMER1) = TIMER_ENCODER_MODE0; // encoder mode0
    TIMER_CHCTL0(TIMER1) = (TIMER_IC_SELECTION_DIRECTTI << 0) | (TIMER_IC_SELECTION_DIRECTTI << 8);
    // input channel n is connected to CInFEn
    TIMER_CTL0(TIMER1) = TIMER_CTL0_CEN;
}

uint16_t get_encoder(void) {
    return TIMER_CNT(TIMER1);
}

ピン方法接続は使用するエンコーダICによって異なりますが、例えば単純な機械式ロータリーエンコーダの場合は普通に(?)プルアップしておけばいいです。

ユーザーマニュアルを見ていると TIMER_CHCTL0 の記述がソースコードと微妙に一致しておらず不思議です。意味はなんとなく察してくれ 「それマクロが用意されてるなら使ってみるべ」と使ってみましたが、こう出来上がってみると意味がわかりにくく微妙ですね。ですので CHCTL0 では却ってマクロを使わないほうが良いと思いますね。
ちなみにこの部分は TIMER_CHCTL0(TIMER1) = (0b01 << 0) | (0b01 << 8) という値になります。

CHCTLx は16bitのレジスタで、上位8ビットと下位8ビットで対応するチャネルが違います。どうやら CTCTL0 のビットマクロは対応する1チャネル分の8ビット分を1まとまりとしてセットしてからシフトするというやり方が正しいのだと思います。

PWM

こちらもチャネルの出力設定をすればいいのです。割と簡単ですね。

void timer_pwm_init(void) { // PA1, no AF remapping needed
    rcu_periph_clock_enable(RCU_GPIOA);
    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);

    rcu_periph_clock_enable(RCU_TIMER1);
    TIMER_PSC(TIMER1) = 1000 * 108 / 2 - 1; // prescaler
    TIMER_CAR(TIMER1) = 1000 * 2 - 1; // maximum value of counting up
    TIMER_CH1CV(TIMER1) = 200 * 2 - 1;
    TIMER_CHCTL0(TIMER1) = TIMER_OC_MODE_PWM0 << 8;
    TIMER_CHCTL2(TIMER1) = TIMER_CHCTL2_CH1EN; // Needed for Output
    TIMER_CTL0(TIMER1) = TIMER_CTL0_CEN;
}

他にもコンプリメンタリな PWM モードもありますが、それはやりません。STM32 同様、ちょこっと設定を変えるだけでできるので。

次はアナログ関連です。