( 1/6 )( 2/6 ) ( 4/6 )( 5/6 )( 6/6 ) 〔マイコンのトップに戻る〕
--------------------------------------------------------------------- #include <ctype.h> #include <string.h> #include <Wire.h> // 電源起動時とリセットの時だけのみ処理する関数 void setup() { Serial.begin(9600) ; // シリアル通信の初期化 Wire.begin() ; // I2Cの初期化、マスターとする delay(5000) ; // 5秒後に開始 } // 繰り返し実行されるメインの処理関数 void loop() { int ans , i , j ; char dt[8] ; for (i=1 ; i<=3 ; i++) { if (i==1) memcpy(dt,"01",2) ; if (i==2) memcpy(dt,"23",2) ; if (i==3) memcpy(dt,"45",2) ; Wire.beginTransmission(8) ; // 通信の開始処理 Wire.write((byte *)dt,2) ; // 通信データを準備する ans = Wire.endTransmission() ;// データの送信と終了処理 delay(100) ; // スレーブがデータを準備するまで待つ ans = Wire.requestFrom(8,7) ; // スレーブ(8)にデータ送信要求(7バイト受信)をだす for (j=0 ; j<ans ; j++) { // 受信したデータの個数だけ繰り返す dt[j] = Wire.read() ; // 1バイト x 7回のデータを取り出す } dt[j] = 0x00 ; Serial.println(dt) ; // IDEにシリアル通信で表示する delay(1000) ; // 1秒ウエイト } } ---------------------------------------------------------------------PIC(12F1822)側スレーブのプログラム例
--------------------------------------------------------------------- #include <pic.h> #include <htc.h> // delay用に必要 #include <string.h> #include "skI2Cslave.h" // I2C関数ライブラリー用 #define _XTAL_FREQ 8000000 // delay用に必要(クロック8MHzを指定) // コンフィギュレーション1の設定 // CLKOUTピンをRA4ピンで使用する(CLKOUTEN_OFF):内部クロック使用する(INTIO) // 外部クロック監視しない(FCMEN_OFF):外部・内部クロックの切替えでの起動はなし(IESO_OFF) // 電源電圧降下常時監視機能ON(BOREN_ON):ウオッチドッグタイマー無し(WDTE_OFF) // 電源ONから64ms後にプログラムを開始する(PWRTEN_ON) // 外部リセット信号は使用せずにデジタル入力(RA3)ピンとする(MCLRE_OFF) // プログラムメモリーを保護しない(CP_OFF):データメモリーを保護しない(CPD_OFF) __CONFIG(CLKOUTEN_OFF & FOSC_INTOSC & FCMEN_OFF & IESO_OFF & BOREN_ON & PWRTE_ON & WDTE_OFF & MCLRE_OFF & CP_OFF & CPD_OFF) ; // コンフィギュレーション2の設定 // 動作クロックを32MHzでは動作させない(PLLEN_OFF) // スタックがオーバフローやアンダーフローしたらリセットをする(STVREN_ON) // 低電圧プログラミング機能使用しない(LVP_OFF) // Flashメモリーを保護しない(WRT_OFF):電源電圧降下常時監視電圧(2.5V)設定(BORV_25) __CONFIG(PLLEN_OFF & STVREN_ON & WRT_OFF & BORV_25 & LVP_OFF); // メインの処理 void main() { int ans ; OSCCON = 0b01110010 ; // 内部クロックは8MHzとする ANSELA = 0b00000000 ; // アナログ使用しない(すべてデジタルI/Oに割当てる) TRISA = 0b00001110 ; // ピンはRA1(SCL)/RA2(SDA)のみ入力(RA3は入力専用) PORTA = 0b00000000 ; // 出力ピンの初期化(全てLOWにする) InitI2C_Slave(8) ; // スレーブモードでの初期化、マイアドレスは8とする while(1) { ans = I2C_ReceiveCheck() ; // 受信状態のチェック if (ans >= 2) { if ((rcv_data[0]==0x30) && (rcv_data[1]==0x31)) { // "01"コマンド memcpy(snd_data,"Arduino",7) ; } if ((rcv_data[0]==0x32) && (rcv_data[1]==0x33)) { // "23"コマンド memcpy(snd_data,"12F1822",7) ; } if ((rcv_data[0]==0x34) && (rcv_data[1]==0x35)) { // "45"コマンド memcpy(snd_data,"16F1827",7) ; } } } } ---------------------------------------------------------------------
--------------------------------------------------------------------- #include <pic.h> #include <htc.h> // delay用に必要 #include "skMonitorLCD.h" #define _XTAL_FREQ 8000000 // delay用に必要(クロック8MHzを指定) // コンフィギュレーション1の設定 // CLKOUTピンをRA4ピンで使用する(CLKOUTEN_OFF):内部クロック使用する(INTIO) // 外部クロック監視しない(FCMEN_OFF):外部・内部クロックの切替えでの起動はなし(IESO_OFF) // 電源電圧降下常時監視機能ON(BOREN_ON):電源ONから64ms後にプログラムを開始する(PWRTEN_ON) // ウオッチドッグタイマー無し(WDTE_OFF): // 外部リセット信号は使用せずにデジタル入力(RA3)ピンとする(MCLRE_OFF) // プログラムメモリーを保護しない(CP_OFF):データメモリーを保護しない(CPD_OFF) __CONFIG(CLKOUTEN_OFF & FOSC_INTOSC & FCMEN_OFF & IESO_OFF & BOREN_ON & PWRTE_ON & WDTE_OFF & MCLRE_OFF & CP_OFF & CPD_OFF) ; // コンフィギュレーション2の設定 // 動作クロックを32MHzでは動作させない(PLLEN_OFF) // スタックがオーバフローやアンダーフローしたらリセットをする(STVREN_ON) // 低電圧プログラミング機能使用しない(LVP_OFF) // Flashメモリーを保護しない(WRT_OFF):電源電圧降下常時監視電圧(2.5V)設定(BORV_25) __CONFIG(PLLEN_OFF & STVREN_ON & WRT_OFF & BORV_25 & LVP_OFF); // I2C関連の割り込み処理 void interrupt InterI2C( void ) { if (SSP1IF == 1) { // SSP(I2C)割り込み発生か? SSP1IF = 0 ; // フラグクリア } if (BCL1IF == 1) { // MSSP(I2C)バス衝突割り込み発生か? BCL1IF = 0 ; // 今回はフラグのみクリアする(無処理) } } // アイドル状態のチェック // ACKEN RCEN PEN RSEN SEN R/W (BF) が全て0ならOK void I2C_IdleCheck(char mask) { while (( SSP1CON2 & 0x1F ) | (SSP1STAT & mask)) ; } // メインの処理 void main() { unsigned char dt ; int i ; OSCCON = 0b01110010 ; // 内部クロックは8MHzとする ANSELA = 0b00000000 ; // アナログは使用しない(すべてデジタルI/Oに割当てる) TRISA = 0b00001110 ; // ピンはRA1/RA2のみ入力(RA3は入力専用) PORTA = 0b00000000 ; // 出力ピンの初期化(全てLOWにする) // I2C(マスターモード)の初期化 SSP1STAT= 0b10000000 ; // 標準速度モードに設定する(100kHz) SSP1CON1= 0b00101000 ; // SDA(RA2)/SCL(RA1)ピンは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)バス衝突割り込みフラグをクリアする __delay_ms(2000) ; MonitorPutc(0x11) ; // モニターの表示位置を設定する __delay_ms(3000) ; // 5秒後に開始する while(1) { // 英文字の"0"〜"9"を1バイトずつ繰り返し送る for (i=0x30 ; i<=0x39 ; i++) { // スタート(START CONDITION) I2C_IdleCheck(0x5) ; SSP1CON2bits.SEN = 1 ; // [スレーブのアドレス+スレーブは受信(書込み要求)]を送信する I2C_IdleCheck(0x5) ; SSP1BUF = (char)(10 << 1) ; // アドレスは10 R/W=0 while(SSP1CON2bits.ACKSTAT==1) ; // [データ]を送信する I2C_IdleCheck(0x5) ; SSP1BUF = (char)i ; while(SSP1CON2bits.ACKSTAT==1) ; // リピート・スタート(REPEATED START CONDITION) I2C_IdleCheck(0x5) ; SSP1CON2bits.RSEN = 1 ; // [スレーブのアドレス+スレーブへデータ送信要求]を送信する I2C_IdleCheck(0x5) ; SSP1BUF = (char)((10 << 1)+1) ; // アドレスは10 R/W=1 while(SSP1CON2bits.ACKSTAT==1) ; // [データ]を受信する I2C_IdleCheck(0x5) ; SSP1CON2bits.RCEN = 1 ; // 受信を許可する I2C_IdleCheck(0x4) ; dt = SSP1BUF ; // 受信 I2C_IdleCheck(0x5) ; SSP1CON2bits.ACKDT = 1 ; // ACKデータはNOACK SSP1CON2bits.ACKEN = 1 ; // ACKデータを返す // ストップ(STOP CONDITION) I2C_IdleCheck(0x5) ; SSP1CON2bits.PEN = 1 ; // モニターに受信データを送る MonitorPutc(dt) ; // 1秒ウエイト __delay_ms(1000) ; } } } ---------------------------------------------------------------------※リピートスタート機能はPICとPICでの通信はOKでしたが、
[前ページ"PIC(マスター)-Arduino(スレーブ"へ]
[次ページ"PICでのマルチマスターの通信"へ]
追記(*2) 2020/03/05
追記(*1) 2012/09/14
【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.