PCからSPIデバイスを制御するアダプタを作りました。
USB経由で動作するものです。
最初はシリアルポートから制御するものを作っていたものの、どうしても入力信号の変化タイミングがおかしくなったりして頓挫しました(涙
ということで、シリアルポート大好き野郎からすると不本意ではありますが、USBマイコンに頼ることとなりました。
[注意] 本機で使用しているUSBのライブラリやUSBのIDについては、マイクロチップ社さんのサンプルで提供されているものを利用しています。よって本機は必ず個人利用の範囲内に留めてください。
こんなものを商品化する方はいないでしょうが、念のため・・・
よくSPIで使われる MISO/MOSI/SCLK/SS(CS) の4本と、一部の特殊なデバイスで Ack や Busy などの制御に使えるよう、入力ポートと出力ポートも設けました。
出力ポートを2本目のSS(CS)信号ピンとして流用すれば、SPIデバイスを2つまで接続できるようになります。
マイコンは5Vで動作させるのに対し、SPIデバイスはひとまず3.3Vとしています。この電圧はデバイスによって変更してください。
マイコンとSPIデバイスの電圧レベルを変換するため 74HC4050 を使っています。マイコン側には3.3Vの入力になりますが、入力スレッショルドを超えているので特に問題はありませんでした。最高速度の12MHzでも安定しています。
消費電力の大きいSPIデバイスの場合、USBのバスパワーでは電力が賄えなくなる可能性があるので外部電源を用意してください。
接続するSPIデバイスによってプルアップ抵抗や使用するピンの処理が異なるため、それぞれのデバイスに合った変換回路が必要になります。と言ってもちょっとした配線だけなので、当方はユニバーサル基板の切れ端で簡単に済ませています。
新たにSPIデバイスが手に入った場合は接続例を追加していきます。
基本的な MISO/MOSI/SCLK/SS(CS) のみ使います。
SPIのモードは0で動作します。
PS1のメモリカードはカードからのAck信号を見る必要があるため、SPIアダプタの入力ピン(IN)をAck制御に使っています。
SPIはモード3、速度は250kHzで動作します。
ダウンロードしたファイルを解凍すると下表のようになります。
フォルダ構成 | 機能 | ||
firm | PICファームウェア | ||
PC | PSMEM | psmr | PS1カード読み込み |
psmw | PS1カード書き込み | ||
SDMMC | sdmmc | SDの主要部ダンプ | |
secdump | SDのアドレス指定ダンプ | ||
TEST | iotest | IOポートの操作・表示 |
私はMPLABを使っていませんので、PICのファームウェアはDOS窓からコンパイルしています。PC用のアプリケーションもすべてDOS窓用です。
それぞれのフォルダにある compile.bat を実行するとコンパイルできるようになっています。
PICのコンパイラはXC8の xc8.exe を使い、PC側はVisualStudio系の cl.exe を使っています。
使い方はそれぞれのフォルダに usage.txt が入っているので参照してください。
SPIモード設定 | |
関数 | void spi_mode(BYTE bMode) |
引数 | bMode 0 : SPIモード0 1 : SPIモード1 2 : SPIモード2 3 : SPIモード3 |
戻り値 | なし |
備考 | デフォルトはモード0になっている。 |
SPI速度設定 | |
関数 | void spi_speed(BYTE bSpeed) |
引数 | bSpeed 0〜255 : SPI速度設定値 |
戻り値 | なし |
備考 | デフォルトは100kHzになっている。 SPIの速度設定値は下記で計算し、0〜255の範囲で指定する。PICの周波数は48MHz(48000kHz)とする。 例えばSPI速度を100kHzにしたい場合は 代表的な周波数 |
Ack制御ON/OFF | |
関数 | void spi_ack(BYTE bAckFlg) |
引数 | bAckFlg 0 : Ack制御OFF 1 : Ack信号立上りで認識 2 : Ack信号立下りで認識 |
戻り値 | なし |
備考 | デフォルトはAck制御はOFFになっている。 Ack制御をONにすると、PICがSPIで1バイト送受信するたびにAck信号の変化を待つようになる。 値の設定には下記の定数が使用できる |
CS制御 | |
関数 | void spi_cs(BYTE bFlg) |
引数 | bFlg 0 : CSピンをLOW 1 : CSピンをHIGH |
戻り値 | なし |
入力ピンの状態取得 | |
関数 | BYTE spi_get_input_pin(void) |
引数 | なし |
戻り値 | 0 : 入力ピンはLOW 1 : 入力ピンはHIGH |
出力ピンの状態設定 | |
関数 | void spi_set_output_pin(BYTE bFlg) |
引数 | bFlg 0 : 出力ピンをLOW 1 : 出力ピンをHIGH |
戻り値 | なし |
出力ピンの状態取得 | |
関数 | BYTE spi_get_output_pin(void) |
引数 | なし |
戻り値 | 0 : 出力ピンはLOW 1 : 出力ピンはHIGH |
データ読み書き(複数バイト) | |
関数 | BYTE spi_rw(BYTE bLen, BYTE *pbSndDat, BYTE *pbRcvDat) |
引数 | bLen 0〜62 : 送受信サイズ pbSndDat pbRcvDat |
戻り値 | 0〜62 : 正常終了 0xFF : エラー |
備考 | 正常終了の戻り値は引数の bLen がそのまま返る 送信データバッファの先頭から順番にSPIで送信され、受信データは受信データバッファに書き込まれる。 受信後のデータのみ必要(送信済みのデータは不要)であれば、送受信バッファは同一のものを指定できる。この場合は送信データの上から受信データが上書きされる。 送信済みのデータを壊さず残しておきたい場合はそれぞれ別のバッファを用意する。 |
データ読み書き(1バイト) | |
関数 | BYTE spi_rw_single(BYTE bDat) |
引数 | bDat 送信データ |
戻り値 | 受信データ |
備考 | 1バイト単位で送受信する場合に使用する。 spi_rw()に比べて送受信バッファを用意しなくて済む。 データの送受信が少量の用途向き。 |
認識が完了したら、サンプルプログラムを実行します。