📄 i2c.c
字号:
typedef struct
{
unsigned char *RAM;
unsigned char PG;
unsigned char BakPG;
unsigned char Addr;
unsigned char Len;
int *Chk;
}E2PINFO;
const E2PINFO E2PInfo[] =
{
(unsigned char*)&SM.Cfg, E2PG0, E2PG1, E2CfgHead, sizeof(CFGGRP), &SM.CfgChk,
SM.CMon.Fee[0], E2PG0, E2PG1, E2CMonHead, sizeof(CMONBLK),&SM.CMonChk,
SM.LMon.Fee[0], E2PG2, E2PG3, E2L1MonHead, sizeof(LMONBLK),&SM.LMonChk,
};
void Delay5ms(void)
{
unsigned int i;
for(i=0;i<800;i++);
_NOP();
}
void I2CStart(void)
{
#ifdef I2C_IO_COM
#ifndef IIC_SIMPLE
I2C_CON_DIR |= (I2C_SDA_BIT+I2C_SCL_BIT+I2C_WP_BIT);
I2C_CON_OUT |= (I2C_SDA_BIT+I2C_SCL_BIT);
#endif
I2C_CON_OUT &= ~I2C_WP_BIT;
#else
I2C_SCL_OUT |= I2C_SCL_BIT;
I2C_SCL_DIR |= I2C_SCL_BIT;
I2C_SDA_OUT |= I2C_SDA_BIT;
I2C_SDA_DIR |= I2C_SDA_BIT;
I2C_WP_OUT &= ~I2C_WP_BIT;
I2C_WP_DIR &= ~I2C_WP_BIT;
#endif
_NOP();
_NOP();
I2C_SDA_OUT &= ~I2C_SDA_BIT;
_NOP();
_NOP();
I2C_SCL_OUT &= ~I2C_SCL_BIT;
}
void I2CStop(void)
{
I2C_SDA_DIR |= I2C_SDA_BIT;
I2C_SDA_OUT &= ~I2C_SDA_BIT;
_NOP();
_NOP();
I2C_SCL_OUT |= I2C_SCL_BIT;
_NOP();
_NOP();
I2C_SDA_OUT |= I2C_SDA_BIT;
}
unsigned char ReadI2CByte(void)
{
unsigned char i;
unsigned char data=0;
I2C_SDA_DIR &= ~I2C_SDA_BIT;
for(i=1;i<=8;i++)
{
I2C_SCL_OUT |= I2C_SCL_BIT;
_NOP(); //
data <<=1;
if ((I2C_SDA_IN&I2C_SDA_BIT)==I2C_SDA_BIT) data |=0x01;
I2C_SCL_OUT &= ~I2C_SCL_BIT;
_NOP();
_NOP(); //
}
I2C_SDA_DIR |= I2C_SDA_BIT;
I2C_SDA_OUT |= I2C_SDA_BIT;
_NOP();
_NOP();
I2C_SCL_OUT |= I2C_SCL_BIT;
_NOP();
_NOP();
//I2C_SDA_OUT &= ~I2C_SDA_BIT; //去掉此处 2005.12.26
//_NOP();
//_NOP();
I2C_SCL_OUT &= ~I2C_SCL_BIT;
return data;
}
unsigned int ReadI2CWord(void)
{
unsigned char i;
unsigned int j=0;
I2C_SDA_DIR &= ~I2C_SDA_BIT;
for(i=1;i<=16;i++)
{
I2C_SCL_OUT |= I2C_SCL_BIT;
j <<=1;
if (((I2C_SDA_IN&I2C_SDA_BIT)==I2C_SDA_BIT)) j |=0x01;
I2C_SCL_OUT &= ~I2C_SCL_BIT;
_NOP();
}
I2C_SDA_DIR |= I2C_SDA_BIT;
I2C_SDA_OUT |= I2C_SDA_BIT;
_NOP();
_NOP();
I2C_SCL_OUT |= I2C_SCL_BIT;
_NOP();
_NOP();
I2C_SDA_OUT &= ~I2C_SDA_BIT;
_NOP();
_NOP();
I2C_SCL_OUT &= ~I2C_SCL_BIT;
return j;
}
signed char SendI2CByte( unsigned char nByte ) //read or write command (0xAF read; OxAE write)
{ //start + 1010xxx (read or write start)
unsigned char i;
signed char j;
I2C_SDA_DIR |= I2C_SDA_BIT;
for(i=1;i<=8;i++)
{
if ((nByte&0x80)==0x80) I2C_SDA_OUT |= I2C_SDA_BIT;
else I2C_SDA_OUT &= ~I2C_SDA_BIT;
nByte <<=1;
_NOP();
_NOP();
I2C_SCL_OUT |= I2C_SCL_BIT;
_NOP();
_NOP();
I2C_SCL_OUT &= ~I2C_SCL_BIT;
_NOP();
_NOP();
}
I2C_SDA_DIR &= ~I2C_SDA_BIT;
_NOP(); //2005.12.24
I2C_SCL_OUT |= I2C_SCL_BIT;
_NOP();
_NOP();
_NOP();
_NOP();
if(I2C_SDA_IN&I2C_SDA_BIT) j=-1;
else j=0;
_NOP();
I2C_SCL_OUT &= ~I2C_SCL_BIT;
return j;
}
void SetI2CPort(void)
{
#ifdef I2C_IO_COM
I2C_CON_DIR |= (I2C_SDA_BIT+I2C_SCL_BIT+I2C_WP_BIT);
I2C_CON_OUT |= (I2C_SDA_BIT+I2C_SCL_BIT+I2C_WP_BIT);
#else
I2C_SCL_OUT |= I2C_SCL_BIT;
I2C_SCL_DIR |= I2C_SCL_BIT;
I2C_SDA_OUT |= I2C_SDA_BIT;
I2C_SDA_DIR |= I2C_SDA_BIT;
I2C_WP_OUT |= I2C_WP_BIT;
I2C_WP_DIR |= I2C_WP_BIT;
#endif
}
//----------------------------------------
// [*Ram_Addr]--
// [I2C_Addr1]-- I2C的器件地址
// [I2C_Addr2]-- I2C的内部读写地址
// [nLen]-- 读写地址的字节数
void GetI2CData( unsigned char *Ram_Addr, unsigned char I2C_Addr1, unsigned int I2C_Addr2, unsigned char nLen )
{
I2CStart();
SendI2CByte( I2C_Addr1 );
// SendI2CByte( I2C_Addr2>>8 ); // address 0 >=24C64
SendI2CByte( I2C_Addr2&0xFF ); // address 1
for( ; nLen>0; nLen-- )
{
I2CStart(); // Current Address Read
SendI2CByte( I2C_Addr1|1 );
(*Ram_Addr) = ReadI2CByte();
Ram_Addr++;
}
I2CStop();
SetI2CPort();
}
void GetI2CWord( unsigned int *Ram_Addr, unsigned char I2C_Addr1, unsigned int I2C_Addr2 )
{
I2CStart();
SendI2CByte( I2C_Addr1 );
SendI2CByte( I2C_Addr2&0xFF ); // address 1
I2CStart(); // Current Address Read
SendI2CByte( I2C_Addr1|1 );
(*Ram_Addr) = ReadI2CWord();
I2CStop();
SetI2CPort();
}
void SetI2CData( unsigned char *Ram_Addr, unsigned char I2C_Addr1, unsigned int I2C_Addr2, unsigned char nLen )
{
I2CStart();
SendI2CByte( I2C_Addr1 ); // control byte
// SendI2CByte( I2C_Addr2>>8 ); // address 0 >=24C64
SendI2CByte( I2C_Addr2&0xFF ); // address 1
for( ; nLen>0; nLen-- )
{
SendI2CByte( *Ram_Addr );
Ram_Addr++;
}
I2CStop();
Delay5ms();
SetI2CPort();
}
#define Wb_Num 16 // 每页一次写的字节数
void E2P_Wb( unsigned char *Ram_Addr, unsigned char I2C_Addr1, unsigned int I2C_Addr2, unsigned char nLen )
{
unsigned char iii,jjj;
iii=I2C_Addr2&0xff;
do
{
if( nLen > Wb_Num-(iii&0x0f) ) jjj = Wb_Num-(iii&0x0f);
else jjj = nLen;
SetI2CData( Ram_Addr, I2C_Addr1, iii, jjj );
iii += jjj;
Ram_Addr += jjj;
nLen -= jjj;
}while(nLen>0);
}
// Patameter Initialation
void ParInit( unsigned char SW )
{
switch(SW)
{
case 0:
#ifdef DISPLAY_CHANGED
SM.Cfg.LcdCtl.DispTime = DISPLAY_TIME&0x0F;
#else
SM.Cfg.LcdCtl.DispTime[0] = DISPLAY_TIME;
#endif
SM.Cfg.LcdCtl.Reg.w[0]=0xFFFE;
SM.TmpOption=1;
SM.Cfg.MetConst[1]=0x16;
SM.Cfg.BillDay[1]=0x01;
//SM.Cfg.Pswd[1][0]=0x01;
SM.Cfg.Pswd[1][0]=0x00;
SM.Cfg.MetStatus[0]=BATTEST(SM.Cfg.MetStatus[0]);
break;
case 1:
SM.CMon.Addr_0_1[0]=E2Start_0_1;
DM.Reg.b[0]=0;
SetI2CData( DM.Reg.b, E2PG2, ECPtr, 1 );
break;
default:
break;
}
}
//***************************************************************
// GRP = 0 : 恢复电表配置
// GRP = 1 : 恢复电能量(当前月)
// GRP = 2 : 恢复电能量(上1月)
// GRP = 3 : 恢复电能量(上2月)
// GRP = 4 : 恢复电能量(上3月)
// GRP = 5 : 恢复电能量(上4月)
//***************************************************************
unsigned char E2ToRAM( unsigned char GROUP, unsigned char Addr )
{
GetI2CData(E2PInfo[GROUP].RAM, E2PInfo[GROUP].PG, Addr, E2PInfo[GROUP].Len+2);
if((*E2PInfo[GROUP].Chk)==ChkSum(E2PInfo[GROUP].RAM, E2PInfo[GROUP].Len)) return 1;
GetI2CData(E2PInfo[GROUP].RAM, E2PInfo[GROUP].BakPG, Addr, E2PInfo[GROUP].Len+2);
if((*E2PInfo[GROUP].Chk)==ChkSum(E2PInfo[GROUP].RAM, E2PInfo[GROUP].Len)) return 2;
return 0;
}
void DataClr( unsigned char GROUP )
{
//MemFill(E2PInfo[GROUP].RAM, E2PInfo[GROUP].Len, 0x00);
MemFill(E2PInfo[GROUP].RAM, E2PInfo[GROUP].Len, 0x00);
ParInit(GROUP);
*E2PInfo[GROUP].Chk=ChkSum(E2PInfo[GROUP].RAM, E2PInfo[GROUP].Len);
}
//***************************************************************
// GRP = 0 : 恢复电表配置
// GRP = 1 : 恢复电能量(当前月)
// GRP = 2 : 恢复电能量(上1月)
// GRP = 3 : 恢复电能量(上2月)
// GRP = 4 : 恢复电能量(上3月)
// GRP = 5 : 恢复电能量(上4月)
//***************************************************************
void SaveGRP( unsigned char GROUP)
{
unsigned char TMP1;
TMP1=GROUP;
E2P_Wb(E2PInfo[TMP1].RAM,E2PInfo[TMP1].PG,E2PInfo[TMP1].Addr,E2PInfo[TMP1].Len+2 );
}
void GetGRP( unsigned char GROUP)
{
unsigned char TMP1;
TMP1=GROUP;
GetI2CData(E2PInfo[TMP1].RAM,E2PInfo[TMP1].PG,E2PInfo[TMP1].Addr,E2PInfo[TMP1].Len+2 );
}
//***************************************************************
// GRP = 0 : 恢复电表配置
// GRP = 1 : 恢复电能量(当前月)
// GRP = 2 : 恢复电能量(上1月)
// GRP = 3 : 恢复电能量(上2月)
// GRP = 4 : 恢复电能量(上3月)
// GRP = 5 : 恢复电能量(上4月)
//***************************************************************
void SaveGRPBAK( unsigned char GROUP)
{
unsigned char TMP1;
TMP1=GROUP;
E2P_Wb(E2PInfo[TMP1].RAM,E2PInfo[TMP1].BakPG,E2PInfo[TMP1].Addr,E2PInfo[TMP1].Len+2 );
}
void GetGRPBAK( unsigned char GROUP)
{
unsigned char TMP1;
TMP1=GROUP;
GetI2CData(E2PInfo[TMP1].RAM,E2PInfo[TMP1].BakPG,E2PInfo[TMP1].Addr,E2PInfo[TMP1].Len+2 );
}
//***************************************************************
// GRP = 0 : 恢复电表配置
// GRP = 1 : 恢复电能量(当前月)
// GRP = 2 : 恢复电能量(上1月)
// GRP = 3 : 恢复电能量(上2月)
// GRP = 4 : 恢复电能量(上3月)
// GRP = 5 : 恢复电能量(上4月)
//***************************************************************
void ProcReq( unsigned char Bit_GRP)
{
SM.E2Flgs |= Bit_GRP;
DM.Tsk.Req.I2C=1;
}
void ProcE2P(void)
{
unsigned int TMP;
unsigned char i;
SM.E2Flgs |= E2BUSY;
for(TMP=0x0100,i=0;TMP<=0x0200;TMP<<=1,i++)
{
if(DM.Tsk.Req.Sec==1) break;
if(SM.E2Flgs&TMP)
{
SaveGRP(i);
SaveGRPBAK(i);
SM.E2Flgs &=~TMP;
}
}
for(TMP=0x0001,i=0;TMP<=0x0002;TMP<<=1,i++)
{
if(DM.Tsk.Req.Sec==1) break;
if(SM.E2Flgs&TMP)
{
if(E2ToRAM(i,E2PInfo[i].Addr)==0)
{
DataClr(i);
}
SM.E2Flgs &=~TMP;
}
}
// 保存 5字节的 0.1 kWh [总、尖、峰、平、谷]
if( SM.E2Flgs&S_E2KWH_0_1 && DM.Tsk.Req.Sec!=1 )
{
SM.CMon.Data_0_1[0]=SM.CMon.Fee[0][0];
SM.CMon.Data_0_1[1]=SM.CMon.Fee[1][0];
SM.CMon.Data_0_1[2]=SM.CMon.Fee[2][0];
SM.CMon.Data_0_1[3]=SM.CMon.Fee[3][0];
SM.CMon.Data_0_1[4]=SM.CMon.Fee[4][0];
SetI2CData(SM.CMon.Data_0_1,E2PG0,SM.CMon.Addr_0_1[0],5 );
SM.E2Flgs &=~S_E2KWH_0_1;
}
// 读出 5字节的 0.1 kWh [总、尖、峰、平、谷]
if( SM.E2Flgs&R_E2KWH_0_1 && DM.Tsk.Req.Sec!=1 )
{
GetI2CData(SM.CMon.Data_0_1,E2PG0,SM.CMon.Addr_0_1[0],5 );
SM.CMon.Fee[0][0]=SM.CMon.Data_0_1[0];
SM.CMon.Fee[1][0]=SM.CMon.Data_0_1[1];
SM.CMon.Fee[2][0]=SM.CMon.Data_0_1[2];
SM.CMon.Fee[3][0]=SM.CMon.Data_0_1[3];
SM.CMon.Fee[4][0]=SM.CMon.Data_0_1[4];
SM.CMonChk=ChkSum(SM.CMon.Fee[0], sizeof(CMONBLK));
SM.E2Flgs &=~R_E2KWH_0_1;
}
// 存当前电量到上月
// 通用的保存10个月的电量;
// 1. 读出当前的电量指针;
// 2. 电量指针加1,并保存;
// 3. 把上月的电量保存到指针所指的位置。
if( SM.E2Flgs&S_E2LMONGRP && DM.Tsk.Req.Sec!=1 )
{
GetI2CData( DM.Reg.b,E2PG2,ECPtr,1 );
if(++DM.Reg.b[0]>9) DM.Reg.b[0]=0;
SetI2CData( DM.Reg.b,E2PG2,ECPtr,1 );
MemCopy(SM.LMon.Fee[0], SM.CMon.Fee[0], sizeof(LMONBLK) );
SM.LMonChk=ChkSum(SM.LMon.Fee[0],sizeof(LMONBLK));
E2P_Wb( SM.LMon.Fee[0],E2PG2,LMonAddr[DM.Reg.b[0]],sizeof(LMONBLK)+2 );
E2P_Wb( SM.LMon.Fee[0],E2PG3,LMonAddr[DM.Reg.b[0]],sizeof(LMONBLK)+2 );
SM.E2Flgs &=~S_E2LMONGRP;
}
// 读上n月的电量
if( (SM.E2Flgs&R_E2LMONGRP)!=0 && DM.Tsk.Req.Sec!=1 )
{
i=((SM.E2Flgs&R_E2LMONGRP)>>4)-1;
GetI2CData( DM.Reg.b,E2PG2,ECPtr,1 );
if(E2ToRAM(2,LMonAddr[DM.Reg.b[0]>=i?DM.Reg.b[0]-i:DM.Reg.b[0]+10-i])==0) DataClr(2);
SM.E2Flgs &=~R_E2LMONGRP;
}
SM.E2Flgs &=~E2BUSY;
if(SM.E2Flgs==0)
DM.Tsk.Req.I2C=0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -