BASCOMでMCP3208を動かす

 前回のブログで取り上げたオーディオ用のレベルメータには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であるのがわかると思います。)

shiftout/shiftinでの波形

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

SPI1OUT/SPI1INでの波形

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を使って無事にデータが取れました。めでたしめでたし。