SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|

2004-08-13(Fri) PICのPWM制御、翻訳続き

  なんだか、翻訳し始めたら楽しくなってしまったので、昨日に引き続き、PICのPWM制御機能の翻訳なのである。英語読んで、日本語にして、理解して……と繰り返すうち、最初はわかんなかったことも、なんだかわかったきて、日本語を一部意訳に書き直したりして。こういう技術文書の場合、内容を理解しないと日本語に直してもダメであることを実感した次第である。

  ふと思ったのだが、翻訳は文章を創作するのと違い、気楽な楽しさがあるかもしれない。私は以前、ちょっとモノマネでSFなんぞを書いてた頃があったのだが、創作は到達点が明らかでないという苦しさがある。物語の展開をどっちに持っていくか、正解はないけど決めなくちゃならないからである。それに引き換え、翻訳はひとつひとつ着実に埋めていけば、必ず正解に到達できる。例えるなら、絵を描くのが創作で、ぬり絵を仕上げるのが翻訳というところであろうか。

  エラそうなことをいいつつ、翻訳品質は保障しないのでそのつもりで(一部、理解できてないところもあるし)。

  9.3 PWMモード

パルス幅変化(PWM)モードとは、CCP1ピンに分解能10ビットのPWM出力を行うものです。PORTBデータ・ラッチによりCCP1ピンを多重化してから、TRISBのビットをクリアすることにより、CCP1ピンを出力モードにできます。

注:CCP1CONレジスタをクリアすると、CCP1のPWM出力ラッチはローレベルになってしまいます。これはPORTBのI/Oデータ・ラッチではありません。下図(左)は、CCPモジュールをPWMモードにした場合のブロックダイヤグラムです。CCPモジュールをPWMモードにする方法については、9.3.3節を参照のこと。

PWM出力は、下図(右)のように、PWM周期と有効期間(High出力期間)から構成されています。

PWM周波数はPWM周期の逆数(1/PWM周期)です。

  画像の説明 画像の説明

  9.3.1 PWM周期

PWM周期はPR2レジスタで指定します。PWM周期は次の式で求められます。

PWM周期 = [(PR2) + 1] x 4 x Tosc x (TMR2プリスケーラ設定値)

PWM周波数は(1/PWM周期)として定義されます。

TMR2とPR2と等しい場合、次のPWM周期に以下のことが発生します。

・TMR2のクリア

・CCP1ピンのセット(ただし、PWM有効期間が0%の場合はCCP1ピンはセットされない)

・PWM有効期間はCCPR1HへCCPR1Lからラッチされる

注:Timer2のポストスケーラ(節8.0参照)はPWM周波数には関与しません。

ポストスケーラはPWM出力とは異なる時の周波数サーボアップデートに用いられます。

  9.3.2 PWM有効期間

PWM有効期間は、CCPR1Lレジスタの8ビットとCCP1CON<5:4>の2ビットで指定され、最大10ビット分解能まで利用できます。PWM有効期間は次の方程式で計算できます。

PWM有効期間 = (CCPR1L:CCP1CON<5:4>) x Tosc x (TMR2プリスケーラ設定値)

CCPR1LとCCP1CONの<5:4>で表されるPWM有効期間はいつでも変更できますが、TMR2とPR2が等しくなるまで変更はCCPR1Hへ反映されません(つまり、そのPWM有効期間内は変更されません)。PWMモードにおいて、CCPR1Hは読み出し専用レジスタであり、PWM制御の際に乱れを生じさせないため、CCPR1Hレジスタと内部の2ビットによりPWM有効期間を二重化して記憶しておくあるのです。そして、CCPR1Hレジスタと内部な2ビットがTMR2と一致すると、内部の2ビットのQクロックがTMR2プリスケーラの2ビットに連結され、CCP1ピンがクリアされます。

PWM制御の最大分解能は以下で式で与えられます。

PWM分解能(bits) = log(Fosc / Fpwm) / log(2)

注:PWM周期より、PWM有効期間長い場合、CCP1ピンはOFFになりません。

  9.3.3 PWM制御の設定

CCPモジュールをPWM制御に設定する場合、以下の順序で行う。

;1. PWM周期をPR2レジスタに書き込む
	SET	RP0, (STATUS)	; バンク1へ
	LD	A, 0FFh
	LD	(PR2), A	; PWM周期をFFに
	SET	RP0, (STATUS)	; バンク0へ
;2. PWM有効期間をCCPR1LとCCP1CON<5:4>に書き込む
	LD	A, 40
	LD	(CCPR1L), A	; PWM有効期間に40(25%)をセット
;	RES	4, (CCP1CON)
;	RES	5, (CCP1CON)	; どうせ後で0クリアしてしまう
;3. TRISBをクリアし、CCP1を出力に設定
	SET	RP0, (STATUS)	; バンク1へ
	RES	2, (TRISB)	; 今回はPORTBの2番をPWMする
	SET	RP0, (STATUS)	; バンク0へ
;4. T2CONに書き込み、TMR2プリスケーラを設定、Timer2を有効化する
	LD	A, 00000100b
	LD	(T2CON), A	; TMR2 ON & PRESCALER x 1
;5. CCP1CONをPWMモードに設定する
	LD	A, 0Ch
	LD	(CCP1CON), A	; PWMモードに設定(ついでに分解能の下位2ビットを0固定)
;Note: TRISBの2か3かは、コンフィギュレーションビットの12ビット目(CCPMX)による

  PICの話をしているのに、Z80ニーモニックを持ち出したりして、冗談が過ぎるよこのひとは……なんて思ったかもしれないが、実はこれマジ。ちゃんと動くし、何を隠そう私は実戦で使っているのである。実はPICの変態(インテル)ニーモニックを見たとき、最初から馴染むのをあきらめて、PICアセンブラで処女作を書く前に、Z80ライクニーモニックからPICニーモニックに変換するRubyスクリプトを書いてしまったのである(私以外に使う変態がいるとも思えないが、そのうち公開しよう)。だから私はPICニーモニックは読めるが書けないという、ハンパPICプログラマなのであった。

  中学から高校時代にかけZ80とMC68000のアセンブラに手を染めていたが、イザというときに指がたどったのはZ80ニーモニックであった。十三つ子の魂百までとはまさにこのこと。あな恐ろしや。

  あ、そうそう。ここんとこ毎日ThinkGeekのColdHotSolderToolの在庫が復活するのをチェックしていたのだが、本日めでたく復活していたので、抜く手も見せずに注文してしまった。届いてから十分にレポートするつもりなので、ひとつ楽しみにしておいて頂きたい。