您的位置 首页 ADAS

51单片机 一般IO口模仿IIC(I2C)接口通讯的程序代码

I2C总线是Philips公司提出的一种集成电路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; i93; 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; bitCnt8; bitCnt++)

{

SCL = 0 ;

I2C_DELAY;

if ((datum0x80) == 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; bitCnt8; bitCnt++)

{

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

I2C_DELAY;

tempbit = SDA ;

if (tempbit)

temp |= 0x01 ;

else

temp = 0xfe ;

SCL = 1 ;

I2C_DELAY;

if(bitCnt7)

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();

}

『本文转载自网络,版权归原作者一切,如有侵权请联络删去』

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qiche/adas/148053.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部