//mem_24LC_lib_i2c.c
#include "mem_24LC_lib_i2c.h"
int mem24LC_Clock = 200000000; //Hz: システムクロック
char read_data[20]; //I2Cデータ受信用
void mem24LC_delay_us(unsigned int usec) //1μsec遅延関数
{
volatile int count;
count = (int)(mem24LC_Clock/20000000)*usec;
do //実測 at 200MH (mem24LC_Clock=200000000)
{ //delay_us(1000):1000.4μsec delay_us(100):100.6μsec delay_us(10):10.5μsec delay_us(1):1.5μsec
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
count--;
}while(count != 0);
}
void mem24LC_delay_ms(unsigned int msec) //1msec遅延関数
{
unsigned int i;
for(i=0; i<msec; i++)
delay_us(1000);
}
void mem24LC_Reset_i2C(void)
{
I2CXCONbits.ON = 0; //IC2モジュール:OFF
I2CXCONbits.ON = 1; //IC2モジュール:ON
}
void mem24LC_Idle_i2c(void) //アイドル待ち
{
while(I2CXCONbits.SEN || I2CXCONbits.PEN || I2CXCONbits.RCEN
|| I2CXCONbits.ACKEN || I2CXSTATbits.TRSTAT);
}
void mem24LC_start_i2c(void) //I2Cスタート
{
mem24LC_Idle_i2c();
I2CXCONbits.SEN = 1; // スタート出力//
while(I2CXCONbits.SEN); // スタート終了待ち
}
void mem24LC_stop_i2c(void) //I2Cストップ
{
I2CXCONbits.PEN = 1; // ストップ出力
while(I2CXCONbits.PEN); // ストップ終了待ち
}
void mem24LC_write_byte_i2c(unsigned char byte) //1バイト書込み
{
I2CXTRN = byte; // データセット送信開始
while(I2CXSTATbits.TBF); // 送信終了待ち
while(I2CXSTATbits.ACKSTAT); // ACK返信待ち
mem24LC_Idle_i2c(); // アイドル待ち
}
void mem24LC_restart_i2c(void)
{
I2CXCONbits.RSEN = 1; //リスタート条件出力
while(I2CXCONbits.RSEN); //出力完了待ち
}
unsigned char mem24LC_ReadChr(unsigned char adr_chips, unsigned int adr_chip_inner)
{
unsigned char data; //EEPROM読み込みデータ
char adr_write_cmd = ((0xa0 | (adr_chips << 1)) & (0b11111110)); //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0
char adr_read_cmd = ((0xa0 | (adr_chips << 1)) | (0b00000001)); //(アドレス + 読み込みコマンド)作成 R/Wビット: 読込み=1
mem24LC_Reset_i2C(); //erratta 対策
mem24LC_start_i2c(); //スタート条件送信
mem24LC_Idle_i2c(); //アイドル待
mem24LC_write_byte_i2c(adr_write_cmd); // (I2Cバスアドレス + 書き込みコマンド)送信
mem24LC_Idle_i2c();
mem24LC_write_byte_i2c(adr_chip_inner >> 8); //EEPROM内部アドレスの上位送信
mem24LC_Idle_i2c();
mem24LC_write_byte_i2c(adr_chip_inner & 0x00FF); //EEPROM内部アドレスの下位送信
mem24LC_Idle_i2c();
mem24LC_restart_i2c(); //再スタート条件送信
mem24LC_Idle_i2c();
mem24LC_write_byte_i2c(adr_read_cmd); //(I2Cバスアドレス + 読み込みコマンド)送信
mem24LC_Idle_i2c();
I2CXCONbits.RCEN = 1; //受信許可
while(!I2CXSTATbits.RBF); //受信バッファI2CXRCVが フルになるまで待つ //Receive complete, I2CxRCV is full
data = I2CXRCV; //受信バッファI2CXRCV読み込み
mem24LC_stop_i2c(); //ストップ条件送信
mem24LC_Idle_i2c();
mem24LC_Reset_i2C(); //erratta 対策
return data;
}
void mem24LC_ReadStr(unsigned char adr_chips, unsigned int adr_chip_inner) //文字列 読み込み
{
int ix = 0;
char adr_write_cmd = ((0xa0 | (adr_chips << 1)) & (0b11111110)); //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0
char adr_read_cmd = ((0xa0 | (adr_chips << 1)) | (0b00000001)); //(アドレス + 読み込みコマンド)作成 R/Wビット: 読込み=1
mem24LC_Reset_i2C(); //erratta 対策
mem24LC_start_i2c(); //スタート条件送信
mem24LC_Idle_i2c(); //アイドル待
mem24LC_write_byte_i2c(adr_write_cmd); // (I2Cバスアドレス + 書き込みコマンド)送信
mem24LC_Idle_i2c();
mem24LC_write_byte_i2c(adr_chip_inner >> 8); //EEPROM内部アドレスの上位送信
mem24LC_Idle_i2c();
mem24LC_write_byte_i2c(adr_chip_inner & 0x00FF); //EEPROM内部アドレスの下位送信
mem24LC_Idle_i2c();
mem24LC_restart_i2c(); //再スタート条件送信
mem24LC_Idle_i2c();
mem24LC_write_byte_i2c(adr_read_cmd); //(I2Cバスアドレス + 読み込みコマンド)送信
mem24LC_Idle_i2c();
while(1) //文字列データの取得
{
I2CXCONbits.RCEN = 1; //受信許可
while(!I2CXSTATbits.RBF); //受信バッファI2CXRCVが フルになるまで待つ //Receive complete, I2CxRCV is full
read_data[ix] = I2CXRCV; //受信バッファI2CXRCV読み込み
if(read_data[ix] == '\r' || ix >= 16)break; //データ終端検出
I2CXCONbits.ACKDT = 0; //更にデータ送信をスレーブに要求するのでACK=0をセットする //AckIC1();
I2CXCONbits.ACKEN = 1; //ACKDTにセットされている ACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
while(I2CXCONbits.ACKEN); //送信完了を待つ //ACKENは送信完了でハードによりクリアされる
ix++;
}
read_data[ix] = '\0'; //配列を文字列化
I2CXCONbits.ACKDT = 1; //スレーブからの文字送信要求は終了なのでNACK=1をセット // NotAckI2C1();
//vs 更にデータ送信をスレーブに要求する場合は、ACK=0をセットする //AckI2C1();
I2CXCONbits.ACKEN = 1; //ACKDTにセットされている NACKかACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
while(I2CXCONbits.ACKEN); //送信完了を待つ //ACKENは送信完了でハードによりクリアされる
mem24LC_stop_i2c(); //ストップ条件送信
mem24LC_Idle_i2c();
mem24LC_Reset_i2C(); //erratta 対策
}
void mem24LC_WriteChr(unsigned char adr_chips, unsigned int adr_chip_inner, unsigned char data)
{
char adr_write_cmd = ((0xa0 | (adr_chips << 1)) & (0b11111110)); //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0
mem24LC_Reset_i2C(); //erratta 対策
mem24LC_start_i2c(); //スタート条件 送信
mem24LC_Idle_i2c(); //アイドル待ち
mem24LC_write_byte_i2c(adr_write_cmd); // (I2Cバスアドレス + 書き込みコマンド)送信
mem24LC_Idle_i2c();
mem24LC_write_byte_i2c(adr_chip_inner >> 8); //EEPROM内部アドレスの上位送信
mem24LC_Idle_i2c();
mem24LC_write_byte_i2c(adr_chip_inner & 0x00FF); //EEPROM内部アドレスの下位送信
mem24LC_Idle_i2c();
mem24LC_write_byte_i2c(data); //データ送信
mem24LC_Idle_i2c();
mem24LC_stop_i2c(); //ストップ条件 送信
mem24LC_Reset_i2C(); //errata 対策
mem24LC_Idle_i2c();
mem24LC_delay_ms(5); //EEPROM書き込み待ち
mem24LC_Reset_i2C(); //erratta 対策
}
void mem24LC_WriteStr(unsigned char adr_chips, unsigned int adr_chip_inner, char* str) //文字列書込み
{
char adr_write_cmd = ((0xa0 | (adr_chips << 1)) & (0b11111110)); //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0
mem24LC_Reset_i2C(); //erratta 対策
mem24LC_start_i2c(); //スタート条件 送信
mem24LC_Idle_i2c(); //アイドル待ち
mem24LC_write_byte_i2c(adr_write_cmd); // (I2Cバスアドレス + 書き込みコマンド)送信
mem24LC_Idle_i2c();
mem24LC_write_byte_i2c(adr_chip_inner >> 8); //EEPROM内部アドレスの上位送信
mem24LC_Idle_i2c();
mem24LC_write_byte_i2c(adr_chip_inner & 0x00FF); //EEPROM内部アドレスの下位送信
mem24LC_Idle_i2c();
while(*str)
{
mem24LC_write_byte_i2c(*str); //データ送信
mem24LC_Idle_i2c();
str++;
}
mem24LC_stop_i2c(); //ストップ条件 送信
mem24LC_Reset_i2C(); //errata 対策
mem24LC_Idle_i2c();
mem24LC_delay_ms(5); //EEPROM書き込み待ち
mem24LC_Reset_i2C(); //erratta 対策
}