本人小白一枚,在此记录STC89C51单片机与AT24C02通过IIC方式通讯。
用到的IIC非高速,采用5us延时;emm...主要细节在读取从机应答,以及发送完数据需要拉低时钟线SCL,拉高数据线SDA以允许AT24C02来产生应答信号。详细见注释
#ifndef IIC
#define IIC
#include "reg52.h"
void Delay5us();
void START();
void STOP();
void READ_ACK();
void SEND_ACK(bit i);
void SEND_DATA(unsigned char Data);
unsigned char READ_DATA();
void AT24C02_WRITE(unsigned char Addr,unsigned char Data);
unsigned char AT24C02_READ(unsigned char Addr);
#endif
#include "iic.h"
sbit SCL = P2^1;
sbit SDA = P2^0;
void Delay5us() //@11.0592MHz
{
}
void START() //起始信号
{
SCL = 1;
SDA = 1;
Delay5us();
SDA = 0;
Delay5us();
}
void STOP() //停止信号
{
/*****/
//避免停止信号前面的起始信号
SCL = 0;
SDA = 0;
/*****/
SCL = 1;
Delay5us();
SDA = 1;
Delay5us();
}
void READ_ACK() //读从机应答
{
SCL = 1; //读取应答信号
Delay5us();
SCL = 0; //允许从机释放数据线
}
void SEND_ACK(bit i) //主机发送应答
{
SCL = 0;
SDA = i;
SCL = 1;
Delay5us();
}
void SEND_DATA(unsigned char Data) //发送8位数据
{
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 0;
Delay5us();
SDA = (Data<<i) & 0x80;
SCL = 1;
Delay5us();
}
SCL = 0;//拉低时钟线,允许从机应答拉低时钟线
SDA = 1;//拉高数据线,等待从机应答
}
unsigned char READ_DATA() //接收8位数据
{
unsigned char i,Data;
for(i=0;i<8;i++)
{
SCL = 0;
Delay5us();
Data = SDA | (Data<<1);
SCL = 1;
Delay5us();
}
return Data;
}
void AT24C02_WRITE(unsigned char Addr,unsigned char Data) //写入AT24C02
{
START();
SEND_DATA(0xa0);
READ_ACK();
SEND_DATA(Addr);
READ_ACK();
SEND_DATA(Data);
READ_ACK();
STOP();
}
unsigned char AT24C02_READ(unsigned char Addr) //读出AT24C02
{
unsigned char Data;
START();
SEND_DATA(0xa0);
READ_ACK();
SEND_DATA(Addr);
READ_ACK();
START();
SEND_DATA(0xa1);
READ_ACK();
Data = READ_DATA();
SEND_ACK(1);
STOP();
return Data;
}
主函数:
#include "reg52.h"
#include "seg.h"
#include "iic.h"
void Delay100ms() //@11.0592MHz
{
unsigned char i, j;
i = 180;
j = 73;
do
{
while (--j);
} while (--i);
}
void main()
{
unsigned char i;
AT24C02_WRITE(2,66);
Delay100ms();
i = AT24C02_READ(2);
while(1)
{
SEG_(i);
}
}
读取到的写入与写出时序如下:
写入时序:
读出时序:
其中发送数据函数中的:SDA = (Data<<i) & 0x80语句执行时间较长,在图中体现在写入数据时SCL为低。