Darkside(リンクエラー修正しました)

2015年1月10日(土) 18:25

真相判明

 ようやく真相判明。
 まず前提知識だが、気圧センサーから1バイトを読み出すには2バイトを送信せねばならない。
・コマンドを1バイト送信する。
・ダミーとして0を送信し、同時に1バイトを受信する。

 次にSTM32におけるハードウェアSPIだが、
・送信はTXEフラグがセットされるのを待ってから行う。
・受信はRNXEフラグがセットされるのを待ってから行う。

 以上のことから、プログラムは以下の手順になっていた。
1)CSをLにする。
2)TXEフラグがセットされるのを待つ。
3)コマンドを1バイト送信する。
4)TXEフラグがセットされるのを待つ。
5)ダミーとして0を送信する。
6)RNXEフラグがセットされるのを待つ。
7)受信データーを1バイト読み出す。
8)BUSYフラグがリセットされるのを待つ。
9)CSをHにする。

 しかし、全二重SPIはその原理上、送信すれば必ず受信が発生する。そして、受信すればRNXEフラグがセットされる。ゆえに、送信すればRNXEフラグがセットされる。
 だから、上記手順の3)を行った時点で、RNXEフラグがセットされる。そのため、6)は一瞬で終了してしまい、5)の直後に7)が実行されてしまうのだ。ソフトウェアSPIであれば、送信と受信は同時に行われるため送受信は1関数になるしフラグ待ちも必要がない。ハードウェアSPIでフラグ待ちが発生するのは、関数が送信してもそれは送信レジスターに書き込むだけであり、関数終了後に実際の送信が開始されているのだろう。
 そうすると、5)の関数が終了しても実際のデーターは最初の1ビットが送り出されているかどうかというタイミングであり、6)を飛ばして7)が実行されると「前のデーター」が読み出されてしまう。具体的には、3)に伴って自動的に受信レジスターに取り込まれた値である。
 だから、正しい値が取得できなかったのである。

 5MHzだけ正しい値が取得できたのは、送受信が高速であるため6)が抜かされても間に合ってしまったと考えられる。
 更に高速な10MHzでも正しい値が取得できたはずだ。信号波形さえナマっていなければ。

 ここで、STM32限定のローカル仕様が登場する。それは、受信データーを読み出せばRNXEフラグがクリアされるというものだ。つまり、3)と4)の間にも6)と7)を実行すれば良い。意味があろうが無かろうが、SPIは送信と受信が常に一体で発生する。だから、最初から終わりまで「送信して受信する」を1セットとして不可分に行わねばならない。
 だったら最初から1関数にしとけよ。自作のソフトウェアSPIみたいに。ソフトだろうがハードだろうが、SPIってそういうものだから。まあ割り込みとかDMAとかやりたいから関数が分割されているのだろう。

 これにより、9)は不要となった。BUSYなど見なくても、CS信号を適切なタイミングで操作できる。

 BUSYを見る必要があったのは、6)が飛ばされてしまい2バイト目の送信が終わる前にCSをHに戻してしまっていたからだ。3日前の↓を再掲する。
 この妙な信号タイミングは、16ビット分のクロックを発生させた後だと思い込んでCSをHに戻していたのだが、実際は8ビット分のクロックしか発生していなかったということだ。

written by higashino [マルチローター] [この記事のURL] [コメントを書く] [コメント(1)] [TB(0)]

この記事へのトラックバックPingURL

Comments

『タイトルなし』

そもそもフルデュープレクスの時はビジーフラグを転送待ちに使うなとマニュアルに明記されてるのに…
自ら"マニュアルよく読まないアフォです"って言ってるようなもんだべ

written by 通行人

TrackBacks

Darkside(リンクエラー修正しました)

Generated by MySketch GE 1.4.1

Remodelling origin is MySketch 2.7.4