SDI1 | A1(0b00) | B5(0b01) | B1(0b10) | B11(0b11) | B8(0b100) |
SDO1(0b11) | A1 | B5 | B1 | B11 | |
SS1 | A0(0b00) | B3(0b01) | B4(0b10) | B15(0b11) | B7(0b100) |
SDI2 | A2(0b00) | B6(0b01) | A4(0b10) | B13(0b11) | B2(0b100) |
SDO2(0b100) | A1 | B5 | B1 | B11 | |
SS2 | A3(0b00) | B14(0b01) | B0(0b10) | B10(0b11) | B9(0b100) |
SRXISEL | 拡張バッファ使用時のSPI受信割り込みのタイミング 0-バッファの中身がすべて吐き出された 1-バッファが空でなくなった 2-バッファの半分以上が埋まった 3-バッファがすべて埋まった |
STXISEL | 拡張バッファ使用時のSPI送信割り込みタイミング 0-送信が完了した 1-バッファが空になった 2-バッファが半分以上からになった 3-バッファに空きができた |
DISSDI | SDIピンの使用(1-使用しない) |
MSTEN | マスターモード(1-マスター:0-スレーブ) |
CKP | 1でクロックがない状態をHighとみなす |
SSEN | 1でスレーブ用にSSxピンを使用する |
CKE | データの取得タイミング(0-クロックが開いている[Active]ときに取得:1-閉じている[Idle]ときに取得) |
SMP | マスターでのデータ受信タイミング(0-クロックの中央:1-クロックの終わり) |
MODE16 | 16bit単位で転送(0で8bit単位) |
MODE32 | 32bit単位で転送(0ならMODE16の値が適用される) |
DISSDO | SDOピンの使用(1-使用しない) |
SIDL | アイドル中の停止(1-停止する) |
ON | SPIの実行(1-実行する) |
ENHBUF | 拡張バッファ(FIFOバッファ)の使用(1-使用する) |
SPIFE | 同期エッジの位置(0-立ち下がり:1-立ち上がり) |
MCLKSEL | マスタクロックを使用(0-周辺クロックを使用) |
FRMCNT | フレーム同期信号のタイミング(0-1データごと:1-2:2-4:3-8:4-16:5-32) |
FRMSYPW | フレーム同期信号の長さ(0-1クロック:1-MODE16/32で指定したビット数) |
MSSEN | スレーブ選択の可否(1-スレーブを選択できるようにする) |
FRMPOL | フレーム同期信号の極性(0-Lowで開く:1-Highで開く) |
FRMSYNC | フレーム同期信号の向き(0-出力/マスター:1-入力/スレーブ) |
FRMEN | フレームモードで使用(1-使用) |
Mode | CKP | CKE |
Mode0 | 0 | 1 |
Mode1 | 0 | 0 |
Mode2 | 1 | 1 |
Mode3 | 1 | 0 |
#include <p32xxxx.h>
#include <sys/attribs.h>
// 外部の8MHz水晶発振器から40MHzのクロックを生成するための設定
#pragma config FNOSC = PRIPLL // 発信源 = 主外部発振器
#pragma config POSCMOD = XT // 主発振の方法 = 外部高精度発振器を使う
#pragma config FPLLIDIV = DIV_2 // PLL入力分数 = x1/2
#pragma config FPLLMUL = MUL_20 // PLL逓倍比 = x20
#pragma config FPLLODIV = DIV_2 // PLL出力分数 = x1/2
#pragma config FPBDIV = DIV_2 //周辺モジュールクロック倍数 : x1/2
void send(int addr, int data)
{
LATBbits.LATB0 = 0;
int i, n;
for(i = 0; i < 3; i++){
switch(i){
case 0: n = 0x40; break;
case 1: n = addr; break;
case 2: n = data; break;
}
SPI2BUF = n;
while(SPI2STATbits.SPIBUSY) ; // 処理が完了するのを待つ
}
LATBbits.LATB0 = 1;
}
int main(void)
{
int i, j = 0;
ANSELB = 0x00; // ポートBをすべてデジタルモードにする
TRISB = 0; // ポートBをすべて出力にする
LATBbits.LATB0 = 1; // B0 = on
SPI2CONbits.ON = 0; // 設定のためSPI1を無効に
SPI2BRG = 15; // SPIの周波数を2MHzに
SPI2CONbits.MSTEN = 1; // マスターモード
SPI2CONbits.CKP = 0; // ArduinoにおけるMode0
SPI2CONbits.CKE = 1; // ArduinoにおけるMode0
SDI2Rbits.SDI2R = 0b0100; // B2にSDI2を割り当てる
RPB1Rbits.RPB1R = 0b0100; // B1にSDO2を割り当てる
SS2Rbits.SS2R = 0b0010; // B0にSS2を割り当てる
j = SPI2BUF; // ダミーに出力してバッファをクリア
SPI2CONbits.ON = 1; // SPI2を稼働
// MCP23S17の設定
// 1バイト目はDevice Opecode。0x40で書き込み命令、0x41で読み込み命令
// 2バイト目は制御レジスタ
// 3バイト目はパラメータ
send(0x0A, 0x20); // IOCON[0x0A]、シーケンシャルモードを無効[SEQOP = 1]
send(0x00, 0x00); // IODIRA[0x00]、ポートAのすべてのピンを出力モードに
while(1){
send(0x12, j); // GPIOA[0x12]、すべてのピンのオン(1)・オフ(0)を切り替える
j = ~j; // 0x00<->0xFFに切り替え
for(i = 0; i < 1000000; i++) ;
}
}
#include<SPI.h>
#define SS 10
#define MCP_WRITE 0x40
#define MCP_READ 0x41
void sendBytes(int address, int data)
{
digitalWrite(SS, LOW);
SPI.transfer(MCP_WRITE);
SPI.transfer(address);
SPI.transfer(data);
digitalWrite(SS, HIGH);
}
void setup()
{
pinMode(SS, OUTPUT);
digitalWrite(SS, HIGH);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV2);
sendBytes(0x0A, 0x20); // I/Oの初期設定[SEQOP:1(バイトモード)]
sendBytes(0x00, 0x00); // ポートAをすべて出力にする
}
int p=0;
void loop() {
sendBytes(0x12, 1<<p);
p = (p == 0) ? 7 : 0;
delay(200);
}