スレーブソース
16F88でI2Cのスレーブを構成します。マスタからの要求に応えて、チャンネル0のAD変換値を返します。実際の処理は、割込み処理 ssp_interupt
() で行っています。state>=0x80 はマスタからのデータ要求ですから、
val= read_adc()>>2;
i2c_write(val);//return value
でデータをマスタに送ります。read_adc()>>2; で2ビット右シフトし、10ビットの測定データの上位8ビットのみを転送しています。
//I2C Slave
//マスタにAD変換値を渡す
//I2Cアドレス 0x42
#include <16F88.h>
//#fuses HS,NOWDT,NOLVP,NOBROWNOUT
#fuses INTRC_IO,NOWDT,NOLVP,NOBROWNOUT
#use delay(clock = 4000000) //設定を間違えるとI2Cの受信を失敗する
#use I2c(slave,sda=PIN_B1,scl=PIN_B4,address=0x42,force_hw)
#use fast_io(B)
#use fast_io(A)
//long val2;
int val;
int state;
#INT_SSP
void ssp_interupt (){
state=i2c_isr_state();
if(state>=0x80){//addrs match with master read
val= read_adc()>>2;
i2c_write(val);//return value
output_toggle(PIN_A0);//受信で点滅
}
else if(state >0){//adrs match with master write
val=i2c_read();
}
}
void main (){
set_tris_a(0x0E);
setup_adc_ports(sAN3);
setup_adc(ADC_clock_div_32);
set_adc_channel(3);
output_float(PIN_B1); //I2C pin float
output_float(PIN_B4); //I2C pin float
set_tris_b(0x36); //I2Cの端子は入力に設定
val=0;
enable_interrupts(INT_SSP); //SSP割り込みを許可
enable_interrupts(GLOBAL); //全ての割り込みを許可
while (1) {
//sleep();
}
}
テスト用マスタ
以下は、I2C接続したAD変換回路のテスト用マスタプログラムです。
i2c_start(); //スタートコンディション
i2c_write(ADdva);
で ADdva のI2Cと接続し、読み取りに必要なパラメータ(チャンネル番号など)を渡しますが、ここでは1チャンネルですので、何も送っていません。続けて、スタートコンディションを送り、ADdva+1
でADdvaのデバイスにデータ送出を要求します。
i2c_start(); //スタートコンディション
i2c_write(ADdva+1);
val=i2c_read(0);
i2c_stop();
val=i2c_read(0); でデータを受け取ります。最後のデータ読み取りには、パラメータ 0 が必須で、これがないとハングアップします。
// I2Cマスターテストプログラム //
//I2CでLED点灯
//I2Cデバイスアドレスは0x62
//コマンド (num,val)、num,valは4bit
//num:桁番号、val:値
//マスタの回路は、C4,C3をI2C接続
//ポートB(下位4bit)、A0 をLED表示(動作確認用)
#include <16f873.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT
#use delay(clock = 20000000)
#use i2c(MASTER,sda=PIN_C4,scl=PIN_C3,FORCE_HW)
//メイン関数/////////////////////////////////////////
#define ADdva 0x42
int val;
void main(){
val=0;
//set_tris_c(0x99); //RB 7-4:IN 3-0:OUT
output_float(PIN_C3); //I2C pin float
output_float(PIN_C4); //I2C pin float
//Cポートに出力する場合、set_tris_c()が必要
delay_ms(100); //wait for Client up
while(1){
output_toggle(PIN_A0);//動作確認
i2c_start(); //スタートコンディション
i2c_write(ADdva);
i2c_start(); //スタートコンディション
i2c_write(ADdva+1);
val=i2c_read(0);
i2c_stop();
output_toggle(PIN_B0);
//valの表示
delay_ms(200);
}
}