📄 i2c_module.c
字号:
/*===========================================================================
* 2006年。三星仪表SOC芯片开发项目
*
*
* 文件名称:Show_Module.c
* 文件标识:
* 摘 要:
*
*
* 当前版本:Ver 1.0
* 作 者:罗冬生
* 修改内容:
* 修改日期:
* 完成日期:
===============================================================================================*/
#ifndef _I2C_Module_
#define _I2C_Module_
//===============================================================================================
#include "includes.h"
//===============================================================================================
#define I2CRead 0x01
#define I2CWrite 0x00
//===============================================================================================
void DelayMs(unsigned char delay)
{
unsigned char i;
while (delay--)
{
for (i=0;i<255;i++)
{
asm(" NOP ");
asm(" NOP ");
asm(" NOP ");
}
}
}
//------------------------------------------------------------------------------------------------
#define E2promSlv_Adr 0xA8
#define I2C_SDA P0_bit.D4
#define I2C_SCL P0_bit.D6
#define NOP2 {asm(" NOP "); asm(" NOP ");}
#define NOP1 {asm(" NOP ");}
__code const unsigned char Byte_Bit[8] = {
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
}; //add
//------------------------------------------------------------------------------------------------
/***** 启动I2C 工作 ****/
void I2C_Start(void)
{
I2C_SDA = 1; //I2c_Sda_High
NOP2;
NOP1;
I2C_SCL = 1; //I2c_Scl_High
NOP2;
NOP2;
I2C_SDA = 0; //I2c_Sda_Low
NOP2;
NOP1;
I2C_SCL = 0; //I2c_Scl_Low
}
/********* 结束I2C 工作 *********/
void I2C_Stop(void)
{
I2C_SCL = 0; //I2c_Scl_Low
NOP2;
I2C_SDA = 0; //I2c_Sda_Low
NOP2;
NOP1;
I2C_SCL = 1; //I2c_Scl_High
NOP2;
NOP2;
I2C_SDA = 1; //I2c_Sda_High
}
/******* 测试从器件应答 ***************/
//return non-zero if ACK received
unsigned char Test_ACk(void)
{
register unsigned char ack;
I2C_SCL = 0; //I2c_Scl_Low
I2C_SDA = 1; //I2c_Sda_High
NOP2;
ack = ErrorFalse;
I2C_SCL = 1; //I2c_Scl_High
NOP2;
if(I2C_SDA)
ack = ErrorTrue;
I2C_SCL = 0; //I2c_Scl_Low
// I2C_SDA = 0; //I2c_Sda_Low
return ack;
}
/********* 正常应答 *********/
void I2C_ACK(void)
{
I2C_SCL = 0; //I2c_Scl_Low
NOP2;
I2C_SDA = 0; //I2c_Sda_Low
NOP2;
I2C_SCL = 1; //I2c_Scl_High
NOP2;
// I2C_SCL = 0; //I2c_Scl_Low
}
/************* 不应答 *************/
void I2C_NACK(void)
{
I2C_SCL = 0; //I2c_Scl_Low
NOP2;
I2C_SDA = 1; //I2c_Sda_High
NOP2;
I2C_SCL = 1; //I2c_Scl_High
NOP2;
// I2C_SCL = 0; //I2c_Scl_Low
}
/******** 通过I2C总线发送一个字节 *********/
void I2C_SendByte(unsigned char data)
{
register unsigned char k=8;
for(k=0; k<8; k++)
{
I2C_SCL = 0; //I2c_Scl_Low
if(data & Byte_Bit[k]) // output bit of data
I2C_SDA = 1; //I2c_Sda_High
else
I2C_SDA = 0; //I2c_Sda_Low
NOP2;
I2C_SCL = 1; //I2c_Scl_High
NOP1;
}
NOP1;
I2C_SCL = 0; //I2c_Scl_Low
}
/******** 通过I2C总线接收一个字节 *********/
unsigned char I2C_RcvByte(void)
{
register unsigned char data, i;
I2C_SCL = 0; //I2c_Scl_Low
I2C_SDA = 1; //I2c_Sda_High
data = 0;
for(i=0;i<8;i++)
{
I2C_SCL = 1; //I2c_Scl_High
if(I2C_SDA)
data |= Byte_Bit[i];
NOP2;
I2C_SCL = 0; //I2c_Scl_Low
NOP1;
}
return data;
}
/******** 通过I2C总线接收一个字节 *********/
unsigned char I2C_SendHand(unsigned int e2Adr)
{
unsigned char err;
err = ErrorFalse;
I2C_Start();
I2C_SendByte(E2promSlv_Adr | ((unsigned char)(e2Adr>>7) & 0x06));
err = Test_ACk();
I2C_SendByte ((unsigned char)e2Adr);
err |= Test_ACk();
return err;
}
void PutData_Api(unsigned char data,unsigned int DataAdr,unsigned char DaAtt)
{
unsigned char __idata *iCp;
unsigned char *xCp;
DataAdr &= 0x3fff;
if (DaAtt == iRAM)
{
iCp = (unsigned char __idata *)((unsigned char )DataAdr); //iRAM指针
*iCp = data;
}
else if (DaAtt == xRAM)
{
xCp = (unsigned char *)DataAdr; //xRAM指针
*xCp = data;
}
}
unsigned char GetData_Api(unsigned int DataAdr,unsigned char DaAtt)
{
unsigned char __idata *iCp;
unsigned char __xdata *xCp;
const unsigned char __code *oCp;
if (DaAtt == iRAM)
{
iCp = (unsigned char __idata *)((unsigned char )DataAdr); //iRAM指针
return (*iCp);
}
else if (DaAtt == xRAM)
{
xCp = (unsigned char __xdata *)DataAdr; //xRAM指针
return (*xCp);
}
else if (DaAtt == pROM)
{
oCp = (const unsigned char __code *)DataAdr; //pROM指针
return (*oCp);
}
return 0xEE;
}
//------------------------------------------------------------------------------------------------
unsigned char CompareE2prom(unsigned int e2Adr,unsigned char DataAdr,unsigned char Len)
{
register unsigned char k,temp,i,err;
k =DataAdrCheck(DataAdr); //判断数据源是在iRAM、xRAM、pROM中
DataAdr &= 0x3fff;
if (Len==0)
return ErrorFalse;
err = I2C_SendHand(e2Adr);
I2C_Start();
I2C_SendByte((E2promSlv_Adr | 0x01) | ((unsigned char)(e2Adr>>7) & 0x06)); //准备读
err |= Test_ACk();
for (i=0;i<Len;i++)
{
temp = I2C_RcvByte();
if (i==(Len-1))
I2C_NACK();
else
I2C_ACK();
if (GetData_Api(DataAdr+i,k)!=temp)
err = ErrorTrue;
}
I2C_Stop();
return err;
}
unsigned char E2prom_Read(unsigned int e2Adr,unsigned int DataBuf,unsigned char Len)
{
register unsigned char k,temp,i,err;
k =DataAdrCheck(DataBuf); //判断数据源是在iRAM、xRAM、pROM中
DataBuf &= 0x3fff;
if (Len==0)
return ErrorFalse;
err = I2C_SendHand(e2Adr);
I2C_Start();
I2C_SendByte((E2promSlv_Adr | 0x01) | ((unsigned char)(e2Adr>>7) & 0x06)); //准备读
err |= Test_ACk();
for (i=0;i<Len;i++)
{
temp = I2C_RcvByte();
if (i==(Len-1))
I2C_NACK();
else
I2C_ACK();
PutData_Api(temp,DataBuf+i,k);
}
I2C_Stop();
return err;
}
unsigned char E2prom_Write(unsigned int e2Adr,unsigned int DataBuf,unsigned char Len)
{
register unsigned char k,i,err;
k = DataAdrCheck(DataBuf); //判断数据源是在iRAM、xRAM、pROM中
DataBuf &= 0x3fff;
err = ErrorFalse;
while (Len)
{
i = 16-(((unsigned char)e2Adr) & 0x0F); //AT24C08存储器写缓冲区为16Byte,并且地址对齐。
if (Len < i)
i = Len;
err |= I2C_SendHand(e2Adr);
Len -=i; //修改长度
e2Adr +=i; //修改eeprom地址
while (i--)
{
I2C_SendByte ( GetData_Api(DataBuf,k)); //取数据并写e2prom
err |= Test_ACk();
DataBuf++;
}
I2C_Stop();
DelayMs(15); //延时10ms
}
return err;
}
unsigned char SetE2prom(unsigned int e2Adr,unsigned char DataVal,unsigned int Len)
{
register unsigned char i,err;
err = ErrorFalse;
while (Len)
{
i = 16-(((unsigned char)e2Adr) & 0x0F); //AT24C08存储器写缓冲区为16Byte,并且地址对齐。
if (Len < i)
i = Len;
err |= I2C_SendHand(e2Adr);
Len -=i; //修改长度
e2Adr +=i; //修改eeprom地址
while (i--)
{
I2C_SendByte ( DataVal); //设数据到e2prom
err |= Test_ACk();
}
I2C_Stop();
DelayMs(15); //延时10ms
}
return err;
}
unsigned char WriteE2prom_Api(unsigned int e2Adr,unsigned int DataBuf,unsigned char Len)
{
unsigned char loop;
loop=3;
while (loop--)
{
if (E2prom_Write(e2Adr, DataBuf,Len)==ErrorFalse)
{
if (CompareE2prom(e2Adr, DataBuf,Len)==ErrorFalse)
return ErrorFalse;
}
}
return ErrorTrue;
}
//------------------------------------------------------------------------------------------------
// i2c初始化
void I2C_Init(void)
{
CFG_bit.SCPS = 0; //Config the port as I2C (I2C and SPI)
I2CMOD_bit.I2CEN = 1; //Enable I2C port
I2CMOD_bit.I2CRATE = I2C_clk; //I2CRATE=00, the serial frequency is 256KHz
IEIP2_bit.ESI = 0; //I2C中断不使能
}
//------------------------------------------------------------------------------------------------
// 读字节
/*
unsigned char I2C_ReadByte(unsigned char Slv,unsigned char addr)
{
I2CADR = Slv | I2CWrite;
SPI2CTx = addr; //sends the address
while(I2CSTAT_bit.I2CTxIRQ == 0);
I2CMOD = I2CMOD & 0xE0;
I2CADR = (Slv | I2CRead);
while(I2CSTAT_bit.I2CRxIRQ == 0);
return(SPI2CRx);
}
*/
//===============================================================================================
// 写I2C函数:1、器件地址,2、器件内部存储器地址,3、数据在Data的指针,4、数据长度
unsigned char I2C_Write(unsigned char Slv,unsigned int Addr,unsigned int buf,unsigned char Len)
{
unsigned char i,j,LenBak,k;
unsigned char __idata *iCp;
unsigned char *xCp;
const unsigned char __code *oCp;
j=DataAdrCheck(buf);
if ((j!=iRAM) && (j!=xRAM) && (j!=pROM)) //判断数据源是否在iRAM、xRAM、pROM中
{return ErrorTrue;} //数据区设置不对
/*------ 向e2prom写入数据 -----*/
iCp = (unsigned char __idata *)((unsigned char )buf); //iRAM指针
xCp = (unsigned char *)(buf & All_RAM); //xRAM指针
oCp = (const unsigned char __code *)(buf & All_RAM) ; //porm指针
E2_Op_Flg =1; //置E2PROM正在操作标志
LenBak = Len;
while (Len)
{
while(I2CSTAT_bit.I2CRxIRQ )
{ k = SPI2CRx; }
k = Addr;
i = 16-(k & 0x0F); //AT24C08存储器写缓冲区为16Byte,并且地址对齐。
if (Len < i)
{ i = Len; }
k = Addr>>8;
I2CADR = (Slv | I2CWrite |(k<<1)) ; //sends the SlvAdr+ r/w at24c08(10位地址)
SPI2CTx = Addr; //sends the address
Len -=i; //修改长度
Addr +=i; //修改地址
while (i--)
{
while(I2CSTAT_bit.I2CTxIRQ == 0);
switch (j)
{
case iRAM:
SPI2CTx = *iCp; //数据源在iRAM中,iRAM-->e2prom
iCp++;
break;
case xRAM:
SPI2CTx = *xCp; //数据源在iRAM中,xRAM-->e2prom
xCp++;
break;
case pROM:
SPI2CTx = *oCp; //数据源在PROM中,pROM-->e2prom
oCp++;
break;
default :
return ErrorTrue;
}
}
DelayMs(15); //延时10ms
}
/*------ 验证写入数据是否正确 -----*/
Addr -=LenBak; //复位入口数据
iCp = (unsigned char __idata *)((unsigned char )buf);
oCp = (const unsigned char __code *)(buf & All_RAM) ;
xCp = (unsigned char *)(buf & All_RAM);
Len = ErrorFalse; //清E2PROM写出错标志
while (LenBak)
{
while(I2CSTAT_bit.I2CRxIRQ )
{ k = SPI2CRx; }
if (LenBak < 32) //ADE7169连续读最大为32字节。
{ i = LenBak; }
k = Addr>>8;
I2CADR = Slv | I2CWrite | (k<<1); //sends the SlvAdr + w
SPI2CTx = Addr; //sends the address
while(I2CSTAT_bit.I2CTxIRQ == 0);
I2CMOD = (I2CMOD | (i-1)); //设定(读I2C数据)长度
I2CADR = (Slv | I2CRead); //sends the SlvAdr + R
LenBak -=i; //修改长度
Addr +=i; //修改地址
while (i--)
{
while(I2CSTAT_bit.I2CRxIRQ == 0);
k = SPI2CRx;
switch (j)
{
case xRAM:
if (*xCp != k)
{ Len = ErrorTrue;}
xCp++;
break;
case iRAM:
if (*iCp != k)
{ Len =ErrorTrue;}
iCp++;
break;
case pROM:
if (*oCp != k)
{ Len =ErrorTrue;}
oCp++;
break;
default :
{ Len =ErrorTrue;}
}
}
}
E2_Op_Flg = 0; //清E2PROM操作标志
return Len; //返回写E2PROM信息标志
}
//===============================================================================================
// 读I2C函数:1、器件地址,2、器件内部存储器地址,3、数据要存放在Data的指针,4、数据长度
void I2C_Read(unsigned char Slv,unsigned int Addr,unsigned int buf,unsigned char Len)
{
unsigned char k,i,j;
unsigned char __idata *iCp;
unsigned char *xCp;
j=DataAdrCheck(buf);
if ((j!=iRAM) && (j!=xRAM))
{ return ;} //数据区设置不对
iCp = (unsigned char __idata *)((unsigned char)buf); //iRAM中传送数据
xCp = (unsigned char *)(buf & (All_RAM)); //xRAM中传送数据
E2_Op_Flg =1; //置E2PROM正在操作标志
while (Len)
{
while(I2CSTAT_bit.I2CRxIRQ )
{ k = SPI2CRx; }
if (Len < 32) //ADE7169连续读最大为32字节。
{ i = Len; }
k = Addr>>8;
I2CADR = Slv | I2CWrite | (k<<1); //sends the SlvAdr + w
SPI2CTx = Addr; //sends the address
while(I2CSTAT_bit.I2CTxIRQ == 0);
I2CMOD = (I2CMOD | (i-1)); //设定(读I2C数据)长度
I2CADR = (Slv | I2CRead); //sends the SlvAdr + R
Len -=i; //修改长度
Addr +=i; //修改地址
while (i--)
{
while(I2CSTAT_bit.I2CRxIRQ == 0);
if (j==xRAM)
{ //xRAM
*xCp = SPI2CRx;
xCp++;
}
else
{ //iRAM
*iCp = SPI2CRx;
iCp++;
}
}
}
E2_Op_Flg = 0; //清E2PROM操作标志
}
//===============================================================================================
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -