📄 iic.c
字号:
#include <reg51.h> /*头文件的包含*/
#include <intrins.h>
#define BYTE unsigned char /*宏定义*/
#define WORD unsigned int
#define _Nop() _nop_() /*定义空指令*/
/* 常量、变量定义区 */
/*端口位定义*/
sbit SDA = P1^3; /*模拟I2C数据传送位*/
sbit SCL = P1^2; /*模拟I2C时钟控制位*/
/*状态标志*/
bit ack; /*应答标志位*/
/*******************************************************************
起动总线函数
函数原型:
void Start_I2C();
功能:
启动I2C总线,即发送I2C起始条件。
参数:
无。
返回值:
无。
********************************************************************/
void Start_I2C()
{
SDA = 1; /*发送起始条件的数据信号*/
_Nop();
SCL = 1;
_Nop(); /* 起始条件建立时间大于4us,延时 */
_Nop();
_Nop();
_Nop();
_Nop();
SDA = 0; /* 发送起始信号 */
_Nop(); /* 起始条件锁定时间大于4 us */
_Nop();
_Nop();
_Nop();
_Nop();
SCL = 0; /* 准备发送或接收数据 */
_Nop();
_Nop();
}
/*******************************************************************
结束总线函数
函数原型:
void Stop_I2C();
功能:
结束I2C总线,即发送I2C结束条件。
参数:
无。
返回值:
无。
********************************************************************/
void Stop_I2C()
{
SDA = 0; /* 发送结束条件的数据信号 */
_Nop(); /* 发送结束条件的时钟信号 */
SCL = 1; /* 结束条件建立时间大于4 us */
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SDA = 1; /* 发送I2C总线结束信号 */
_Nop();
_Nop();
_Nop();
_Nop();
}
/*******************************************************************
字节数据传送函数
函数原型:
void SendByte(BYTE data);
功能:
将数据data发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态
位进行操作。(不应答或非应答都使ack = 0) 发送数据正常,ack=1;ack=0
表示接收器无应答或损坏。
参数:
需要发送的数据。
返回值:
无。
********************************************************************/
void SendByte(BYTE data)
{
BYTE BitCount;
for(BitCount = 0; BitCount < 8; BitCount ++) /* 要传送的数据长度为8位 */
{
if((data << BitCount) & 0x80) SDA = 1; /* 判断发送位 */
else SDA = 0;
_Nop();
SCL = 1; /* 置时钟线为高,通知被控器开始接收数据位 */
_Nop();
_Nop(); /* 保证时钟高电平周期大于4 us */
_Nop();
_Nop();
_Nop();
SCL = 0;
}
_Nop();
_Nop();
SDA = 1; /* 8位发送完后释放数据线,准备接收应答位*/
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA == 1) ack = 0;
else ack = 1; /* 判断是否接收到应答信号*/
SCL=0;
_Nop();
_Nop();
}
/*******************************************************************
字节数据传送函数
函数原型:
BYTE RecByte();
功能:
用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后请用
应答函数。
参数:
无。
返回值:
读取到的数据。
********************************************************************/
BYTE RecByte()
{
BYTE RecData;
BYTE BitCount;
RecData = 0;
SDA = 1; /* 置数据线为输入方式 */
for(BitCount = 0; BitCount < 8; BitCount ++)
{
_Nop();
SCL=0; /* 置时钟线为低,准备接收数据位 */
_Nop();
_Nop(); /* 时钟低电平周期大于4.7us */
_Nop();
_Nop();
_Nop();
SCL= 1; /* 置时钟线为高使数据线上数据有效 */
_Nop();
_Nop();
RecData = RecData << 1;
if(SDA==1) RecData = RecData +1; /* 读数据位,接收的数据位放入retc中 */
_Nop();
_Nop();
}
SCL= 0;
_Nop();
_Nop();
return(RecData);
}
/********************************************************************
应答子函数
原型:
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(); /* 时钟低电平周期大于4us */
_Nop();
_Nop();
_Nop();
SCL = 0; /* 清除时钟线,以便继续接收 */
_Nop();
_Nop();
}
/*******************************************************************
向无子地址器件发送字节数据函数
函数原型:
bit SendByteData(BYTE Slave,BYTE Data);
功能:
从启动总线到发送地址,数据,结束总线的过程。
参数:
slave--从器件地址。
data --要发送的数据。
返回值:
如果返回1表示操作成功,否则操作有误。
注意:
使用前必须已结束总线。
********************************************************************/
bit SendByteData (BYTE Slave, BYTE Data)
{
Start_I2C(); /* 启动总线 */
SendByte(Slave); /* 发送器件地址 */
if(ack == 0) return(0);
SendByte(Data); /* 发送数据 */
if(ack == 0) return(0);
Stop_I2C(); /* 结束总线 */
return(1);
}
/*******************************************************************
向有子地址器件发送多字节数据函数
函数原型:
bit SendStr(BYTE Slave, BYTE SubAddress, BYTE *Source, BYTE Num);
功能:
从启动总线到发送地址,子地址,数据,结束总线的过程。
参数:
Slave--从器件地址
SubAddress--子地址
Source--指向发送内容的指针
Num--发送字节个数
返回值:
如果返回1表示操作成功,否则操作有误。
注意:
使用前必须已结束总线。
********************************************************************/
bit SendStr(BYTE Slave, BYTE SubAddress, BYTE *Source, BYTE Num)
{
BYTE i;
Start_I2C(); /* 启动总线 */
SendByte(Slave); /* 发送器件地址 */
if(ack == 0) return(0);
SendByte(SubAddress); /* 发送器件子地址 */
if(ack == 0) return(0);
for(i = 0; i < Num; i++)
{
SendByte(*Source); /* 发送数据 */
if(ack == 0) return(0);
Source ++;
}
Stop_I2C(); /* 结束总线 */
return(1);
}
/*******************************************************************
向无子地址器件读字节数据函数
函数原型:
bit RecByteData(BYTE Slave,BYTE *Data);
功能:
从启动总线到发送地址,读数据,结束总线的过程。
参数:
从器件地址Slave,返回值在Data。
返回值:
如果返回1表示操作成功,否则操作有误。
注意:
使用前必须已结束总线。
********************************************************************/
bit RecByteData(BYTE Slave,BYTE *Data)
{
Start_I2C(); /* 启动总线 */
SendByte(Slave+1); /* 发送器件地址 */
if(ack == 0) return(0);
*Data = RecByte(); /* 读取数据 */
Ack_I2C(1); /* 发送非就答位 */
Stop_I2C(); /* 结束总线 */
return(1);
}
/*******************************************************************
向有子地址器件读取多字节数据函数
函数原型:
bit RecStr(BYTE Slave, BYTE SubAddress, BYTE *Source, BYTE Num);
功能:
从启动总线到发送地址,子地址,读数据,结束总线的过程。
参数:
Slave--从器件地址。
SubAddress--子地址
Source--指向读出的内容放入的存储区的指针
Num--读字节个数。
返回值:
如果返回1表示操作成功,否则操作有误。
注意:
使用前必须已结束总线。
********************************************************************/
bit RecStr(BYTE Slave, BYTE SubAddress, BYTE *Source, BYTE Num)
{
BYTE i;
Start_I2C(); /* 启动总线 */
SendByte(Slave); /* 发送器件地址 */
if(ack == 0) return(0);
SendByte(SubAddress); /* 发送器件子地址 */
if(ack == 0) return(0);
Start_I2C();
SendByte(Slave+1);
if(ack == 0) return(0);
for(i = 0; i < Num-1; i++)
{
*Source = RecByte(); /* 发送数据 */
Ack_I2C(0); /* 发送就答位 */
Source++;
}
* Source =RecByte();
Ack_I2C(1); /* 发送非应位 */
Stop_I2C(); /* 结束总线 */
return(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -