今回は内部発振回路を使ったプログラムとした。Configuration bit の記述では 2 種類の内部発振回路を使う記述方法がある。一つは外部にクロックを出力する記述 FOSC = 5 と、他は外部にクロックを出力しない記述の FOSC = 4 。
アセンブラでは
__CONFIG _BODEN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _CPD_OFF & _CP_OFFCC5Xでは
#pragma config BODEN = off, MCLR_off, PWRTE = on, WDTE = off, FOSC = 4, CP_offとなる。
上記の記述はプログラム内で行わずライタで PIC への書き込み時に設定してもいい。これは内部発振周波数の校正値 OSCCAL value の設定も同じ。
C 言語では
#pragma cdata[0x3ff] = 0x349c // この例では 9c が手持ち個体の発振周波数校正値とすることでアセンブラの記述
org 0x3ff retlw 0x349cと同じになる。
校正値を OSCCAL レジスタにセットするにはアセンブラの記述では call 0x3ff としたが、 C 言語での記述では DW 0x2000 + 0x3ff として W レジスタにいったん校正値を読み込んだ後、OSCCAL = W とすればいい。
今回のプログラムでステップ数を調整するために nop(); を使っている。これはアセンブラの nop と同じ。 CC5X では nop(); を 2 回記述する代わりに nop2(); が使える。これはアセンブラの goto $+1 と同じだ。プログラムコードが短くて済むのでコードエリアが節約できる。ところが今回のプログラムに使われている nop(); 二つを nop2(); に置き換えたところ 1 秒の点滅周期が変わってしまった。シミュレータで検証してみたら for ループの最後に記述された nop2(); が実行されていないことが判明した。生成されたアセンブラコードを確認したところやはりすぐ手前の命令で for ループの先頭に戻るような記述となっていた。これは CC5X のコンパイラバグと思われる。この件についてはバグレポートを開発元にメールしたところ、 3-4 週間のうちに訂正するとの返事がきた。
for(;;) { GPIO0 = 1; // GP0 ON delay(244); // 499.992 msec nop2(); // cc5x では goto $+1 を生成する nop2(); // nop(); を二つ記述するのと同じ nop2(); GPIO0 = 0; // GP0 OFF delay(244); nop2(); // プログラムコードが短くて済むので積極的に使った方がいいが nop(); // ここで以下 2 行の nop(); をまとめて nop2(); と記述すると nop(); // コンパイラバグのため最後の nop2(); が実行されない。
}