微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > C51单片机模拟I2C总线驱动程序设计(1)

C51单片机模拟I2C总线驱动程序设计(1)

时间:11-26 来源:互联网 点击:
/********************************** I2C 总线驱动 ******************************

模块名:I2C 总线驱动 型号:I2C

功能描述:

此模块包括发送数据及接收数据,应答位发送,并提供了几个直接面对器件的操作函数,能

很方便的与用户程序进行连接并扩展。需要注意的是,函数是采用延时方法产生 SCL 脉冲,

对高晶振频率要做一定的修改!!在写 E2PROM 的时候一定要延时!!!

说明:

1us机器周期,晶振频率要小于12MHz

返回1:则操作成功,返回0:则操作失败。

sla为器件从地址,suba为器件子地址。

*******************************************************************************

#i nclude "AT89X52.h"

#i nclude

#define SomeNOP(); {_nop_();_nop_();_nop_();_nop_();_nop_();} //定义空指令

sbit SDA = P1^3; //模拟 I2C 数据传输位

sbit SCL = P1^2; //模拟 I2C 时钟控制位

bit bdata I2C_Ack; //应答标志位

/************************************ I2C_Start *******************************

函数名:void I2C_Start()

入口:

出口:

功能描述:启动 I2C 总线,即发送 I2C 初始条件

解释: 在 I2C 总线协议中规定的起始位格式是:在 SCL 高电平期间,SDA 发生从高到低的电平

跳变.它与其它数据格式的区别在于,协议中规定有效的数据必须在 SCL 的高电平期间保持

不变,只有在 SCL 的低电平期间才能发生跳变.所以这一有别与其它格式的数据才能做为起

始位.

调用函数:

全局变量

*******************************************************************************

void I2C_Start()

{

SDA = 1; //发送起始条件的数据信号

_Nop();

SCL = 1;

SomeNOP(); //起始条件建立时间大于 4.7us,延时

SDA = 0; //发送起始信号

SomeNOP(); //起始条件建立时间大于 4us,延时

SCL = 0; //钳住 I2C 总线准备发送或接收数据

//解释:I2C 总线在空闲状态下都是被上拉为高电平的,所以当它们处于低电平时就表示忙的状态.

_nop_();

_nop_();

}

/************************************ I2C_Stop ********************************

函数名:void I2C_Stop()

入口:

出口:

功能描述:结束 I2C 总线,即发送 I2C 结束条件

解释:同起始条件的格式类似,结束条件的格式是在 SCL 高电平期间,SDA 由低电平向高电平

跳变.

调用函数:

全局变量:

*******************************************************************************

void I2C_Stop()

{

SDA = 0; //发送结束条件的数据信号

_Nop();

SCL = 1; //发送结束条件的时钟信号

SomeNOP();//结束条件建立时间大于 4us,延时

SDA = 1; //发送 I2C 总线结束信号

SomeNOP();

}

/************************************ I2C_CheckAck ****************************

函数名:bit I2C_CheckAck(void)

入口:

出口:0(无应答),1(有应答)

功能描述:

检验 I2C 总线应答信号,有应答则返回 1,否则返回 0,超时值取 255.

解释:I2C 总线协议中规定传输的每个字节之后必须跟一个应答位,所以从器件在接收到每

个字节之后必须反馈一个应答信号给主控制器,而主控制器就需要检测从器件回传的应答信

号,根据其信息做出相应的处理.另外,主从之别是相对的,接收数据的即为从,发送数据的及

为主.

再看看应答信号的格式:在由发送器产生的时钟响应周期里,发送器先释放 SDA(置高),然后

由接受器将 SDA 拉低,并在这个时钟脉冲周期的高电平期间保持稳定的低电平.即表示从器

件做出了应答.

调用函数:void I2C_Stop()

全局变量:

*******************************************************************************

bit I2C_CheckAck(void)

{

uchar errtime = 255; // 因故障接收方无 Ack,超时值为 255

SDA = 1; //发送器先释放 SDA

SomeNOP();

SCL = 1;

SomeNOP(); //时钟电平周期大于 4 us

while(SDA) //判断 SDA 是否被拉低

{

errtime--;

if(errtime==0)

{

I2C_Stop();

return(0);

}

}

SCL = 0;

_nop_();

return(1);

}

/************************************ I2C_SendB *******************************

函数名:void I2C_SendB(uchar c)

入口:uchar 型数据

出口:

功能描述:

字节数据传送函数,将数据 c 发送出去,可以是地址,也可以是数据,发完后等待应答,

并对

此状态位进行操作

注意:在传送数据时,数据(SDA)的改变只能发生在SCL的低电平期间,在SCL的高电平期间保

持不变

调用函数:bit I2C_CheckAck()

全局变量:I2C_Ack

*******************************************************************************

void I2C_SendB(uchar c)

{

uchar BitCnt;

for (BitCnt=0; BitCnt<8; BitCnt++) //要传送的数据长度为 8 位

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top