简介
I2C(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备(特别是外部存储器件)。
与UART的区别
u异步通信:只负责发送
i同步通信:SCL时钟负责收发双方的时钟节拍,SDA数据线负责传输数据
u:多用于板间通信
i:板内通信
I2C通信时序
分为起始信号、数据传输部分和停止信号
(1)起始信号
SCL为高电平期间,SDA由高变低
(2)数据传输
UART:低位在前,高位在后。由固定的波特率
I2C:高位在前,低位在后。无波特率要求,但是要符合时序图
要求:SCL低电平,允许改变SDA。SCL为高电平的时候,SDA不可以变化
数据位最后一位为ACK,应答位。
数据传输部位对字节数没有限制,但是每一位字节后面需要跟一位应答位
(3)停止信号
UART:固定高电平信号
I2C:SCL为高电平期间,SDA由低变高
寻址模式
发送完起始信号后,发送从机地址,地址有7位,第8位为数据方向位(R/W)
1为读,0为写
如果发送地址存在,该地址器件会回应一个ACK,(拉低电平输出0),否则,SDA保持高电平回应1。
//I2C.c文件
#include <reg52.h>
#include <intrins.h>
#define I2CDelay(){_nop_();_nop_();_nop_();_nop_();} //一个_nop_()为一个机器周期
sbit I2C_SCL=P3^7;
sbit I2C_SDA=P3^6;
void I2CStart()//产生起始信号
{
I2C_SDA=1;
I2C_SCL=1;
I2CDelay();
I2C_SDA=0;
I2CDelay();
I2C_SCL=0;
}
void I2CStop() //产生结束信号
{
I2C_SCL=0;
I2C_SDA=0;
I2CDelay();
I2C_SCL=1;
I2CDelay();
I2C_SDA=1;
I2CDelay();
}
bit I2CWrite(unsigned char dat) //写操作,返回值为从机应答位值
{
bit ack;
unsigned char mask;
for(mask=0x80;mask!=0;mask>>=1) //从高位到低位发送数据位
{
if((mask&dat)==0)
I2C_SDA=0;
else
I2C_SDA=1;
I2CDelay();
I2C_SCL=1;
I2CDelay();
I2C_SCL=0;
}
I2C_SDA=1; //发送完数据位将这个电平拉高,检测应答位
I2CDelay();
I2C_SCL=1;
ack=I2C_SDA;
I2CDelay();
I2C_SCL=0;
return (~ack);//进行取反以符合正常的逻辑
}
//读操作,并发送非应答信号,返回值为读到的字节
unsigned char I2CReadNAK() //从高位到低位进行读取
{
unsigned char mask;
unsigned char dat;
I2C_SDA=1;
for(mask=0x80;mask!=0;mask>>=1)
{
I2CDelay();
I2C_SCL=1;//拉高SCL
if(I2C_SDA==0)//为0对应位为0
dat&=~mask;
else
dat|=mask;//为1对应位为1
I2CDelay();
I2C_SCL=0;
}
I2C_SDA=1;
I2CDelay();
I2C_SCL=1;
I2CDelay();
I2C_SCL=0;
return dat;
}
unsigned char I2CReadACK()//读操作,并发送应答信号,就可以继续往下读取
{
unsigned char mask;
unsigned char dat;
I2C_SDA=1;
for(mask=0x80;mask!=0;mask>>=1)
{
I2CDelay();
I2C_SCL=1;//拉高SCL
if(I2C_SDA==0)//为0对应位为0
dat&=~mask;
else
dat|=mask;//为1对应位为1
I2CDelay();
I2C_SCL=0;
}
I2C_SDA=0;
I2CDelay();
I2C_SCL=1;
I2CDelay();
I2C_SCL=0;
return dat;
}
//检查地址为ADDR的器件是否存在,返回值为器件应答值
bit I2CAddressing(unsigned char addr)
{
bit ack;
I2CStart();
ack=I2CWrite(addr<<1); //左移一位,最低位需要表示读或写
I2CStop();
return ack;
}