当前位置:首页 > 单片机 > 单片机
[导读]I2C总线是Philips公司提出的一种集成电路IC器件之间相连接的总线协议,其目的是使电子系统(不只 限于单片机系统)各个IC器件之间的连线变得容易。因为使用传统的并行总线在IC器件之间连接,往往会使得IC之间连线较多

I2C总线是Philips公司提出的一种集成电路IC器件之间相连接的总线协议,其目的是使电子系统(不只 限于单片机系统)各个IC器件之间的连线变得容易。因为使用传统的并行总线在IC器件之间连接,往往会使得IC之间连线较多,显得非常复杂。而I2C总线 则使IC器件之间只需SDA、SCL两条连线就可以传送数据,因而十分方便。由于I2C在印刷体中不容易书写(需要上标),所以实际书写时,还常见到 IIC、I2C等书写方法,本文采用IIC的写法,敬请注意。关于IIC总线的知识,请参阅相关书籍,此处不再做进一步介绍。

下面我们用一个使用IIC总线连接器件的例子来简单说明IIC总线的仿真。

例.EEPROM24C02是采用IIC接口的一种常用2Kbit(256×8bit)的存储器。编写程序使用AT89C51的IO口模拟实现IIC总线协议进行通信,并向24C02存储器内从字节0到字节FF写入数字0到FF。

51系列单片机本身没有IIC接口,但一些本身具有IIC接口的单片机往往是高端产品,一方面价格不菲,另一方面我们的系统也没有必要使用之。通常我们就使用软件通过51系列单片机的IO口来模拟实现IIC总线通信。

本例事实上比较简单,但需要对IIC总线时序有较好的理解。源文件如下图所示(采用C51语言编写):







在Keil中编辑好源文件以后,接下来就可以建立工程文件并生成相应的源代码了,然后我们来绘制电路图。
此例的电路图极其简单。只需两个IC,即AT89C51和24C02C,和两个上拉电阻,而且上拉电阻还可以省略。至于连接,就更为简单了。最后得到绘制好的电路图如下图所示:



绘制好电路图,我们就可以将前面刚刚生成的程序源代码装入单片机了,装入以后,下面我们就可以来进行仿真了。

首先点击仿真按钮,系统没有什么反映,只有高低电平变化的颜色。我们要想查看结果,还要用前文中仿真扩展 RAM存储器的方法,先点击暂停,然后点击“Debug”菜单下的“I2C Memory Internal Memory – U2”子菜单来打开U2即EEPROM存储器24C02C的内容窗口“I2C Memory Internal Memory – U2”,然后我们就看到了其中的内容,也就是我们仿真程序的结果。如下图所示:



从图中我们能清楚地看到我们的仿真结果,程序完全正确地执行了我们的命令。

当然,如果你过早地点击了暂停按钮,那么你得到的结果可能和上图略有不同,那可能是因为程序尚未执行完毕。此时你可以继续点击运行按钮,或者点击单步按钮来仔细查看程序执行过程中24C02C存储器内容的改变情况。


完整代码如下:

/*----------------------------------------------------------------

Acess the eeprom--24c04

----------------------------------------------------------------*/

#include


#ifndef INT8U

#define INT8U unsigned char

#endif


#ifndef INT8S

#define INT8S signed char

#endif


#ifndef INT16U

#define INT16U unsigned int

#endif


#define I2C_DELAY; _nop_();_nop_();_nop_();_nop_();_nop_(); // >=4.7uS


//----------------------------------------------------------------

// delay 100us

//----------------------------------------------------------------

void mDelay(INT8U k)

{

INT16U i ;


for(; k>0; k--)

{

for(i=0; i<93; i++)

;

}

}




//----------------------------------------------------------------

//OK

//----------------------------------------------------------------

void I2C_Start(void)

{

SDA = 1;

I2C_DELAY;


SCL = 1;

I2C_DELAY;


SDA = 0;

I2C_DELAY;

I2C_DELAY;

}




//----------------------------------------------------------------

//OK

//----------------------------------------------------------------

void I2C_Stop(void)

{

SDA = 0 ;

I2C_DELAY;


SCL = 1 ;

I2C_DELAY;


SDA = 1 ;

I2C_DELAY;

I2C_DELAY;

}




//----------------------------------------------------------------

//

//----------------------------------------------------------------

void sendAck(void)

{

SCL = 0;

I2C_DELAY;


SDA = 0;

I2C_DELAY;


SCL = 1;

I2C_DELAY;


}



//----------------------------------------------------------------

//

//----------------------------------------------------------------

void sendNoAck(void)

{

SCL = 0;

I2C_DELAY;


SDA = 1;

I2C_DELAY;


SCL = 1;

I2C_DELAY;


}



//----------------------------------------------------------------

// 0 = noACK; 1 = ACK ;

//----------------------------------------------------------------

bit checkAck()

{

bit tempbit;

/*发送完一个字节后检验设备的应答信号*/

SDA = 1;

I2C_DELAY;


SCL = 0;

I2C_DELAY;


tempbit = SDA;


SCL = 1;

I2C_DELAY;


if(tempbit==1)

{

return 0; //noACK

}

else

{

return 1; //ACK

}

}




//----------------------------------------------------------------

//OK

// a positive clock edge clock a bit into the ROM

//----------------------------------------------------------------

void writeByte(INT8U datum)

{

INT8U bitCnt = 0 ;


for(bitCnt=0; bitCnt<8; bitCnt++)

{

SCL = 0 ;

I2C_DELAY;


if ((datum&0x80) == 0x80) //if the MSb is 1

SDA = 1 ;

else

SDA = 0 ;

I2C_DELAY;


SCL = 1 ;

I2C_DELAY;


datum<<=1 ;

}


}




//----------------------------------------------------------------

//OK

//----------------------------------------------------------------

INT8U readByte(void)

{

bit tempbit = 1 ;

INT8U temp = 0 ;

INT8U bitCnt ;


SDA = 1 ; // release the bus,ready to receive byte??????????????

I2C_DELAY;


for(bitCnt=0; bitCnt<8; bitCnt++)

{

SCL = 0; //?????????????????????????huan???????????????

I2C_DELAY;


tempbit = SDA ;

if (tempbit)

temp |= 0x01 ;

else

temp &= 0xfe ;


SCL = 1 ;

I2C_DELAY;


if(bitCnt<7)

temp <<= 1 ;


}


return(temp) ;

}




/*~~~~~~~~~~~~~~~~~~~~~~~ API ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/


/*-----------------------------------------------------------------

write some bytes to sequential address

-----------------------------------------------------------------*/

void writeToROM(INT8U datum[], INT8U address, INT8U num)

{

bit tempbit ;

INT8U i ;

INT8U *datum_P ;

datum_P = datum ;


I2C_Start() ;


writeByte(0xa0) ;

tempbit = checkAck();


writeByte(address) ;

tempbit = checkAck();


for(i=0; i

{

writeByte(*(datum_P+i)) ;



if(!checkAck())

{

I2C_Stop() ;

mDelay(100) ;

}

}


I2C_Stop() ;

}




/*-----------------------------------------------------------------

read some bytes from ROM`s sequential address

-----------------------------------------------------------------*/

void readFromROM(INT8U datum[], INT8U address, INT8U num)

{

bit tempbit ;

INT8U i ;

INT8U *datum_P ;


datum_P = datum;


I2C_Start() ;


writeByte(0xa0) ;

tempbit = checkAck();


writeByte(address) ;

tempbit = checkAck();


I2C_Start() ;

writeByte(0xa1) ;

tempbit = checkAck();


for(i=0; i

{

*(datum_P+i) = readByte() ;


if(i!=num-1)

{

sendAck() ;

}

else

{

sendNoAck() ;

}

}


I2C_Stop() ;

}




/*-----------------------------------------------------------------

wirte one byte to ROM --random write

-----------------------------------------------------------------*/

void writeOneByte(INT8U addr, INT8U datum)

{

bit tempbit ;

/*write a byte to mem*/


I2C_Start();


writeByte(0xa0);

tempbit = checkAck();


writeByte(addr); /*address*/

tempbit = checkAck();


writeByte(datum); /*the data*/


tempbit = checkAck();


I2C_Stop();

mDelay(100) ;


}




/*-----------------------------------------------------------------

read one byte from rom --random read

-----------------------------------------------------------------*/

INT8U readOneByte(INT8U addr)

{

bit tempbit = 1;

INT8U mydata;

/*read a byte from mem*/


I2C_Start();


writeByte(0xa0);

tempbit = checkAck();


writeByte(addr); /*address*/

tempbit = checkAck();


I2C_Start();


writeByte(0xa1);

tempbit = checkAck();


mydata = readByte();

tempbit = checkAck();


return (mydata) ;


I2C_Stop();

}

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

无线通讯技术在现代社会中发挥着越来越重要的作用,然而在实际使用过程中,会遭遇各种形式的干扰,影响通信质量。

关键字: 无线通信 通讯 噪声干扰

华为似乎成了一道不可忽视的风景线。它在全球通信领域的崛起和持续的创新势头,引发了许多猜测与议论。但是,背后的故事却鲜为人知。

关键字: 华为通信 通信领域 通讯

串口通信作为一种最传统的通信方式,在工业自动化、通讯、控制等领域得到广泛使用。

关键字: Linux 串口通信 通讯

可编程逻辑控制器是种专门为在工业环境下应用而设计的数字运算操作电子系统。它采用一种可编程的存储器,在其内部存储执行逻辑运算、顺序控制、定时、计数和算术运算等操作的指令

关键字: plc 通讯 逻辑运算

显然这是目前存在的现状,蓝牙Mesh、Zigbee等一些标准共存于物联网智能家居江湖,但又谁也取代不了谁。正如周巍所说:“没有任何一个标准能在一个应用层垄断,尽管小米阿里在主推蓝牙Mesh,华为在推Zigbee,但未来迟...

关键字: 物联网 协议 通讯

蓝牙设备在生活中无处不在,但是我们也只是将其作为蓝牙模块进行使用,发送简单的AT命令实现数据收发。那么,像对于一些复杂的使用场合:“车载蓝牙”、"智能手表"、“蓝牙音箱”等,我们不得不去了解底层的蓝牙实现原理。

关键字: 蓝牙 无线电技术 通讯

上海2022年9月28日 /美通社/ -- 9月28日,中国广电5G(上海)网络服务精彩启航仪式在东方明珠电视塔举行。此举标志着在中国广电事业扬帆启航、守正创新之年,上海广电5G建设已圆满达成重大节点目标。中共上海市委常...

关键字: 通讯 中国广电 5G

全球首款超低功耗Wi-Fi 6+BLE物联网双模通讯芯片 新竹2022年9月26日 /美通社/ -- 旺凌科技宣布其新一代物联网通讯芯片OPL2500通过了WIFI联盟的WIFI6认证测试。延续其OPL1000系列的低...

关键字: 芯片 WIFI6 通讯 BSP

(全球TMT2022年9月2日讯)音频、视频和协作解决方案企业Jabra宣布与富士胶片商业创新(原富士施乐)合作,为亚太区客户提供基于Jabra Evolve2 系列专业办公耳麦及Speak系列全向麦的统一通讯解决方案...

关键字: 富士 通讯 音频 EV

合作旨在促进亚太区企业无缝统一通讯 上海2022年9月2日 /美通社/ -- 音频、视频和协作解决方案领军企业 Jabra 今日宣布与富士胶片商业创新(原富士施乐)合作,为亚太区客户提供基于Jabra Evolve2...

关键字: 富士 数字化 通讯 音频
关闭
关闭