( 1/6 ) ( 3/6 )( 4/6 )( 5/6 )( 6/6 ) 〔マイコンのトップに戻る〕

例)
byte dt ;
void receiveEvent(int howMany)
{
while(Wire.available()) { // 受信データが0個になるまで繰り返す
dt = Wire.read() ; // 1バイト受信する
Serial.print(dt) ; // IDEにシリアル通信で表示する
}
}
Bマスターからの読み出し要求(R/W=1)を受けた時の割込み関数を登録する
例)
byte dt ;
void requestEvent()
{
dt = dt + 0x11 ; // 受信データに0x11だけ足して送り返す
Wire.write(dt) ; // マスターに1バイト送信する
}
マスターからの要求により、AとBが割込み処理されます。
---------------------------------------------------------------------
#include <Wire.h>
byte dt ;
// データを受信すると処理される割込み関数
void receiveEvent(int howMany)
{
while(Wire.available()) {
dt = Wire.read() ; // 1バイト受信する('0'〜'9')
Serial.print(dt) ; // IDEにシリアル通信で表示する
}
}
// データ要求を受信すると処理される割込み関数
void requestEvent()
{
dt = dt + 0x11 ; // 受信データに0x11だけ足して送り返す
Wire.write(dt) ; // マスターに1バイト送信する('A'〜'I')
}
// 電源起動時とリセットの時だけのみ処理する関数
void setup()
{
Serial.begin(9600) ; // シリアル通信の初期化
Wire.begin(8) ; // I2Cの初期化、マイアドレスは8とする
Wire.onRequest(requestEvent) ; // 割込み関数の登録
Wire.onReceive(receiveEvent) ; // 割込み関数の登録
}
// 繰り返し実行されるメインの処理関数
void loop()
{
}
---------------------------------------------------------------------

| ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| 機能 | SMP | D/A | P | S | R/W | BF |
| ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| 機能 | WCOL | SSPOV | SSPEN | SSPM3 | SSPM2 | SSPM1 | SSPM0 |
| ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| 機能 | ACKSTAT | ACKDT | ACKEN | RCEN | PEN | RSEN | SEN |

以下がレジスタ設定の例です。
SSP1STAT= 0b10000000 ; // 標準速度モードに設定する(100kHz)
SSP1CON1= 0b00101000 ; // SDA/SCLピンはI2Cで使用し、マスターモードとする
SSP1ADD = 0x13 ; // クロック=FOSC/((SSPADD + 1)*4) 8MHz/((0x13+1)*4)=0.1(100KHz)
SSP1IE = 1 ; // SSP(I2C)割り込みを許可する
BCL1IE = 1 ; // MSSP(I2C)バス衝突割り込みを許可する
PEIE = 1 ; // 周辺装置割り込みを許可する
GIE = 1 ; // 全割り込み処理を許可する
SSP1IF = 0 ; // SSP(I2C)割り込みフラグをクリアする
BCL1IF = 0 ; // MSSP(I2C)バス衝突割り込みフラグをクリアする
マスターからの書き込み要求(マスターは送信:スレーブは受信)
プログラムのサンプル例
void I2C_Send(unsigned char adrs,int len,char *buf)
{
int i ;
// スタート(START CONDITION)
I2C_IdleCheck(0x5) ;
SSP1CON2bits.SEN = 1 ;
// [スレーブのアドレス+スレーブは受信を要求]を送信する
I2C_IdleCheck(0x5) ;
SSP1BUF = (char)(adrs << 1) ; // アドレスを送信 R/W=0
while(SSP1CON2bits.ACKSTAT==1) ;
// [データ]を送信する
for (i=0 ; i<len ; i++) {
I2C_IdleCheck(0x5) ;
SSP1BUF = (char)*buf ; // データを送信
buf++ ;
while(SSP1CON2bits.ACKSTAT==1) ; // 相手からのACK返答を待つ
}
// ストップ(STOP CONDITION)
I2C_IdleCheck(0x5) ;
SSP1CON2bits.PEN = 1 ;
}
マスターからの読み出し要求(マスターは受信:スレーブは送信)
プログラムのサンプル例
void I2C_Receive(unsigned char adrs,int len,char *buf)
{
unsigned dt ;
int i ;
// スタート(START CONDITION)
I2C_IdleCheck(0x5) ;
SSP1CON2bits.SEN = 1 ;
// [スレーブのアドレス+スレーブへデータ要求]を送信する
I2C_IdleCheck(0x5) ;
SSP1BUF = (char)((adrs << 1)+1) ; // アドレスを送信 R/W=1
while(SSP1CON2bits.ACKSTAT==1) ;
for (i=1 ; i<=len ; i++) {
// [データ]を受信する
I2C_IdleCheck(0x5) ;
SSP1CON2bits.RCEN = 1 ; // 受信を許可する
I2C_IdleCheck(0x4) ;
*buf = SSP1BUF ; // 受信
buf++ ;
I2C_IdleCheck(0x5) ;
if (i==len) SSP1CON2bits.ACKDT = 1 ; // ACKデータはNOACK *4)
else SSP1CON2bits.ACKDT = 0 ; // ACKデータはACK
SSP1CON2bits.ACKEN = 1 ; // ACKデータを返す
}
// ストップ(STOP CONDITION)
I2C_IdleCheck(0x5) ;
SSP1CON2bits.PEN = 1 ;
}
PIC(12F1822)側のプログラム例
スレーブへ1秒毎に"0"〜"9"が繰り返し送信されます。例) int ans ; char buf[4] ; buf[0] = 0x30 ; ans = I2C_Send(8,1,buf) ; // スレーブアドレスは8で1バイト送信する if (ans == 0) 正常に送信した else 異常ans = I2C_Receive(adrs,len,*buf)
例) int ans ; char buf[4] ; ans = I2C_Receive(8,1,buf) ; // スレーブアドレスは8で1バイト受信する if (ans == 0) MonitorPutc(buf[0]) ; // LCDモニターに表示する else 異常
skI2Cmaster.cのライブラリを使ったサンプル例です。
本ライブラリを使う事により下記の如くシンプルに送受信が可能です。
void main()
{
char buf[8] ;
int i , ans ;
OSCCON = 0b01110010 ; // 内部クロックは8MHzとする
ANSELA = 0b00000000 ; // アナログは使用しない(すべてデジタルI/Oに割当てる)
TRISA = 0b00001110 ; // ピンはRA1(SCL)/RA2(SDA)のみ入力(RA3は入力専用)
PORTA = 0b00000000 ; // 出力ピンの初期化(全てLOWにする)
InitI2C_Master() ; // I2C通信:マスターモードでの初期化処理
while(1) {
for (i=0x30 ; i<=0x39 ; i++) {
buf[0] = i ;
ans = I2C_Send(8,1,buf) ; // スレーブに1バイト送信する
if (ans == 0) {
__delay_ms(100) ; // スレーブがデータを準備するまで待つ
I2C_Receive(8,1,buf) ; // スレーブから1バイト受信する
MonitorPutc(buf[0]) ; // LCDモニターに表示する
} else MonitorPuts("NG") ; // スレーブが返答しない
__delay_ms(1000) ; // 1秒ウエイト
}
}
}
interrupt InterI2C()
[前ページ"Arduino(マスター)-PIC(スレーブ)"へ]
[次ページ"複数バイトの送受信"へ]
記事変更(*5) 2020/04/08
NOACK発行処理のバグを変更(*4) 2017/12/20
追記(*3) 2015/07/19
追記(*2) 2012/09/14
追記(*1) 2012/01/21
【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.