📄 i2c.c
字号:
//IO口模拟IIC实现代码
void Sda_Output(void)
{
PFR61_I2CE0 = 0;
PFR6_A20E = 0;
DDR6_D64 = 1;
PCR6_P64 = 1;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void Sda_Input(void)
{
PFR61_I2CE0 = 0;
PFR6_A20E = 0;
DDR6_D64 = 0;
PCR6_P64 = 1;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void Scl_Output(void)
{
PFR61_I2CE0 = 0;
PFR6_A21E = 0;
DDR6_D65 = 1;
PCR6_P65 = 1;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void Scl_Input(void)
{
PFR61_I2CE0 = 0;
PFR6_A21E = 0;
DDR6_D65 = 0;
PCR6_P65 = 1;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void Sda_High(void)
{
PDR6_P64 = 1;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void Sda_Low(void)
{
PDR6_P64 = 0;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void Scl_High(void)
{
PDR6_P65 = 1;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void Scl_Low(void)
{
PDR6_P65 = 0;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
int Get_Sda_Val(void)
{
if(PDR6_P64)
return(1);
else
return(0);
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void _Nop(void) //~= 1us
{
volatile int i;
for(i=0;i<40;i++);
}
void I2c_Wait(void)
{
_Nop(); /*起始条件建立时间大于4.7us,延时*/
_Nop();
_Nop();
_Nop();
_Nop();
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
/*******************************************************************
起动总线函数
函数原型: void Start_I2c();
功能: 启动I2C总线,即发送I2C起始条件.
********************************************************************/
void Start_I2c()
{
Sda_High(); /*发送起始条件的数据信号*/
I2c_Wait();
Scl_High();
I2c_Wait();
I2c_Wait();
Sda_Low(); /*发送起始信号*/
I2c_Wait();
I2c_Wait();
Scl_Low(); /*钳住I2C总线,准备发送或接收数据 */
I2c_Wait();
I2c_Wait();
}
/*******************************************************************
结束总线函数
函数原型: void Stop_I2c();
功能: 结束I2C总线,即发送I2C结束条件.
********************************************************************/
void Stop_I2c()
{
Sda_Low(); /*发送结束条件的数据信号*/
I2c_Wait();
I2c_Wait();
Scl_High(); /*结束条件建立时间大于4μs*/
I2c_Wait();
I2c_Wait();
Sda_High(); /*发送I2C总线结束信号*/
I2c_Wait();
I2c_Wait();
}
/*******************************************************************
字节数据传送函数
函数原型: void SendByte(unsigned char c);
功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使ack=0 假)
发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
void SendByte(unsigned char c)
{
unsigned char BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/
{
if((c<<BitCnt)&0x80)Sda_High(); /*判断发送位*/
else Sda_Low();
I2c_Wait();
I2c_Wait();
Scl_High(); /*置时钟线为高,通知被控器开始接收数据位*/
I2c_Wait();
I2c_Wait();
Scl_Low();
}
I2c_Wait();
//lxh 5-16 I2c_Wait();
Sda_High(); /*8位发送完后释放数据线,准备接收应答位*/
I2c_Wait();
//lxh 5-16 I2c_Wait();
Sda_Input(); //add by lxh for test
I2c_Wait();
Scl_High();
I2c_Wait();
I2c_Wait();
if(Get_Sda_Val()) ack=0;
else ack=1; /*判断是否接收到应答信号*/
Scl_Low();
I2c_Wait();
I2c_Wait();
Sda_Output();
}
/*******************************************************************
字节数据传送函数
函数原型: unsigned char RcvByte();
功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数。
********************************************************************/
unsigned char RcvByte()
{
unsigned char retc;
unsigned char BitCnt;
retc=0;
Sda_High(); /*置数据线为输入方式*/
I2c_Wait();
Sda_Input();
I2c_Wait();
for(BitCnt=0;BitCnt<8;BitCnt++)
{
Scl_Low(); /*置时钟线为低,准备接收数据位*/
I2c_Wait();
I2c_Wait();
Scl_High(); /*置时钟线为高使数据线上数据有效*/
I2c_Wait();
I2c_Wait();
retc=retc<<1;
if(Get_Sda_Val()) retc=retc+1; /*读数据位,接收的数据位放入retc中 */
I2c_Wait();
}
Scl_Low();
I2c_Wait();
Sda_Output();
I2c_Wait();
I2c_Wait();
return(retc);
}
/********************************************************************
应答子函数
原型: void Ack_I2c(unsigned char ack);
功能:主控器进行应答信号,(可以是应答或非应答信号)
********************************************************************/
void Ack_I2c(unsigned char ack)
{
if(ack == 0) Sda_Low(); /*在此发出应答或非应答信号 */
else Sda_High();
I2c_Wait();
I2c_Wait();
Scl_High();
I2c_Wait();
I2c_Wait();
Scl_Low(); /*清时钟线,钳住I2C总线以便继续接收*/
I2c_Wait();
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//GPB10 --dat GPB9 ---clk
void I2c_Init()
{
Sda_Output();
Scl_Output(); //
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
unsigned char dr_vIIC_ReadByte(unsigned int slvAddr,unsigned int addr,unsigned char *data)
{
Start_I2c(); /*启动总线*/
SendByte(slvAddr); /*发送器件地址*/
if(ack==0)
{
Stop_I2c(); /*结束总线*/
// RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----1\n")));
return(0);
}
I2c_Wait();
I2c_Wait();
SendByte(addr);
if(ack==0)
{
Stop_I2c(); /*结束总线*/
// RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----2\n")));
return(0);
}
I2c_Wait();
Start_I2c();
I2c_Wait();
I2c_Wait();
SendByte(slvAddr+1);
if(ack==0)
{
Stop_I2c(); /*结束总线*/
// RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
return(0);
}
I2c_Wait();
I2c_Wait();
*data=RcvByte(); /*读取数据*/
Ack_I2c(1); /*发送非就答位*/
I2c_Wait();
I2c_Wait();
Stop_I2c(); /*结束总线*/
return(1);
}
//------------------------------------------------------------------------
unsigned char dr_ucIIC_ReadSingleByte(unsigned int slvAddr,unsigned char *data)
{
Start_I2c(); /*启动总线*/
SendByte(slvAddr+1);
if(ack==0)
{
Stop_I2c(); /*结束总线*/
// RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
return(0);
}
I2c_Wait();
I2c_Wait();
*data=RcvByte(); /*读取数据*/
Ack_I2c(1); /*发送非就答位*/
I2c_Wait();
I2c_Wait();
Stop_I2c(); /*结束总线*/
return(1);
}
//------------------------------------------------------------------------
unsigned char dr_ucIIC_ReadDoubleByte(unsigned int slvAddr,unsigned char *data)
{
Start_I2c(); /*启动总线*/
SendByte(slvAddr+1);
if(ack==0)
{
Stop_I2c(); /*结束总线*/
// RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
return(0);
}
I2c_Wait();
I2c_Wait();
*data=RcvByte(); /*读取数据*/
Ack_I2c(0); /*发送非就答位*/
data++;
I2c_Wait();
I2c_Wait();
*data=RcvByte(); /*读取数据*/
Ack_I2c(1); /*发送非就答位*/
I2c_Wait();
I2c_Wait();
Stop_I2c(); /*结束总线*/
return(1);
}
//------------------------------------------------------------------------
unsigned char dr_vIIC_WriteByte(unsigned char slvAddr,unsigned int addr,unsigned char data)
{
Start_I2c(); /*启动总线*/
SendByte(slvAddr); /*发送器件地址*/
if(ack==0)
{
Stop_I2c(); /*结束总线*/
// RETAILMSG(1,(TEXT("GpioI2c: Wd24C080----1\n")));
return(0);
}
I2c_Wait();
I2c_Wait();
SendByte(addr); /*发送数据*/
if(ack==0)
{
Stop_I2c(); /*结束总线*/
// RETAILMSG(1,(TEXT("GpioI2c: Wd24C080----2\n")));
return(0);
}
I2c_Wait();
I2c_Wait();
SendByte(data); /*发送数据*/
if(ack==0)
{
Stop_I2c(); /*结束总线*/
// RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
return(0);
}
I2c_Wait();
I2c_Wait();
Stop_I2c(); /*结束总线*/
return(1);
}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
unsigned char dr_ucIIC_WriteByte(unsigned char *slvAddr,unsigned char *data)
{
Start_I2c(); /*启动总线*/
SendByte(*slvAddr); /*发送器件地址*/
if(ack==0)
{
Stop_I2c(); /*结束总线*/
// RETAILMSG(1,(TEXT("GpioI2c: Wd24C080----1\n")));
return(0);
}
I2c_Wait();
I2c_Wait();
SendByte(*data); /*发送数据*/
if(ack==0)
{
Stop_I2c(); /*结束总线*/
// RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
return(0);
}
I2c_Wait();
I2c_Wait();
data++;
SendByte(*data); /*发送数据*/
if(ack==0)
{
Stop_I2c(); /*结束总线*/
// RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
return(0);
}
data++;
SendByte(*data); /*发送数据*/
if(ack==0)
{
Stop_I2c(); /*结束总线*/
// RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
return(0);
}
I2c_Wait();
I2c_Wait();
Stop_I2c(); /*结束总线*/
return(1);
}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
void Delay_ms(int delay)
{
unsigned int val = 0x03AA;
TMCSR0 = 0; /* Stop timer and clear interrupts */
TMRLR0 = val; /* Reload value */
TMCSR0_CSL1 = 1; /* Clock: 00=R/2 01=R/8 10=R/32 */
TMCSR0_CSL0 = 0;
TMCSR0_RELD = 1; /* 1 = reload timer; 0 = one shot timer */
TMCSR0_INTE = 0; /* 1 = Interrupt enable */
TMCSR0_UF = 0; /* clear underflow (UF) interrupt bit */
TMCSR0_CNTE = 1; /* 1 = timer enable - wait for trigger */
TMCSR0_TRG = 1; /* Trigger : Go ! */
while(delay--)
{
while(TMR0 >= val>>1);
while(TMR0 < val>>1);
}
TMCSR0_CNTE = 0;
TMCSR0 = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -