2018年12月21日金曜日

1-Wireを使ってみた

 STM32F4で1-WireのDS18B20を使ってみた。
 今回はまじめにstrong pullupを実装した。

 回路図はこんな感じ。


 R1でプルアップ、R3でプルダウン、R2でTXをリミット、という感じ。
 R1は通常のプルアップ。
 R3で非常に弱いプルダウンを作り、リセッシブで3.1V程度になるように調整している。
 R2でマイコンの吸い込みを制限することにより、マイコンがLowに駆動しているのか、デバイスがLowに駆動しているのかを判断できるようにしている。また、この抵抗によりstrong pullupでの負荷で電圧が変動するようにしている。

 今回はSTM32F405RGT(STBee F4mini)のUSART2を1-Wireの通信に使用している。
 通信はNVICで行い、DMAは使用していない。


 通信中の波形はこんな感じ(マイコンのADCでサンプリングした)。


 バスの電圧が3.1V程度で始まり、リセットパルスは100Ωにより0.1V程度までしか落ちていない。
 その後、プレゼンスパルスはデバイスが無制限に吸い込むため、ほぼ0Vまで落ちている。skip ROMとconvert tempはマイコンからの送信のため、こちらも0.1V程度。
 conv tempコマンドの直後にstrong pullupを有効にしているので、一旦3.3V程度まで上昇し、その後、デバイスのADCが開始して消費電流が増えると、100Ωのドロップ分で3.2V付近まで落ちている。
 立ち上がりから電圧のドロップまでは15usec程度しかない。DS18B20のTime to Strong Pullup On(tSPON)はこの期間を指していて、最小で10usecでADCが開始する(最大でも10usec以内にstrong pullupをONにしろ)、ということ。

 マイコンでも10usecくらい簡単に過ぎてしまうので、strong pullupは割り込みで処理している。といっても、UARTの割り込みはタイミングが合わないので、EXTI(ピン変化割り込み)を使っている。
 STM32のGPIOは、オルタネートを使いながらピン変化割り込みを発生させることができる。ただし、HAL_GPIO_Initを使用するとこの初期化が行えないので、自分でGPIOのレジスタを叩いて設定する必要がある。

 また、毎回EXTIを発生させると邪魔なので、strong pullupが必要なコマンドを送る際は、最終ビットを送る直前にEXTIを有効にし、最終ビットが送られたタイミングで割り込みが発生し、このISRの中でEXTIの無効化とAF_ODをAF_PPに変更する処理を行っている。
 次の通信の際は、リセットパルスを送る前にAF_PPからAF_ODに戻す処理を行っている。
 ビットが立ち上がる際は必ずGPIOがHighになっていて、ODはHigh Zだから、これをAF_PPにしてやればLow Z / High levelに固定される。


 その他注意点として、リセットパルスを送る際に1-WireのTx/Rxキューをクリアしたほうがいい。Txはどうでもいいが、ついでなので。
 デバイスがホットプラグで追加された場合、デバイスを挿入した際にプレゼンスパルスが送信されるが、これがRxキューに入ると正常な通信を行えないため。
 1-Wireのバスが使用中でも気にせずにプレゼンスパルスが送信されるから、1-Wireは厳密にはホットプラグは非対応、という感じだろうけども。

***

 ということで、無事にSTM32で1-Wireのstrong pullupが実装できた。3ピン必要かな、と思っていたが、2ピンで処理できた。ほんとは1ピンでできるのが理想だけどね。
 タイマ割り込みとか使えば可能だけど、コスパが悪いのでUARTで2ピン使うほうが良さそう。

 転送速度はもう少し改善できそうな気もするけど、そこまでキチキチにビットレート稼ぐようなバスでもないし。もう少しリファクタリングしたら完了かなー。
 せっかくなので液晶か何かに表示して温度計にしたいが。

0 件のコメント:

コメントを投稿