您的位置:首页 > 其它

51模拟I2c,原理+程序

2016-07-29 22:48 323 查看

1、I2c启动



    由上图可知SDA在SCL为高电平时由高变为低表示启动I2c,注意时间。

2、I2c关闭



    由上图可知SDA在SCL为高电平时由低变为高表示启动I2c,注意时间。

3、数据0



    由上图可知SDA在SCL为高电平时拉低表示0,注意时间。

4、数据1



    由上图可知SDA在SCL为高电平时拉高表示0,注意时间。

5、I2c写数据(数据由51到设备)



由上图可以看书写数据的步骤为:

1)启动I2c;

2)写入设备地址(七位设备地址加一位读写命令,最后1为读,0为写);

3)等待应答(由设备发出,读数据时由51给应答),这一步可以和第二部写在一个函数中;

4)写入数据要存放的地址;

5)等待应答;

6)写入数据;

7)等待应答;

8)关闭I2c。

若将等待应答与写数据放在一个函数中可简化为:

1)启动I2c;

2)写入设备地址

3)写入数据要存放的地址;

4)写入数据;

5)关闭I2c。

6、I2c读数据(51从设备中读取数据)



由上图可以看书写数据的步骤为:

1)启动I2c;

2)写入设备地址;

3)写入要读取数据存放的地址;

4)启动I2c;

5)写入设备地址(第八位为1,表示读数据);

6)读数据;

7)给设备发送应答信号;

8)关闭I2c;

7、对应的51程序

#include <STC12C5A60S2.H>
#define uchar unsigned char
#define uint unsigned int

sbit SCL=P2^1;
sbit SDA=P2^0;
uchar code duan[]=
{
0xfc,0x60,0xda,
0xf2,0x66,0xb6,
0xbe,0xe0,0xfe,0xf6
};

void delay(uint time) 	//ÑÓ³Ù9us
{
uint i,j;
for(i=0;i<time;i++)
for(j=0;j<10;j++);
}

void I2c_start()
{
SDA=1;
delay(1);
SCL=1;
delay(1);		//ÑÓ³ÙÖÁÉÙ4.7us
SDA=0;
delay(1);		//±£³Öʱ¼ä>4us
SCL=0;
delay(1);
}

void I2c_stop()
{
SDA=0;
delay(1);
SCL=1;
delay(1);	//ÑÓ³ÙÖÁÉÙ4.7us
SDA=1;
delay(1);
}

//·¢ËÍack
void I2c_sendAck(bit ack)
{
SDA = ack;
SCL = 1;
delay(1);
SCL = 0;
delay(1);

}

//»ñÈ¡ack
bit I2c_getAck(void)
{
bit ack;
SDA = 1;
SCL = 1;
delay(1);
ack = SDA;
SCL = 0;
return ack;
}

uchar I2c_read()
{
uchar i,dat=0;
SDA=1;
delay(1);
for(i=0;i<8;i++)
{
SCL=1;
delay(1);
dat<<=1;
dat|=SDA;
delay(1);
SCL=0;
}
return dat;
}

void I2c_write(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
SDA=dat>>7;
dat<<=1;
delay(1);
SCL=1;
delay(1);
SCL=0;
delay(1);
}
I2c_getAck();
}

void I2c_toDevice(uchar deviceAdd,uchar datAdd,uchar dat)
{
I2c_start();
I2c_write(deviceAdd);
I2c_write(datAdd);
I2c_write(dat);
I2c_stop();
}
uchar I2c_fromDevice(uchar deviceAdd,uchar datAdd  )
{
uchar dat;
I2c_start();
I2c_write(deviceAdd);
I2c_write(datAdd);
I2c_start();
I2c_write(deviceAdd+1);
dat=I2c_read();
I2c_sendAck(1);
I2c_stop();
return dat;
}

void main()
{
uchar num;
I2c_toDevice(0xa0,3,7);
delay(130);
num=I2c_fromDevice(0xa0,3);
while(1)
{
P0=0x00;
P1=duan[num];
delay(10);
P1=0x00;
}

}

8、注意事项

1)关闭I2c和启动I2c之间要有1ms间隔,给IO口准备时间,否则乱码。

2)关于应答,当写数据时由设备应答,读数据时MCU应答。

3)读数据时启动两次I2c。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: