SNSへはこちら

CH559マイコンをいじってみよう(4) - PWM

どんどん行こう。続いては PWM です。このマイコン、いっちょ前に PWM 付いてます。まあ 8051 をバカにしすぎなんだろうけれど。

PWM構成

そもそも PWM は変調方式そのものの名前ですが、本マイコンではタイマカウンタ + PWM 出力機能ロジックという構成で出来ているようです。データシートによると、Timer3 には PWM 機能があるようですが全く説明されていません。ブロック図タイトルの Notation にはたしかにそう書いてありますが、文章では何一つ説明されず...ブロック図を見て察しろということなんでしょうか。

それに比べて(?)こちらは PWM に特化したペリフェラル。データシートのペリフェラルセクションによると、以下のような構成を持つという:

  • 8bit 幅の PWM が2つ
  • 極性は任意に設定可能
  • PWM3 というものもあるが、こちらは Timer3 の機能を使ったもの。詳細な設定方法は未検証。

そんで、レジスタ一覧を見てみたら結構簡単そうですね。実際にそうでしたので、今回はサラッと行きます。

Duty等の設定

データシート記述をそのまま載せます。

  • PWM1 の Duty は PWM_DATA / PWM_CYCLE で表され、0% から 100% を表現可能
    • PWM_DATA > PWM_CYCLE のとき (Duty 100% 以上の指定のとき)は単に 100% とみなされる

とても素直な仕様ですね。前回の Timer3 が嘘のようだ。

実際の設定

LED ボヤァをやりたかったので割り込みを入れました。LED はコメントにある通り、P2.4 (25番ピン)に刺してください。

なお、先の 48MHz システムクロック設定をすると早すぎて視認不可能ですので、クロック速度はデフォルトスピードのままでコードを実行してもらうと良いと思います。PWM の設定レジスタビット幅が 16bit だったら良かったんだけどね。

あ、そうそう。ピン設定は適用する機能に合わせることが必要です。昔のマイコンコアを使ったものよろしく、ピンの制御は有効化したペリフェラルが乗っ取るのですが、ピン方向は IO ポート設定に左右されます。あと出力モードも。push-pull か open drain か。これはなんかペリフェラルごとの独立性が微妙だなと思いつつも、そういうものだと思ってください。昔のマイコンってこういうことが往々にしてあるし。

// To see LED blur, it is recommended for clock_init to be disabled.
void pwm1_init(void) {
    PWM_CK_SE = 255;

    PWM_CTRL &= ~(1 << 1);

    PWM_CYCLE = 100;
    PWM_DATA = 1; // Initial Value

    PWM_CTRL |= 1 << 3; // PWM1 Output Enable
    PWM_CTRL |= 1 << 7; // Interrupt on each count cycle
    EA = 1;
    IE_EX |= 1 << 5;

    // P2.4(#25)
    PORT_CFG &= ~(1 << 2);
    PORT_CFG |= 1 << (4+2);
    P2_DIR |= 1 << 4;
}

void pwm1_isr(void) __interrupt(11) {
    PWM_DATA = (PWM_DATA + 1) % 100;
    PWM_CTRL |= 1 << 4;
}