前回はI2C(マスタ)の接続の練習にMicroChip社製24LC64 シリアルE2PROMを使用しました。今回はSPI(マスタ)の接続練習に、やはりMicroChip社製の23LC512 シリアルSRAMを使用してみます。PIC16Fと同じMicroChip社製品なのだから繋がらん筈がないっと。
『PIC三昧』PIC関係の記事総目次はこちら
※作業はMicroChip社の統合開発環境 MPLAB X IDEと、その上で走るコンフィギュレーションツールMCC Classic を使用して行っています。ターゲット・マイコンはPIC16F18855です。
MSSP(Master Synchronous Serial Port)のSPI使い
前回は重厚なお名前のペリフェラルMSSPをI2Cマスタとして使用してみました。今回はSPIマスタです。I2Cスレーブ、SPIスレーブとして設定することもできるので、ようやくその機能の半分だけエクササイズしたって感じですが。
SPI接続するのは23LC512、マイクロチップ社のSRAM
接続してみるのは前回につづいてメモリです。SPIシリアル接続の512KビットSRAMです。8x64K構成です。
通常のSPIモード以外にSDI、SQIモードもサポートしており、より高速な伝送が可能です。ただし、今回はフツーのSPIモードです。入出力とも接続は1本づつね。5Vでも3.3Vでも動作可能なので、今回は3.3V電源づかいでPIC16F18855の信号線とは直結デス。
MCC Classicでのコンフィギュレーション
さて、前回とほぼ同様に、MSSP1とEUSARTをプロジェクトに取り込むことから始めます。EUSARTは結果をUSBシリアル経由でprintfするためっす。
さて、MSSP1の設定が以下に。前回と異なりSPI Masterを設定です。
SPI Modeという欄がありますが、SCKの立ち上がりでサンプリングするか立下りでするか、デフォルトがLoかHiかで4種類の設定があります。相手の周辺装置次第です。今回の23LC512は「素直な」Mode 0でした。データシートの波形など確認しないとなりませぬ。メンドクセー。
さてコンフィギュレーションしたピン配置が以下に。EUSARTのTX/RXはUSBシリアル用にボード上で配線されているので動かせません。
PortAのビット0は例によってLチカ用です。また、PortCのビット6は、SPIのCS信号(ソフトウエア制御)用です。
ハードウエアの接続
今回実験したPIC16F18855と23LC512の接続が以下に。
ブレッドボード上の23LC512との現物接続の様子が以下に。
今回実験に使ったソース
23LC512は64Kバイトの容量があるのですが、最初の方の255バイトを読み書きしてお茶を濁してます。高速な転送用にページ・リード、ページライトなどのモードももっているのですが、チマチマとバイト単位で、読んで、書いてを繰り返してます。アドレスの下8ビットから1引いたデータを書いて、しばらくお休みしてから同じアドレスのデータを読んで確かめてます。
#include "mcc_generated_files/mcc.h" void write23LC512(uint16_t adr, uint8_t dat) { uint8_t buf[4]; buf[0] = 0x02; buf[1] = (adr >> 8) & 0xFF; buf[2] = adr & 0xFF; buf[3] = dat; RC6=0; SPI1_ExchangeBlock(buf, 4); RC6=1; } uint8_t read23LC512(uint16_t adr) { uint8_t buf[4]; buf[0] = 0x03; buf[1] = (adr >> 8) & 0xFF; buf[2] = adr & 0xFF; buf[3] = 0; RC6=0; SPI1_ExchangeBlock(buf, 4); RC6=1; return buf[3]; } void main(void) { uint16_t adr = 1; uint8_t dat; SYSTEM_Initialize(); INTERRUPT_GlobalInterruptEnable(); INTERRUPT_PeripheralInterruptEnable(); printf("23LC512 W/R test.\n"); RC6=1; SPI1_Initialize(); while (1) { adr = adr < 0xFF ? adr + 1 : 1; dat = (uint8_t)(adr - 1); SPI1_Open(0); write23LC512(adr, dat); RA0 = 1; __delay_ms(500); printf("ADR=0x%04x DATA=0x%02x\n", adr, read23LC512(adr)); SPI1_Close(); RA0 = 0; __delay_ms(500); } }
読み書き1バイト毎に標準出力に結果を表示すると同時にLチカもしてます。
実機動作確認
USBシリアルに接続した仮想端末(TeratermPro)の画面が以下に。アドレス引く1の値が読み出せておりますがな。
あたりまえか。