■先日入手したARMモジュールSTBee-mini。IDEもなく、エディタでコーディングして、GCCでコンパイルするだけの環境。SPIやUSARTのインターフェースまわりを使いたいのだけど、データシートだけでは今ひとつ解らない。おおまかな手順はわかるのだけど、適切なシーケンスが今ひとつ解らない。そこは手っ取り早くサンプルソースを探した。もちろん、探せば出てくるものだ。
USARTでよく解らなかったのはIOピンのモード設定とペリフェラル選択、USARTのモード設定まわり。とりあえずDMA転送はせずに、単純な1文字送受信から。参考にしたのはWikimuraの「STM32でUSARTを使ってみる」。
SPIについても資料の整備は進められているようでしたが、現時点では詳細がわからず、こちらはまた別途探すことになりました。
USARTはPCとの通信用に必要で、SPIはセンサ類との通信に必要です。ターゲットにしているのは温度センサのLM74。このセンサはAVRで遊んでいた時も使っていて、どういうプログラムモジュールを用意する必要があるのかも解っている。とにかくまずはSPI。WikimuraにSPIモジュールを使う際の注意書きなどはあるけれどコードサンプルが無いので、なにやら茫漠としたまま他をあたる。
探してみると組み込み系の開発会社である(株)テクノロードの掲示板にSPI.zipというSTマイクロからの提供ソースへのリンクがあることを見つけてどうにか。
LM74はSPIのスレーブだけど、データソースなので、SPIマスタであるSTBee-Mini側ではダミーで0x0000を送信することでクロックだけ起こしてLM74からデータを貰います。CS(チップセレクタ)の制御はソフトウェアでSPIとは独立して制御しました。そして、これらのタイミング確認はオシロスコープで。前回掲示した画像がその時の波形。
LM74からのデータ受信はできたのですが、ここでさらに加工が必要。LM74は正負サイン付12ビットで、計13ビットのデータを16ビットデータに押し込んで返してくる。なので、受信した後、後ろ3ビットをカットして、それから2進バイナリを2進化10進(BCD)形式に変換する。
2進からBCDへの変換は、引き算の塊になります。3桁BCDであれば、変換対象の数値から100を繰り返し引いて、次に10を繰り返し引いて、と各桁の値を出していく。意外とこのサンプルが見つからなかった。要領としては次のようになります。実装のやり方は他にもいろいろあると思います。
u32 basedec[7] = {1000000, 100000, 10000, 1000, 100, 10, 1}; char bcd[8] ; void bin2bcd(u32 *src){ u8 n; u8 i; u32 wk; u32 cls; wk = *src; for(i=0;i<7;i++){ bcd[i] = 9; cls = basedec[i]; for(n=0;n<10;n++){ if(wk >= cls) { wk -= cls; } else { bcd[i] = n; break; } } } bcd[7] = 0; }
LM74の受信データ加工ではあと1つ注意がいるのは、データが0.0625刻みだということです。なので、BCDに変換する前に0.0625倍しなければなりません。ただ、小数点を扱おうとすると、BCDでは難しくなり、浮動小数点ライブラリが必要になってくるので、単純に625倍しました。つまり、STM32内部ではLM74のデータを1000倍した値としてBCD化するわけです。小数点以下は失われますが、表示する時に適切な桁で小数点を表示すれば済む話です。
従って、LM74のデータを8で割り、625倍します(負数の処理はまた別として)。面白かったのは1つの式の中で8で割り、625倍すると誤差が出たことです。コンパイラ内部で割って掛けるか、掛けてから割るかの違いだと思うのですが、数式ではx=625*y/8で、内部処理でどちらを先にしても変わってはならないのですが、そうはなっていません。たぶん、最適化の処理でx=y*(625/8)とされてしまい、丸め誤差が出たためではないかと推測しています。
そのため、まずy=y/8としてから625倍したところ、適切に処理されるようになりました。このあたりのコンパイラのクセも、仕事ではちょっとやってられないところですが、ホビーということもあって、ちょっと面白いところです。