目录
1.IIC的介绍
1.IIC总线有两条串行线,其一是时钟线SCK(同步),其二是数据线SDA(一条数据线半双)。应用中,单片机常常作为主机,外围器件(外部存储)可以挂载多个。每一个从机器件都拥有唯一的一个地址。要查看从机手册找到这个唯一地址。一般还需要自行配置芯片管脚上的高低电平,来实现确定从机地址的目的。硬件设计上,SCK线和SDA线通过典型的4.7K电阻进行上拉,保证两条线空闲时保持高电平状态。如图:
IIC组成线与的关系,任何一个器件都可以拉低电平。有起始信号、数据传输、停止信号。
2.IIC传输一个字节的时序图
1.IIC的起始信号
在SCL=1,SDA=1。经过一段时间SDA=0。产生下降沿说明有起始信号。
#include<intrins.h>
#define I2Cdelay() {_nop_();_nop_();_nop_();_nop_();} 延时函数
void I2Cstart()
{
SCL=1;
SDA=1;
I2Cdelay();
SDA=0; //下降沿
I2Cdelay();
SCL=0; //SCL=0 才可以改变数据
}
2.IIC的停止信号
在SCL=0、SDA=0。。SCL=1产生。经过一段时间SDA=1上升沿。说明停止信号到来。
oid I2CStop()
{
SCL=0;
SDA=0;
I2Cdelay();
SCL=1;
I2Cdelay();
SDA=1; //上升沿
I2Cdelay();
}
3.IIC的写字节
每写完一个字节。从机都会发送一个应答信号ack 如果是0表示成功,否则失败。
bit I2Cwrite(unsigned char data)
{
bit ack;
unsigned char bitDate;
for(bitDate=0x80;bitDate!=0;bitDate>>=1)
{
if(bitDate&data) //先写高位 次低位
{
SDA=1;
}
else
{
SDA=0;
}
I2Cdelay();
SCL=1; //接收方在SCL=1 会来读取数据
I2Cdelay();
SCL=0; //SCL=1 让其为写下一位做准备
}
SDA=1; //释放总线
I2Cdelay();
SCL=1; //看时序图SCL=1
ack=SDA; //从机发送给主机应答信号
I2Cdelay();
SCL=0; //看时序图SCL=0
return ack;
}
4.IIC的读字节
当读完一个字节。如果主机还想读就发送ACK信号0。 如果不想读就发送NACK信号1。所以读的方式有两种。
读NACK信号
unsigned char I2CreadNAk()
{
unsigned char bitDate;
unsigned char date;
SDA=1;//首先确保释放主机 开始读取数据
for(bitDate=0x80;bitDate!=0;bitDate>>=1)
{
I2Cdelay();
SCL=1;
if(SDA) //SDA=1
{
date|=bitDate;
}
else //SDA=0
{
date&=~bitDate;
}
I2Cdelay();
SCL=0;
}
SDA=1; //非应答(主机发送1)信号 只读一个字节
I2Cdelay();
SCL=1; //在SCL=1 读取主机的非应答信号
I2Cdelay();
SCL=0;
return date;
}
读ACK信号
unsigned char I2CreadACK()
{
unsigned char bitDate;
unsigned char date;
SDA=1;//首先确保释放主机
for(bitDate=0x80;bitDate!=0;bitDate>>=1)
{
I2Cdelay();
SCL=1;
if(SDA)
{
date|=bitDate;
}
else
{
date&=~bitDate;
}
I2Cdelay();
SCL=0;
}
SDA=0; //应答信号 不只读一个字节(要读多个)
I2Cdelay();
SCL=1; //SCL=1 读取主机发送的应答信号
I2Cdelay();
SCL=0;
return date;
}
3.EEPROM(24c02)
1.EEPROM的介绍
指带电可擦可编程只读存储器。是一种掉电后数据不丢失的存储芯片(在运行时可以改变数据,而在掉电后不能改变数据),可以重复擦写30w~100w次。可以保持100年。(比如电表就有利用EEPROM在运行时不断改变度数。当停电了数据不会改变)EEPROM就是一个器件。而IIC只是一个协议。
2.IIC对EEPROM单字节的写操作
具体的步骤
- IIC的起始信号 EEPROM器件唯一的地址(7位+读写1位)
- 发送写入到EEPROM的哪个地址里。
- 发送数据字节(这里只发送一字节)
- IIC的停止信号
void writeEEPROM(unsigned char addr,date)
{
I2Cstart(); //IIC的起始信号
I2Cwrite(0x50<<1); //EEPROM的地址(七位)+读写位(1位) 左移一位是让最低位为0(代表写)
I2Cwrite(addr); //我要写到EEPROM哪个地址(因为EEPROM有256个字节)
I2Cwrite(date); //写入数据到上一步指定数据
I2CStop(); //IIC的停止信号
}
总结:每写完一个字节,从机都会发送一个应答信号0,表示我收到了。否则失败。在每写完一个字节EEPROM的地址都会自动的加一,如果超过范围就会溢出。
3.对EEPROM单字节的读操作
具体的步骤
- IIC的起始信号 EEPROM器件唯一的地址(7位+读写1位)写
- 发送读取EEPROM的哪个地址里数据
- 重新发送IIC的起始信号EEPROM器 件唯一的地址(7位+读写1位)读
- IIC的停止信号
unsigned char readEEPROM(unsigned char addr)
{
unsigned char date;
I2Cstart();
I2Cwrite(0x50<<1);
I2Cwrite(addr);
I2Cstart();
I2Cwrite((0x50<<1)|0x01); //先左移一位,或上0x01 把最低位置1
date=I2CreadNAk();
I2CStop();
return date;
}
总结:在前三步中每一个字节都是在写,因此都会回应一个应答信号0。读取器件的数据,每读一个字节。如果还想读主机发应答位。如果不想读主机非应答。并且每读一字节从机地址都是自增的。
4.EEPROM的总结
- 在单片机控制EEPROM中MCU都是主机、EEPROM都是从机。
- 无论读写时钟信号都是由MCU产生。
- 在写的时候应答信号由从机发送给主机,而在读的时候应答信号由主机发给从机。