どんどん行こう。続いては 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;
}