📄 i2c.c
字号:
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
//常变量定义区,端口位定义
sbit SDA=P3^4;
sbit SCL=P3^5;
//状态标志
bit ack;
/***************************************************************
启动总线函数
函数原型:void Start_I2C();
功能:启动I2C总线,即发送I2C起始条件
***************************************************************/
void Start_I2C()
{
SDA=1;
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
_nop_();
_nop_();
}
/***************************************************************
结束总线函数
函数原型:void Stop_I2c();
功能:结束I2C总线,即发送I2C结束条件
****************************************************************/
void Stop_I2C()
{
SDA=0;
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
_nop_();
_nop_();
}
/****************************************************************
字节数据传送函数
函数原型:void SendByte(uchar c)
功能:将数据c发送出去,可以时地址,也可以时数据,发完后等待应答,并对
此状态位进行操作(不应答或非应答都使ack=0,表示应答失败)。发送数据正常,ack=1;ack=0
表示被控器无应答或损坏
*******************************************************************/
void SendByte(uchar c)
{
uchar BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++)
{
if((c<<BitCnt)&0x80)
SDA=1;
else SDA=0;
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
}
_nop_();
_nop_();
SDA=1; //8位发送完后释放数据线,准备接收应答位
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
if(SDA==1) //应答时接收器必须把SDA线拉低
ack=0;
else ack=1; //判断是否接收到应答信号
SCL=0;
_nop_();
_nop_();
}
/*************************************************************************
字节数据接受函数
函数原型:uchar RcvByte();
功能:用来接收从器件传来的数据,并判断总线错误(不发应答信号)
*************************************************************************/
uchar RcvByte()
{
uchar retc;
uchar BitCnt;
retc=0;
for(BitCnt=0;BitCnt<8;BitCnt++)
{
SDA=1; //置数据线为输入方式
SCL=0; //置时钟线低,准备接受数据位
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=1; //置时钟线为高,使数据线上数据有效
_nop_();
_nop_();
retc=retc<<1;
if(SDA==1)
retc=retc+1;
_nop_();
_nop_();
}
SCL=0;
_nop_();
_nop_();
return(retc);
}
/***************************************************************
应答子函数
函数原型:void Ack_I2c(bit a);
功能:主控制器进行应答信号(可以是应答或非应答信号)
***************************************************************/
void Ack_I2C(bit a)
{
if(a)
SDA=1;
else
SDA=0;
_nop_();
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
_nop_();
_nop_();
}
/****************************************************************
向无子地址器件发送字节数据函数
函数原型:bit ISendByte(uchar sla,uchar c);
功能:从启动总线到发送地址,数据,直至结束总线的全过程;从器件地址sla,c为发送内容。
如果返回1,表示操作成功,否则失败
*********************************************************************/
bit ISendByte(uchar sla,uchar c)
{
Start_I2C();
SendByte(sla);
if(ack==0)
return(0);
SendByte(c);
if(ack==0)
return(0);
Stop_I2C();
return(1);
}
/***************************************************************
向有子地址器件发送多字节数据函数
函数原型:bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no);
功能:从启动总线到发送地址,子地址,数据直到结束总线的全过程;从器件地址sla,子地址suba,发送的内容是s指向的内容,
发送no个字节。如果返回是1,表示成功,否则失败。
****************************************************************/
bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)
{
uchar i;
Start_I2C();
SendByte(sla);
if(ack==0)
return(0);
SendByte(suba);
if(ack==0)
return(0);
for(i=0;i<no;i++)
{
SendByte(*s);
if(ack==0)
return(0);
s++;
}
Stop_I2C();
return(1);
}
/********************************************************************
向无子地址器件读取字节数据函数
函数原型:bit IRcvByte(uchar sla,uchar *c);
功能:从启动总线到发送地址,直至结束总线的全过程;从器件地址sla,
读取数据返回值c.如果返回是1表示成功,否则失败
**************************************************************************/
bit IRcvByte(uchar sla,uchar *c)
{ //立即地址读取
Start_I2C();
SendByte(sla+1);
if(ack==0)
return(0);
*c=RcvByte();
Ack_I2C(1);
Stop_I2C();
return(1);
}
/******************************************************************************
向有子地址器件读取多字节数据函数
函数原型:bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no);
功能:从启动总线到发送地址,子地址,数据直到结束总线的全过程;从器件地址sla,子地址suba,到读出内容放到s指向的存储区,
读no个字节。如果返回是1,表示成功,否则失败。
****************************************************************/
bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)
{
uchar i;
Start_I2C();
SendByte(sla); //伪写操作
if(ack==0)
return(0);
SendByte(suba);
if(ack==0)
return(0);
Start_I2C();
SendByte(sla+1); //读操作命令
if(ack==0)
return(0);
for(i=0;i<no-1;i++)
{
*s=RcvByte();
Ack_I2C(0); //发送应答信号
s++;
}
*s=RcvByte();
Ack_I2C(1); //发送非应答信号并停止读操作
Stop_I2C();
return(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -