やっぱり手っ取り早いのは __delay_ms(); だ。
PIC24シリーズというかXC16というか、8BITのものとは若干使い方が違ったので放置状態だったが、使い方が分ったので書く。
肝心なのは以下の3行のおまじない。
1 2 3 |
#define FOSC (8000000UL) #define FCY (FOSC/2) #include <libpic30.h> |
システムのクロック(FOSC)を指定し、それを2で割ったものがInstruction Cycle Clock (FCY)になる。
The processor clock source is divided by two to produce the internal instruction cycle clock, FCY. In this document, the instruction cycle clock is also denoted by FOSC/2.
ま、難しいことはよく分からないが、これを書いておけば、__delayが使えるってわけ。
例えばこんな感じ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include "p24fj64gb002.h" #include <xc.h> #define FOSC (8000000UL) #define FCY (FOSC/2) #include <libpic30.h> int main(void){ OSCCONbits.COSC = 0b001;//Fast RC Oscillator with Postscaler and PLL module (FRCPLL) CLKDIVbits.RCDIV = 0b000;//FRC Postscaler Select bits 8 MHz TRISBbits.TRISB2 =0; while(1){ LATBbits.LATB2 = 0; __delay_ms(500); LATBbits.LATB2 = 1; __delay_ms(500); } } |
6ピンにつないだLEDが0.5秒間隔で点滅する。
ちなみに、PICF24では訳の分らない Configuration Bits が山ほどある。
もちろん8BITのPICのConfiguration Bitsもすべてを把握したわけではないが、数がねえ16BITでは全く違って、頭が痛くなる。
というわけで、今回、あれこれこねくり回した挙句どうやら意図した動作にこぎつけたドタバタの記録。
__delay_ms(500);と設定しているのに、実測すると88.06475msとかいう値になる。
あれこれ見直しても直らないので、面倒になってConfiguration Bitsの設定を全て削除してみたら、499.5685msと意図した値になる。
あれこれいじり倒した挙句におかしな設定をしてしまったという毎度のパターンだ。
原因を絞っていくと、
#pragma config FNOSC = FRCPLL // Initial Oscillator Select (Fast RC Oscillator with Postscaler and PLL module (FRCPLL))
となっているとダメで、
#pragma config FNOSC = FRCDIV // Initial Oscillator Select (Fast RC Oscillator with Postscaler (FRCDIV))
ならうまく動く。
もちろん、他の設定との兼ね合いでどうにかなる場合もあるのでこれが直接の原因だとは一概には言えない。
そうは言っても他との兼ね合いまで考慮するとわけ分らなくなるので、とりあえずこのFNOSCとは何ぞやということに絞る。
良く分らないので調べると、PIC24 Family Reference Manual の Section 6. Oscillator によれば以下の通り。
Power-on Reset時に使うClock sourceを決定するんだって。
ついでに同じところの下の表を見るとこうなっていて、
今回の目標である「内蔵のクロックを使って8MHzをPLLでもう少し速くして使いたい。」という場合には、赤枠の設定でいいことが分る。
88.06475msという予期しない値になったときの設定がこれなので、あながちでたらめをやってたわけでもないようだ。
下は、PIC24FJ64GB002 のデータシートから。
ちなみにIDE(v2.35)ではPOSCMDではなくPOSCMODとなっている。
そうなると、結局のところ、Oscillatorの設定に関しては問題は無いが PLL module を含めると変になるということなので、今度はPLLを調べないといけない。
仕方なくPLLがらみを PIC24 Family Reference Manual Section 6. Oscillator で読んでいく。
すると一番大事な勘違いに気付く。
このファミリーには大きく2種類のPLLの仕組みのいずれかが搭載されていて、それは「Basic 4x PLL Block」と「96 MHz PLL Block」である。
PIC24FJ64GB002はUSB機能の付いているPICなので「96 MHz PLL Block」が載っている。
実は、データシートをナナメにしか読まない私は、「96 MHz PLL Block」はUSB機能を使わないなら無関係だと勘違いして、これ関連の設定を全く無視していたのだった。
実際は、たとえUSBは使わなくても、PLLを使うなら必須の設定項目があったのだ。
下のブロック図を見るとそれがよくわかる。
内蔵のOscillatorを使って最速の32MHzで動かすときの設定の流れを赤い矢印で示してある。
そしてたぶん一番肝心なのがこの一文。
PLLには4MHzを入れなきゃいけないので、クロックが8MHzなら一度4MHzにする必要がある。
#pragma config PLLDIV = DIV2 // USB 96 MHz PLL Prescaler Select (Oscillator input divided by 2 (8 MHz input))
これを設定すれば、当初の設定の
#pragma config FNOSC = FRCPLL // Initial Oscillator Select (Fast RC Oscillator with Postscaler and PLL module (FRCPLL))
のままでちゃんと意図した動作をしてくれる。
ただし、#define FOSC (8000000UL) は #define FOSC (32000000UL) と書き直す。
以上で、とりあえず、
内蔵クロック、PLLで最速駆動、delayを使う
が実現できた。
最近お気に入りの光らせ方。