📄 i2c.c
字号:
/*
**********************************************************************************************
* Project: T8Lib
* File: i2c.c
* Contents:
* The i2c module c file
* use GPIO to control SDA and SCL, communicate with T8
* $Date: 10/13/05 Michal T8R01LIB v0.1 initial
* $Date: 11/29/05 Michal T8R01LIB v0.2 test finish both 51 and MCF5249
* $Date: 11/30/05 Michal T8R01LIB v0.3 make lib OK on MCF5249
* $Date: 12/01/05 Michal T8R01LIB v0.4 Add HW_IIC ,HW_SPI macro
* $Date: 12/02/05 Michal T8R01LIB v0.5 Add function below
* static void DoXX(BYTE* out ,BYTE* in,BYTE len,BOOL mode)
* static BOOL DoComunication(BYTE* array, BYTE len,BOOL mode)
*
*
* Moidfy some *Cmd Fuction and Reply() function
* $Date: 12/05/05 Michal T8R02LIB v0.1 Add errcode1 to identify T8 off i2c bus state
* $Date: 12/29/05 Michal T8R02LIB v0.2
Modify InitezT8(BOOL mode ) to BOOL InitezT8Lib(BOOL ComMod,BYTE I2cSlvAdr,BOOL I2cIsHigh,BYTE SpiCLkMod,WORD SpiRate,BYTE *key);
void I2c_Init( ); void I2c_Sel( BYTE SlvAdr, BOOL isHigh) to void I2c_Init(BYTE SlvAdr, BOOL isHigh);
void Spi_Init();BOOL Spi_ClkSel(BYTE mode, WORD rate); To void Spi_Init(BYTE mode, WORD rate);
Delete void SpiClkSelOpr(BYTE mode, WORD rate) ;
void I2c_Sel( BYTE SlvAdr, BOOL isHigh);
void SetXXKey(BYTE* key);
* $Date: 12/29/05 Michal T8R02LIB v0.5 test communiction at 400khz speed is OK
* Copyright (c) 2005 Fameg, Inc. All rights reserved
***********************************************************************************************
*/
#include "ezT8.h"
#include "I2c.h"
#if SW_IIC
static BOOL iHighMode;
BYTE BusSlvAdr=0xEA; //default I2c bus slave address for communiction
static void Stop_I2c();
static void Ack_I2c(BOOL a);
static BYTE I2cRcvByte();
//Pin operation
#if 1
void WritePinSCL(){SCL=1; }
void ClearPinSCL(){SCL=0;}
void setSDAin(){}
void setSDAout(){}
void WritePinSDA(){SDA=1;}
void ClearPinSDA(){SDA=0;}
BOOL ReadPinSDA(){return(SDA);}
void InitReadAck(){SDA=1;}
//Delay
void Delay_0_5us(unsigned char cnt)
{
// unsigned char ct=1;
while(cnt--)
{
// while(ct--);
// asm("nop");
// ct=1;
}
}
#else
#define WritePinSCL() SCL=1
#define ClearPinSCL() SCL=0
#define setSDAin() /##/
#define setSDAout()/##/
#define WritePinSDA() SDA=1
#define ClearPinSDA() SDA=0
#define ReadPinSDA() SDA
#define InitReadAck() SDA
//Delay
BYTE delay;
// #define Delay_0_5us(cnt) //{/*delay =cnt ;while(delay--);*/} /##/
void Delay_0_5us(unsigned char cnt)
{
// unsigned char ct=1;
// while(cnt--)
// {
// while(ct--);
// asm("nop");
// ct=1;
// }
}
#endif
void I2c_Init(BYTE SlvAdr,BOOL isHigh)
{
/* SDA */
iHighMode=isHigh;
BusSlvAdr=SlvAdr;
Stop_I2c();
}
/*void I2c_Sel( BYTE SlvAdr,BOOL isHigh)
{
iHighMode=isHigh;
BusSlvAdr=SlvAdr;
}*/
/*******************************************************************
起动总线函数
函数原型: void Start_I2c();
功能: 启动I2C总线,即发送I2C起始条件.
********************************************************************/
void Start_I2c()
{
setSDAout();
WritePinSDA();
Delay_0_5us(10) ; /*发送结束条件的时钟信号*/
WritePinSCL();
Delay_0_5us(10); /*起始条件建立时间大于4.7us,延时*/
ClearPinSDA(); /*发送起始信号*/
Delay_0_5us(10); /* 起始条件锁定时间大于4μs*/
ClearPinSCL(); /*钳住I2C总线,准备发送或接收数据 */
// Delay_0_5us(2);
}
/*******************************************************************
结束总线函数
函数原型: void Stop_I2c();
功能: 结束I2C总线,即发送I2C结束条件.
********************************************************************/
static void Stop_I2c()
{
setSDAout();
ClearPinSDA(); /*发送结束条件的数据信号*/
Delay_0_5us(10) ; /*发送结束条件的时钟信号*/
WritePinSCL(); /*结束条件建立时间大于4μs*/
Delay_0_5us(10);
WritePinSDA(); /*发送I2C总线结束信号*/
Delay_0_5us(10);
}
/*******************************************************************
字节数据传送函数
函数原型: void I2cSendByte(BYTE c);
功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使ack=0 假)
发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
BOOL I2cSendByte(BYTE c)
{
BYTE BitCnt;
BOOL t,ack;
setSDAout();
for(BitCnt=0x80;BitCnt!=0;BitCnt=BitCnt>>1) /*要传送的数据长度为8位*/
{
if(iHighMode==true)
Delay_0_5us(1);
else
Delay_0_5us(4);
if(c&BitCnt)
{
// t=SDA;
WritePinSDA(); /*判断发送位*/
}
else
ClearPinSDA();
if(iHighMode)
Delay_0_5us(1);
else
Delay_0_5us(4);
// t=SCL;
WritePinSCL();/*置时钟线为高,通知被控器开始接收数据位*/
if(iHighMode) /*保证时钟高电平周期大于4μs*/
{
Delay_0_5us(1);
Delay_0_5us(1);
}
else
{
Delay_0_5us(4);
Delay_0_5us(4);
}
ClearPinSCL();
// InitReadAck(); //11.22 add
} //9 clocks
/* if(iHighMode)
{
Delay_0_5us(1);
}
else
{
Delay_0_5us(4);
}*/
//WritePinSDA
InitReadAck();
if(iHighMode)
{
Delay_0_5us(1);
Delay_0_5us(1);
}
else
{
Delay_0_5us(4);
Delay_0_5us(4);
}
WritePinSCL(); //9 clock
// ReadPinSDA(t) //first read
if(iHighMode)
Delay_0_5us(1);
else
Delay_0_5us(4);
t=ReadPinSDA(); //second read
if(t==1)
ack=0;
else
ack=1; /*判断是否接收到应答信号*/
if(iHighMode)
Delay_0_5us(1);
else
Delay_0_5us(4);
ClearPinSCL(); //钳住总线 9 clock end
if(iHighMode)
Delay_0_5us(1);
else
Delay_0_5us(4);
return ack;
}
/*******************************************************************
字节数据传送函数
函数原型: BYTE I2cRcvByte();
功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数。
********************************************************************/
static BYTE I2cRcvByte()
{
BYTE retc;
BYTE BitCnt;
BOOL t;
retc=0;
WritePinSDA(); /*置数据线为输入方式*/
setSDAin();
for(BitCnt=0;BitCnt<8;BitCnt++)
{
ClearPinSCL(); /*置时钟线为低,准备接收数据位*/
if(iHighMode) /*保证时钟高电平周期大于4μs*/
Delay_0_5us(2);
else
Delay_0_5us(8);
WritePinSCL(); /*置时钟线为高使数据线上数据有效*/
if(iHighMode)
Delay_0_5us(2);
else
Delay_0_5us(8);
retc=retc<<1;
t=ReadPinSDA();
if(t==1)
retc=retc+1; /*读数据位,接收的数据位放入retc中 */
}
ClearPinSCL();
Delay_0_5us(2);
return(retc);
}
/********************************************************************
应答子函数
原型: void Ack_I2c(BOOL a);
功能:主控器进行应答信号,(可以是应答或非应答信号)
********************************************************************/
static void Ack_I2c(BOOL a)
{
setSDAout();
if(a==0)
ClearPinSDA(); /*在此发出应答或非应答信号 */
else
WritePinSDA();
Delay_0_5us(3);
WritePinSCL();
Delay_0_5us(10);
/*时钟低电平周期大于4μs*/
ClearPinSCL(); /*清时钟线,钳住I2C总线以便继续接收*/
Delay_0_5us(2);
}
/*******************************************************************
向有子地址器件发送多字节数据函数
函数原型: BOOL I2c_SendStr(BYTE sla,BYTE *s,WORD no);
功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
如果返回1表示操作成功,否则操作有误。
注意: 使用前必须已结束总线。
********************************************************************/
BYTE I2c_SendStr(BYTE sla,BYTE *s,WORD no)
{
BYTE i;
BOOL ack;
#if COMENINT==1
vDisableIsrs();//add
#endif
Start_I2c(); /*启动总线*/
sla = sla;// << 1;
ack = I2cSendByte(sla); /*发送器件地址*/
if(ack==0)
{
Stop_I2c();
#if COMENINT==1
vEnableIsrs();//add
#endif
return 0xff; //slave ack not exist
}
for(i=0;i<no;i++)
{
ack=I2cSendByte(*s); /*发送数据*/
/* if(ack==0)
{
Stop_I2c();
#if COMENINT==1
vEnableIsrs();//add
#endif
return(i+1); //error byte index
} */
s++;
}
Stop_I2c(); /*结束总线*/
#if COMENINT==1
vEnableIsrs();//add
#endif
return(0);
}
/*******************************************************************
向有子地址器件读取多字节数据函数
函数原型: BOOL I2c_RcvStr(BYTE sla,BYTE *s,WORD Len);
功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
地址sla,子地址suba,读出的内容放入s指向的存储区,读Len个字节。
如果返回1表示操作成功,否则操作有误。
注意: 使用前必须已结束总线。
********************************************************************/
BYTE I2c_RcvStr(BYTE sla,BYTE *s,WORD Len)
{
WORD i;
BOOL ack;
#if COMENINT==1
vDisableIsrs();//add
#endif
Start_I2c(); /*启动总线*/
sla=sla+1;
ack=I2cSendByte(sla);
if(ack==0) //slave ack not exist
{
Stop_I2c();
#if COMENINT==1
vEnableIsrs();//add
#endif
return(0xff);
}
for(i=0;i<Len-1;i++)
{
*s=I2cRcvByte(); /*读取数据*/
Ack_I2c(0); /*发送就答位*/
s++;
}
*s=I2cRcvByte();
Ack_I2c(1); /*发送非应位*/
Stop_I2c(); /*结束总线*/
#if COMENINT==1
vEnableIsrs();//add
#endif
return(0);
}
#elif (IIC_USED==0 )//!SW_IIC both SW_IIC and HW_IIC are not needed, define dummy functions
BYTE BusSlvAdr=0x62; //default I2c bus slave address for communiction
void I2c_Init( )
{
}
void I2c_Sel( BYTE SlvAdr,BOOL isHigh)
{
}
BYTE I2c_SendStr(BYTE sla,BYTE *s,WORD no)
{
}
BYTE I2c_RcvStr(BYTE sla,BYTE *s,WORD no)
{
}
#endif //SW_IIC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -