IIC总线协议程序
//---------------------------------------------------------------// delay 100us //---------------------------------------------------------------void mDelay(INT8U k) { INT16U i ;
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
datum_P = datum;
I2C_Start() ;
writeByte(0xa0) ; tempbit = checkAck();
writeByte(address) ;
tempbit = checkAck();
I2C_Start() ; writeByte(0xa1) ; tempbit = checkAck();
SCL = 1 ; I2C _DELAY;
SDA = 1 ; I2C _DELAY; I2C _DELAY; }
//---------------------------------------------------------------// //---------------------------------------------------------------void sendAck(void) {
for(bitCnt=0; bitCnt<8; bitCnt++) {
SCL = 0; //?????????????????????????huan??????wk.baidu.com???????? I2C _DELAY;
tempbit = SDA ; if (tempbit) temp |= 0x01 ; else temp &= 0xfe ;
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;
I2C _DELAY;
SDA = 1; I2C _DELAY;
SCL = 1; I2C _DELAY;
}
//---------------------------------------------------------------// 0 = noACK; 1 = ACK ; //---------------------------------------------------------------bit checkAck() { bit tempbit; /*发送完一个字节后检验设备的应答信号 */ SDA = 1;
datum_P = datum ;
I2C_Start() ;
writeByte(0xa0) ; tempbit = checkAck();
writeByte(address) ; tempbit = checkAck();
for(i=0; i<num; i++) { writeByte(*(datum_P+i)) ;
下面我们用一个使用 IIC 总线连接器件的例子来简单说明 IIC 总线的仿真。 例.EEPROM24C02是采用 IIC 接口的一种常用2Kbit(256×8bit)的存储器 。 编写程序使用 AT89C51的 IO 口模拟实现 IIC 总线协议进行通信,并向24C02存 储器内从字节0到字节 FF 写入数字0到 FF。 51系列单片机本身没有 IIC 接口,但一些本身具有 IIC 接口的单片机往往是 高端产品,一方面价格不菲,另一方面我们的系统也没有必要使用之。通常我们 就使用软件通过51系列单片机的 IO 口来模拟实现 IIC 总线通信。 本例事实上比较简单,但需要对 IIC 总线时序有较好的理解。源文件如下图 所示(采用 C51语言编写):
/*---------------------------------------------------------------Acess the eeprom--24c04 ----------------------------------------------------------------*/ #include <intrins.h>
//---------------------------------------------------------------void writeByte(INT8U datum) { INT8U bitCnt = 0 ;
for(bitCnt=0; bitCnt<8; bitCnt++) {
SCL = 0 ; I2C _DELAY;
for(i=0; i<num; i++) {
*(datum_P+i) = readByte() ;
我们仿真程序的结果。如下图所示:
从图中我们能清楚地看到我们的仿真结果,程序完全正确地执行了我们的 命令。
当然,如果你过早地点击了暂停按钮,那么你得到的结果可能和上图略有 不同,那可能是因为程序尚未执行完毕。此时你可以继续点击运行按钮,或者点 击单步按钮来仔细查看程序执行过程中24C02C 存储器内容的改变情况。
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 ;
51单片机 IO 口模拟 IIC 总线协议
2008-01-13 15:01
I2C 总线是 Philips 公司提出的一种集成电路 IC 器件之间相连接的总线协 议,其目的是使电子系统(不只限于单片机系统)各个 IC 器件之间的连线变得 容易。因为使用传统的并行总线在 IC 器件之间连接,往往会使得 IC 之间连线较 多,显得非常复杂。而 I2C 总线则使 IC 器件之间只需 SDA、SCL 两条连线就可 以传送数据,因而十分方便。由于 I2C 在印刷体中不容易书写(需要上标),所 以实际书写时,还常见到 IIC、I2C 等书写方法,本文采用 IIC 的写法,敬请注 意。关于 IIC 总线的知识,请参阅相关书籍,此处不再做进一步介绍。
SCL = 1; I2C _DELAY;
SDA = 0; I2C _DELAY; I2C _DELAY; }
//---------------------------------------------------------------//OK //---------------------------------------------------------------void I2C_Stop(void) { SDA = 0 ; I2C _DELAY;
for(; k>0; k--) { for(i=0; i<93; i++)
; } }
//---------------------------------------------------------------//OK //---------------------------------------------------------------void I2C_Start(void) { SDA = 1; I2C _DELAY;
首先点击仿真按钮,系统没有什么反映,只有高低电平变化的颜色。我们 要想查看结果,还要用前文中仿真扩展 RAM 存储器的方法,先点击暂停,然后 点击“Debug”菜单下的“I2C Memory Internal Memory – U2”子菜单来打开 U2即 EEPROM 存储器24C02C 的内容窗口“I2C Memory Internal Memory – U2”,然 后我们就看到了其中的内容,也就是
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 ;
SCL = 0; I2C _DELAY;
SDA = 0; I2C _DELAY;
SCL = 1; I2C _DELAY;
}
//---------------------------------------------------------------// //---------------------------------------------------------------void sendNoAck(void) { SCL = 0;
在 Keil 中编辑好源文件以后,接下来就可以建立工程文件并生成相应的源 代码了,然后我们来绘制电路图。
此例的电路图极其简单。只需两个 IC,即 AT89C51和24C02C,和两个上 拉电阻,而且上拉电阻还可以省略。至于连接,就更为简单了。最后得到绘制好 的电路图如下图所示:
绘制好电路图,我们就可以将前面刚刚生成的程序源代码装入单片机了, 装入以后,下面我们就可以来进行仿真了。
#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