前回のブログで取り上げたオーディオ用のレベルメータにはADコンバータにMCP3208を使いました。SPIインターフェースのICなのでSPIで通信を行うつもりでしたが、BASCOMのSPI1の動作が不確実だったのでSHIFTOUT/SHIFTIN命令でプログラムを作成。
' 従来のShiftin命令の動作を宣言
Config Shiftin = Compatible
' MCP308で6チャンネルのADC読み取り
For Ch = 0 To 5
Reset Cs ' CSをLowにして開始
'=== コマンド送信 ===
' MCP3208: Start bit=1, SGL=1(Diff=0), D2,D1,D0, nullビット
Txsout = &B00011000 Or Ch 'ch=0 to 5
'data-port,clock-port,var,mode (mode=1 clock is up-edge, msb to lsb )
Shiftout Mosi , Sck , Txsout , 1 ' Start + SGL + D2,D1,D0
'=== データ受信(12bit) ===
Shiftin Miso , Sck , Dummy , 1 , 2 ' receive 2-bit (空読み)
Shiftin Miso , Sck , Byteh , 1 , 4 ' receive 4-bit (上位4bit)
Shiftin Miso , Sck , Bytel , 1 , 8 ' receive 8-bit (下位8bit)
Set Cs ' CSをHighにして通信終了
Byteh = Byteh And &B00001111
' 上位4bitと下位8bitをword型に結合して代入
Adc_value(ch) = Makeint(bytel , Byteh)
Next Ch
スタートビットに続けて入力構成(シングル/差動)の設定、そしてチャンネル選択の3ビットを送った後、2ビットの空読みをし、ここから12ビットのデータを読めばOKです。
波形がこちら。(3回分の測定波形 3段目のクロックが8-2-4-8であるのがわかると思います。)

今回試作したものについてはここまで。検討時になぜSPIがうまく動作しなかったのかも含めてブレッドボードで検討を続けたところ様子がわかってきました。SPIを試していると設定を8ビットに収めて送信(SPI1OUT)、続けて8ビットを2回受信(SPI1INを2回)とすることでデータは取れるように。

HELPを見ていたらSPI1OUTとSPI1INの組み合わせではなく、SPI1MOVEでまとめて取れるように思えたので試してみました。コマンド解説にあるRXSPI(1)=SPI1MOVE(TXSPI(1),3) としたところコンパイルでエラー。この構文をSPI0の方(構文はSPIMOVE)でコンパイルをしたらエラーは出ず。え?コンパイラのバグ?と、更新版があるかと調べたら、2.0.8.7がある。(今まで使っていたのは2.0.8.6)
これをダウンロードしてインストール。上記の構文で同様にコンパイルしたらエラーは出ない。ということでコンパイラのバグが原因でした。
Reset Cs ' CSをLowにして開始
'=== コマンド送信 ===
' MCP3208: Start bit=1, SGL=1(Diff=0), D2,D1,D0, nullビット
Txspi(1) = &B00000110 ' スタートビット+シングルエンド指定+チャンネル指定の上1bit
Txspi(2) = &B00000000 ' 上位2bitがチャンネル指定の下2bit
Txspi(3) = &B00000000
rxspi(1) = Spi1move(txspi(1),3 ) 'txspi(1)からtxspi(3)までの3バイト送信(受信データはrxspi()に入る)
Set Cs ' CSをHighにして通信終了
Byteh = rxspi(2) And &B00001111 ' 2バイト目の下位4bitを取り出し rxspi(1)は関係ないので無視
Adc_value(0) = Makeint(rxspi(3) , Byteh) ' 上位4bitと下位8bitをword型に結合して代入 これがADの12bitの測定データ
上が最終のコードで下が波形。

SPI1MOVEを使って無事にデータが取れました。めでたしめでたし。