STM32使用IIC拓展EEPROM(AT24C02)
1. IIC的使用
- 时序图:
- 起始操作
从上面的时序图可以得出,IIC协议的开始标志为:在SCL为低电平时将SDA拉高
对应代码:
void IIC_Start()
{
SDA_OUT();
IIC_SDA=1; IIC_SCL=1;
delay_us(4);
IIC_SDA=0; //开始信号
delay_us(4);
IIC_SCL=0; //准备发送信号或者接收数据
}
- 终止操作
在 SCL为高电平时将 SDA拉低
对应代码:
void IIC_Stop()
{
SDA_OUT();
IIC_SCL=0; IIC_SDA=0;
delay_us(4);
IIC_SCL=1;
IIC_SDA=1; //结束信号
delay_us(4);
}
- 发送应答
当发送器发送完一个字节的数据后,由接收器对发送器发送的数据进行反馈. 当接收器的反馈为低电平时表示 成功接受, 当接收器的反馈为 高电平时表示 接收没有成功.
代码:
void IIC_Ack() //产生ACK应答
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
void IIC_NAck() //不产生ACK应答
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
- 等待应答
当发送器发送完一个字节的数据后,对接收器的反馈进行判定.根据SDA线进行判定
代码:
u8 IIC_Wait_Ack()
{
u8 ucErrTime=0;
SDA_IN(); //设置为输入
IIC_SDA=1; delay_us(1);
IIC_SCL=1; delay_us(1);
while (Read_SDA)
{
ucErrTime++;
if (ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0; //时钟输出0
return 0;
}
- 发送数据与读取数据
在IIC收发数据时,在时钟信号为高电平期间,数据线的数据必须保持稳定, 只有在时钟线上的信号为低电平期间,数据线山的高电平或低电平状态才可以变化. 一般在SCL的上升沿到来之前就开始将SDA的数据进行变化,并在SDA下降沿之后SDA变化结束
发送代码:
void IIC_Send_Byte(u8 dat) //IIC发送一个字节的数据
{
u8 t;
SDA_OUT();
IIC_SCL=0; //拉低时钟开始数据传输
for (t=0;t<8;t++)
{
IIC_SDA=(dat&0x80)>>7; //从数据的最高位开始传输
dat<<=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
读取代码:
u8 IIC_Read_Byte(unsigned char ack) //IIC读取一个字节的数据并发送应答; ack=1时发送ACK, ack=0时发送NACK
{
unsigned char i, receive=0;
SDA_IN(); //设置为输入
for (i=0;i<8;i++)
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if (Read_SDA)
receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();
else
IIC_Ack();
return receive;
}
2. AT24C02的使用
原理图
首先将芯片按照此电路连接好
然后附上代码:
读操作:
u8 AT24CXX_ReadOneByte(u16 ReadAddr) //从AT24CXX器件读出一个字节数据
{
u8 temp;
IIC_Start();
IIC_Send_Byte(0xA0+((ReadAddr/256)<<1)); //发送器件地址0xA0,写数据
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr%256); //发送低地址
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0xA1); //进入接收模式
IIC_Wait_Ack();
temp = IIC_Read_Byte(0);
IIC_Stop(); //停时
return temp;
}
写操作:
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 WriteData) //向AT24CXX器件写一个字节数据
{
IIC_Start();
IIC_Send_Byte(0xA0+((WriteAddr/256)<<1));
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr%256); //发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(WriteData);
IIC_Wait_Ack();
IIC_Stop();
delay_ms(10);
}