51单片机开发——I2C通信接口
I2C是微电子通信控制领域广泛采用的一种总线标准。
起始和停止信号:
void iic_start(void)
{
IIC_SDA=1;//如果把该条语句放在SCL后面,第二次读写会出现问题
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SDA=0; //当SCL为高电平时,SDA由高变为低
delay_10us(1);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
delay_10us(1);
}
void iic_stop(void)
{
IIC_SDA=0;//如果把该条语句放在SCL后面,第二次读写会出现问题
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SDA=1; //当SCL为高电平时,SDA由低变为高
delay_10us(1);
}
应答和非应答:
void iic_ack(void)
{
IIC_SCL=0;
IIC_SDA=0; //SDA为低电平
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SCL=0;
}
void iic_nack(void)
{
IIC_SCL=0;
IIC_SDA=1; //SDA为高电平
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SCL=0;
}
等待应答:
u8 iic_wait_ack(void)
{
u8 time_temp=0;
IIC_SCL=1;
delay_10us(1);
while(IIC_SDA) //等待SDA为低电平
{
time_temp++;
if(time_temp>100)//超时则强制结束IIC通信
{
iic_stop();
return 1; //未应答
}
}
IIC_SCL=0;
return 0; //应答
}
读写数据:
SCL低电平时数据可以改变,数据按照从高到低的顺序传输。
void iic_write_byte(u8 dat)
{
u8 i=0;
IIC_SCL=0;
for(i=0;i<8;i++) //循环8次将一个字节传出,先传高再传低位
{
if((dat&0x80)>0)
IIC_SDA=1;
else
IIC_SDA=0;
dat<<=1;
delay_10us(1);
IIC_SCL=1;
delay_10us(1);
IIC_SCL=0;
delay_10us(1);
}
}
u8 iic_read_byte(u8 ack)
{
u8 i=0,receive=0;
for(i=0;i<8;i++ ) //循环8次将一个字节读出,先读高再传低位
{
IIC_SCL=0;
delay_10us(1);
IIC_SCL=1;
receive<<=1;
if(IIC_SDA)receive++;
delay_10us(1);
}
if (!ack)
iic_nack();
else
iic_ack();
return receive;
}
数据传输:
从机地址:
开发板上使用的是 AT24C02(EEPROM) 芯片,此芯片具有 I2C 通信接口,芯片内保存的数据在掉电情况下都不丢失。
void at24c02_write_one_byte(u8 addr,u8 dat)
{
iic_start();
iic_write_byte(0XA0); //发送写命令
iic_wait_ack();
iic_write_byte(addr); //发送写地址
iic_wait_ack();
iic_write_byte(dat); //发送字节
iic_wait_ack();
iic_stop(); //产生一个停止条件
delay_ms(10);
}
u8 at24c02_read_one_byte(u8 addr)
{
u8 temp=0;
iic_start();
iic_write_byte(0XA0); //发送写命令
iic_wait_ack();
iic_write_byte(addr); //发送写地址
iic_wait_ack();
iic_start();
iic_write_byte(0XA1); //进入接收模式
iic_wait_ack();
temp=iic_read_byte(0); //读取字节
iic_stop(); //产生一个停止条件
return temp; //返回读取的数据
}