Raspberry Pi に乗っけられるlpc1114のボードで相変わらず遊んでいます。
どれくらい短いパルスをこれで生成できるのか実験してみました。PWMを使うのが常識的とは思いますが、ここでは、Ticker で0.1秒程度に1回割り込みをかけて、下のルーチンでいくつかの異なったやり方でGPIOをトグルして、オシロスコープで生成したパルスを観察しました。
void pulse () { // 常識的 LPC_GPIO0->DATA |= 0x0000080; // dp28 set 1 LPC_GPIO0->DATA &=~0x0000080; // dp28 set 0 // faster? int n,n0,n1; n=LPC_GPIO0->DATA; n0= n|0x80; n1= n&(~0x80); LPC_GPIO0->DATA =n0; LPC_GPIO0->DATA =n1; // 他のポートに影響を与える LPC_GPIO0->DATA = 0x80; // dp28 set 1 (affect other pin) LPC_GPIO0->DATA = 0x0 ; // dp28 set 0 }
結果
- 常識的な、ORしてANDしてbit を上げ下げするもの: 104ns
- ポートのデータを読んでおいて、OR, ANDしたものを用意しておいてから、順次書き込む。: 42ns
- 他のポートのことは無視して、定数を書き込む: 62ns
というわけで、一番短くて42ns のパルスが作れることがわかりました。ちっちゃなマイコンなのにすごいね。
PWMを使ってパルスを作るのもやってみましたが、こちらは644ns より短いパルスにならないので論外(ペリフェラルのマニュアル読んでないので、何でか分かってないけど)。
… あとで調べたら、mbedのpwm ではプリスケーラーが30に設定されているために、パルスが短くならないとわかった。
実験ではpin dp18のpwm を使っていた(TMR16B1)ので、これに対応しているレジスタを調整して、パルスを出してみる。
# prescaler 0
TMR16B1->PR=0
# MR3: PWM period maximum 16bit value (一番間隔を長くする)
TMR16B1->MR3=65535
# MR0: PWM duty cycle 16 bit
# この値になったときにパルスが立つので、一番大きな値にすると短いパルスとなる。
TMR16B1->MR0=65535
pin 番号とTMRの関係は、pwmout_api.c とかPinNames.hをみて調べた。
mbedを使わずに直接やってもいいけど、とりあえず実験なので、PwmOut でpwm を使うようにした後にレジスタを書き換えるという乱暴な方法を取りました。まあ、動いているからよい。
結果
20.8ns=(1/48M)のパルスを1.37ms (=65536/48M)間隔で出力することができました。めでたしめでたし。オシロで観察していると、プローブへのGNDラインの引き方でパルスの反射がとってもぐらぐら動くので面白いです。
とりあえず、あとのために、pwm ポートと設定レジスタの対応を下記にまとめる。
- dp1 P0_8 PWM_1 LPC_TMR16B0 MR0
- dp2 P0_9 PWM_2 LPC_TMR16B0 MR1
- dp18 P1_9 PWM_3 LPC_TMR16B1 MR0
- dp24 P0_1 PWM_5 LPC_TMR32B0 MR2