ctr_mcu/branches/0.10(fix)/i2c_twl.c

207 lines
5.5 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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