📄 iic.c
字号:
#include "reg51.h"
#include "IIC.h"
#include <stdio.h>
#include <intrins.h>
/*---------------------------------
启动总线函数
函数原型:Start_I2C()
功能:启动I2C总线,即发送起始条件
---------------------------------*/
void Start_I2C()
{
SDA = 1; //发送起始条件数据信号
_nop_();
SCL = 1;
_nop_(); //起始建立时间大于4.7us
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 0; //发送起始信号
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0; //钳位
_nop_();
_nop_();
}
/*-------------------------------
结束总线函数
函数原型:Stop_I2C()
功能:结束I2C总线,即发送I2C结束条件
-------------------------------*/
void Stop_I2C()
{
SDA = 0; //发送结束条件的数据信号
_nop_(); //发送结束条件的时钟信号
SCL = 1; //结束条件建立时间大于4us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 1; //发送I2C总线结束命令
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
/*------------------------------
字节数据传送函数
函数原型:SendByte(uchar c)
功能:将数据C发送出去,可以是地址,
也可以是数据,发送完成之后等待应答
并且对应答状态位进行操作,不应答和非
应答都使得ACK=0,发送数据正常则ACK=1
--------------------------------*/
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; //释放数据线,准备接受应答位
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
_nop_();
if(SDA == 1) ack =0;
else ack = 1; //判断是否收到应答信号
SCL = 0;
_nop_();
_nop_();
}
/*-------------------------------------------
字节数据接收函数
函数原型:uchar RcvByte();
功能:用来接收从器件传来的数据,并且判断总线错误(不发送应答信号)
发送完成后使用应答信号
-------------------------------------------*/
uchar RcvByte();
{
uchar retc;
uchar BitCnt;
retc = 0;
SDA = 1; //置数据线为输入方式
for(BitCnt = 0;BitCnt < 8;BitCnt++)
{
_nop_();
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 == 0)SDA = 0; //在此发出应答信号或者非应答信号
else SDA = 1;
nop();
nop();
nop();
SCL = 1;
nop();
nop();
nop();
nop();
nop();
SCL = 0;
nop();
nop();
}
/*----------------------------------
向无子地址器件发送字节数据函数
函数原型:bit ISendByte( uchar sla,uchar c);
功能:从启动总线到发送地址,数据,结束总线的全过程,从器件地址
sla。如果返回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
子地址suba,读出内容放在s指向的存储区,读no个字节
如果返回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)
{
uchar i;
Start_I2C(); //启动总线
SendByte(sla); //发送器件地址
if(ack == 0)
return(0);
SendByte(suba); //发送子地址
if(ack == 0)
return(0);
Start_I2C(); //启动
StartByte(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 + -