#pragma sfr /* 特殊機能レジスタ使用 */ /*============================================================================*/ #include "incs.h" #include "i2c_twl_defs.h" extern u8 vreg_twl[]; #ifdef _MCU_BSR_ //#ifdef _MODEL_TS0_ || _MODEL_WM0_ // ワーキングモデルはI2Cが逆 #define ACKD ACKD0 #define ACKE ACKE0 #define COI COI0 #define IICAEN IICA0EN #define IICRSV IICRSV0 #define IICA IICA0 #define IICAIF IICAIF0 #define IICAMK IICAMK0 #define IICAPR0 IICAPR00 #define IICAPR1 IICAPR10 #define IICCTL0 IICCTL00 #define IICE IICE0 #define IICF IICF0 #define IICS IICS0 #define IICWH IICWH0 #define IICWL IICWL0 #define LREL LREL0 #define SPD SPD0 #define SPIE SPIE0 #define STCEN STCEN0 #define STD STD0 #define SVA SVA0 #define WREL WREL0 #define WTIM WTIM0 #define SMC SMC0 #endif #ifndef _MCU_BSR_ // ke3の時はダミー関数 void IIC_twl_Stop( void ) { } void IIC_twl_Init( void ) { } #else /*============================================================================*/ u8 vreg_adrs; u8 pre_dat; u16 tot; // 注! ↓はマクロなので、returnはメインループに戻ります。 #define wait_next { \ tot = 0; \ while( IICAIF != 1 ){ \ if( SPD ){ \ LREL = 1; \ return; \ } \ tot++; \ if( tot == 0 ){ \ LREL = 1; \ return; \ } \ } \ } __interrupt void int_iic_twl( ) { u8 temp; u16 tot; // WDT_Restart(); // フラグ1回目 スレーブアドレス,R/W /* COI != 1 なら、割り込みはいらない if( COI != 1 ){ // 被呼び出し? LREL = 1; // 呼ばれたのは他のID return; }else{ ACKE0 = 1; // 自動でackを返すようにする WREL = 1; // ウェイト解除して次のバイトを待つ } */ WREL = 1; // ウェイト解除して次のバイトを待つ wait_next; // 1バイト受信完了を待つ // 2回目 R/W レジスタアドレス temp = IICA; IICAIF = 0; WREL = 1; vreg_adrs = adrs_table_twl_ext2int( temp ); // 3回目 // スタートコンディションか、データ受信完了フラグ待ち while( 1 ) { u8 my_iics = IICS; if( my_iics & 0x01 ) // SPD { // 強制終了 LREL = 1; return; } else if( my_iics & 0x02 ) // ( STD && !SPD ) { // 送信 // (スタートコンディション検出) pre_dat = vreg_twl_read( vreg_adrs ); // mcu内部アドレスを渡す。一バイト目の準備 IICBに書き込むとウェイト解除 // 自局をRで呼ばれるのを待つ wait_next; IICAIF = 0; if( COI != 1 ) { // 被呼び出し? LREL = 1; // 呼ばれたのは他のID(あれ?) return; } IICA = pre_dat; // データを送る。ウェイトも解除される。 wait_next; // 4回目。(送信データ後の、ACK/NACK後) どうしても発生してしまう。 IICAIF = 0; // おしまい LREL = 1; return; } else if( IICAIF && (( my_iics & 0x03 ) == 0 )) // !STD && !SPD ) { // 受信 // IICAIF = 0; temp = IICA; WREL = 1; // 通常アクセス(ライト) // LREL = 1; // スタートコンディション待ちへ(連続書き込み未対応のため) vreg_twl_write( vreg_adrs, temp ); return; // 受信おしまい // } } } /*****************************************************/ void IIC_twl_Init( void ) { IICAEN = 1; IICE = 0; /* IICA disable */ IICAMK = 1; /* INTIICA disable */ IICAIF = 0; /* clear INTIICA interrupt flag */ IICAPR0 = 0; /* set INTIICA high priority */ IICAPR1 = 0; /* set INTIICA high priority */ P20 &= ~0x3; SVA = IIC_T_SLAVEADDRESS; IICF = 0x01; STCEN = 1; // リスタートの許可 IICRSV = 1; // 通信予約をさせない:スレーブに徹する SPIE = 0; // ストップコンディションでの割り込みを禁止 WTIM = 1; // 自動でACKを返した後clkをLに固定する ACKE = 1; // ダメCPUは無視して次の通信をはじめるかもしれないんで早くclkを開放しないといけない IICWH = 5; IICWL = 10; // L期間の長さ(?) SMC = 1; IICAMK = 0; // 割り込みを許可 IICE = 1; PM20 &= ~0x3; /* set clock pin for IICA */ LREL = 1; } //**************************************************************************** void IIC_twl_Stop( void ) { IICE = 0; /* IICA disable */ IICAEN = 0; } #endif