( 1/6 )( 2/6 ) ( 4/6 )( 5/6 )( 6/6 ) 〔マイコンのトップに戻る〕
IDEに下記のスケッチプログラムをコピーペーストして貼り付けて下さい。
---------------------------------------------------------------------
#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.