📄 i2c.c
字号:
/**————————————————————
〖说明〗I2C总线驱动程序(用两个普通IO模拟I2C总线)
包括100Khz(T=10us)的标准模式(慢速模式)选择,
和400Khz(T=2.5us)的快速模式选择,
默认11.0592Mhz的晶振。
〖文件〗I2C.C
〖作者〗yeaman
〖修改〗2006/12/21 命令:BB 接收8个数据并写入;FF 读出所有内容。
〖版本〗V1.00 Build 1221
—————————————————————*/
#include<at89x51a.h>
#include <intrins.h>
#ifndef SDA
#define SDA P0_0
#define SCL P0_1
#endif
#define uchar unsigned char
#define uint unsigned int
#define Byte unsigned char
#define Word unsigned int
#define bool bit
#define true 1
#define false 0
#define SomeNOP(); _nop_();_nop_();_nop_();_nop_();_nop_();
/**--------------------------------------------------------------------------------
调用方式:void I2CStart(void)
函数说明:私有函数,I2C专用
---------------------------------------------------------------------------------*/
void I2CStart(void)
{
//EA=0;
SDA=1; SCL=1; SomeNOP();//INI
SDA=0; SomeNOP(); //START
SCL=0;
}
/**--------------------------------------------------------------------------------
调用方式:void I2CStop(void) ﹫2001/07/0 4
函数说明:私有函数,I2C专用
---------------------------------------------------------------------------------*/
void I2CStop(void)
{
SCL=0; SDA=0; SomeNOP(); //INI
SCL=1; SomeNOP(); SDA=1; //STOP
//EA=1;
}
/**--------------------------------------------------------------------------------
调用方式:bit I2CAck(void) ﹫2001/07/0 4
函数说明:私有函数,I2C专用,等待从器件接收方的应答
---------------------------------------------------------------------------------*/
bool WaitAck(void)
{
uchar errtime=255;//因故障接收方无ACK,超时值为255。
SDA=1;SomeNOP();
SCL=1;SomeNOP();
while(SDA)
{errtime--;
if (!errtime)
{I2CStop();
//SystemError=0x11;
return false;
}
}
SCL=0;
return true;
}
/**--------------------------------------------------------------------------------
调用方式:void SendAck(void) ﹫2001/07/0 4
函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。
---------------------------------------------------------------------------------*/
/*void SendAck(void)
{
SDA=0; SomeNOP();
SCL=1; SomeNOP();
SCL=0;
}
/**--------------------------------------------------------------------------------
调用方式:void SendAck(void) ﹫2001/07/0 4
函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,非应答信号。
}**--------------------------------------------------------------------------------*/
void SendNotAck(void)
{
SDA=1; SomeNOP();
SCL=1; SomeNOP();
SCL=0;
}
/**--------------------------------------------------------------------------------
调用方式:void I2CSend(uchar ch) ﹫2001/07/0 5
函数说明:私有函数,I2C专用
---------------------------------------------------------------------------------*/
/*void I2CSendByte(Byte ch)
{
uchar i=8;
while (i--)
{
SCL=0;_nop_();
SDA=(bit)(ch&0x80); ch<<=1; SomeNOP();
SCL=1; SomeNOP();
}
SCL=0;
}*/
//-------------------------------------------------------------------------
void I2CSendByte(uchar Data)
{
uchar BitCounter=8; //位数控制
uchar temp; //中间变量控制
do
{
temp=Data;
SCL=0;
SomeNOP();
if((temp&0x80)==0x80) //如果最高位是1
SDA=1;
else
SDA=0;
SCL=1;
SomeNOP();
temp=Data<<1; //RLC
Data=temp;
BitCounter--;
}while(BitCounter);
SCL=0;
}
/**--------------------------------------------------------------------------------
调用方式:uchar I2CReceive(void) ﹫2001/07/0 5
函数说明:私有函数,I2C专用
---------------------------------------------------------------------------------*/
Byte I2CReceiveByte(void)
{
uchar i=8;
Byte ddata=0;
SDA=1;
while (i--)
{
ddata<<=1;
SCL=0;SomeNOP();
SCL=1;SomeNOP();
ddata|=SDA;
}
SCL=0;
return ddata;
}
//---------------------------------------------------------------------------
void Readi2c(uchar Data[],uchar Address,uchar Num)
{
uchar i;
uchar *PData;
PData=Data;
for(i=0;i<Num;i++) //读出连续的8个地址的内容
{
I2CStart(); //发送启动信号
I2CSendByte(0xa0); //写入器件地址启动写操作
WaitAck();//
I2CSendByte(Address+i); //写入指定地址
WaitAck();
I2CStart();
I2CSendByte(0xa1); //启动读操作
WaitAck();
*(PData+i)=I2CReceiveByte();
SCL=0;
SendNotAck();
I2CStop();
}
}
//----------------------------------------------------------------------------
void WrToROM(uchar Data[],uchar Address,uchar Num)
{
uchar i;
uchar *PData;
PData=Data;
I2CStart(); //发送启动信号
I2CSendByte(0xa0); //发送SLA+W
WaitAck();
I2CSendByte(Address); //发送地址
WaitAck();
for(i=0;i<Num;i++)
{
I2CSendByte(*(PData+i));
WaitAck();
}
I2CStop();
}
//----------------------------------------------------------------------------
void main()
{
uchar Data[8]={0,0,0,0,0,0,0,0};
uchar i;
uchar a;
uchar j;
uchar resum=0;
TMOD=0x20; //01000000B,定时器工作方式2
TL1=0xfd;TH1=0xfd;//波特率9600
SCON=0x50;//0101 0000 SM2=0 串口工作方式1,允许接收
PCON=0x00;//SMOD=0,
TR1=1;//开始计时
while(RI==0);
RI=0;
a=SBUF;
SBUF=a;
switch (a)
{
/* case 0x00:
WrToROM( Data,resum,7);
delayms(10);
break;*/
case 0xbc:
for(i=0;i<8;i++) //接收8个数据并写入
{
while(RI==0);
RI=0;
a=SBUF;
Data[i]=a;
}
WrToROM( Data,1,8); //数据写入08H地址
delayms(10);
break;
case 0xbb:
for(i=0;i<8;i++) //接收8个数据并写入
{
while(RI==0);
RI=0;
a=SBUF;
Data[i]=a;
}
WrToROM( Data,16,8); //数据写入地址
delayms(10);
break;
case 0xff:
for (j=0;j<16;j++) //读出128字节的内容
{
Readi2c( Data,resum,8);
for (i=0;i<8;i++) //通过串口发送数据给PC
{
a=Data[i];
SBUF=a;
while(TI==0);
TI=0;
}
resum=resum+8;
}
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -