前回のブログで取り上げたオーディオ用のレベルメータには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を使って無事にデータが取れました。めでたしめでたし。