⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 MSP430F413单相电表DEMO(编译器IAR 3.42A)
💻 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 + -