📄 i2c.c
字号:
/********************************************************************************************
通过I2C总线对EEPROM读写操作源程序。
********************************************************************************************/
#include <I2C.h>
void SETSDA(uchar port)
{
if(port==I2C0) I2C0SDA=1;
if(port==I2C1) I2C1SDA=1;
}
void CLRSDA(uchar port)
{
if(port==I2C0) I2C0SDA=0;
if(port==I2C1) I2C1SDA=0;
}
void SETSCL(uchar port)
{
if(port==I2C0) I2C0SCL=1;
if(port==I2C1) I2C1SCL=1;
}
void CLRSCL(uchar port)
{
if(port==I2C0) I2C0SCL=0;
if(port==I2C1) I2C1SCL=0;
}
/*******************************************************************************************
启动I2C总线.
*******************************************************************************************/
void Start_I2c(uchar port)
{
setSCL;
setSDA;
delay(0);
clrSDA;
delay(0);
}
/*******************************************************************************************
结束I2C总线
********************************************************************************************/
void Stop_I2c(uchar port)
{
setSCL;
clrSDA;
delay(0);
setSDA;
delay(0);
}
/*******************************************************************
发送一个字节
********************************************************************/
bit SendByte(uchar c, uchar port)
{
uchar BitCnt;
bit ack;
for(BitCnt=0;BitCnt<8;BitCnt++) /*数据长度为8位*/
{
clrSCL;
if((c<<BitCnt)&0x80) setSDA; /*设置数据位*/
else clrSDA;
delay(0);
setSCL; /*置时线为高电平,通知接收方读数据*/
delay(0);
}
clrSCL;
setSDA; /*8位数据发送完毕,释放数据线,准备接收应答。*/
delay(0);
setSCL;
if(port==I2C0)
{
if(I2C0SDA==1) ack=0; /*检查是否收到了确认信号。ack==0,不确认*/
else ack=1; /* ack==1,确认。*/
}
if(port==I2C1)
{
if(I2C1SDA==1) ack=0; /*检查是否收到了确认信号。ack==0,不确认*/
else ack=1; /*ack==1,确认。*/
}
delay(0);
clrSCL;
clrSDA;
delay(0);
if(ack==1) return(1); /*如果成功写入了数据,返回1*/
else return(0);
}
/*******************************************************************
读一个字节,读完数据要应答
********************************************************************/
uchar RcvByte(uchar port)
{
uchar retc;
uchar BitCnt;
retc=0;
for(BitCnt=0;BitCnt<8;BitCnt++)
{
clrSCL; /*准备接收数据*/
setSDA; /*把数据线输出寄存器设为1,为输入数据作准备。*/
delay(0);
setSCL; /*置时钟线为高是平,使数据线上的数据有效*/
retc=retc<<1;
if(port==I2C0)
{
if(I2C0SDA==1)retc=retc+1; /*读数据位 */
}
if(port==I2C1)
{
if(I2C1SDA==1)retc=retc+1; /*读数据位*/
}
delay(0);
}
return(retc); /*返回收到的数据*/
}
/********************************************************************
应答函数
********************************************************************/
void Ack_I2c(bit a, uchar port)
{
clrSCL;
if(a==0)clrSDA; /*确认信号*/
else setSDA; /*不确认*/
delay(0);
setSCL;
delay(0);
}
/********************************************************************************************
多字节数据写函数
功能: 通过"port"总线,向器件地址为"sla"的E2PROM从子地址"suba"开始写入"no"个数据,要发送的数据在指钟"s"所指向的地址中。返回值为1表示操作成功。
********************************************************************************************/
bit WriteStr(uchar sla,uchar suba,uchar *s,uchar no, uchar port)
{
uchar i;
Start_I2c(port); /*I2C Start*/
if(SendByte(sla, port)==0) return(0); /*发送器件地址*/
if(SendByte(suba, port)==0) return(0); /*发送子地址*/
for(i=0;i<no;i++)
{
if(SendByte(*s, port)==0) return(0); /*发送数据*/
s++;
}
Stop_I2c(port); /*I2C Stop*/
return(1);
}
/********************************************************************************************
多字节数据读函数
功能: 通过"port"总线,从器件地址为"sla"的E2PROM的子地址"suba"开始读取"no"个数据,读取的数据放在指钟"s"所指向的地址中。返回值为1表示操作成功。
********************************************************************************************/
bit ReadStr(uchar sla,uchar suba,uchar *s,uchar no, uchar port)
{
uchar i;
Start_I2c(port); /*I2C Start*/
if(SendByte(sla, port)==0) return(0); /*发送器件地址*/
if(SendByte(suba,port)==0) return(0); /*发送子地址*/
Start_I2c(port); /*ReStart*/
if(SendByte(sla+1, port)==0) return(0);
for(i=0;i<no-1;i++)
{
*s=RcvByte(port); /*接收最后一位数据*/
Ack_I2c(0, port); /*发送应答位*/
s++;
}
*s=RcvByte(port); /*接收最后一位数据*/
Ack_I2c(1, port); /*发送应答位*/
Stop_I2c(port); /*结束总线*/
return(1);
}
/********************************************************************************************
延时函数,没有返回值。
********************************************************************************************/
void delay(int us)
{
int i;
for(i=0;i<us;i++) _Nop();
}
bit Wait(uchar sla, uchar port)
{
int i;
bit ack;
i=0;
do
{
Start_I2c(port);
i++;
if(i>30000) return(0); /*如果等待时间超过30ms,结束等待,以免死循环*/
ack=SendByte(sla, port); /*发送器件地址*/
} while(!ack);
Start_I2c(port);
Stop_I2c(port);
return(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -