I2C——24C02
I2C:
1.I2C传数据先传高bit位,丛机收到数据后,若有应答,第9个时钟高电平期间,需要把SDA拉低。
2.I2C主机接收数据,若有应答,第9个时钟高电平期间,需要把SDA拉低。
3.起始信号后必须传送一个从机的地址(7位),第8位是数据的传送方向位(R/T),用“0”表示主机发送数据(T),“1”表示主机接收数据(R)
4.24c02先关的时序要求:
测试能正常工作的程序:
#include <reg52.h>
//stdio.h,string.h用于printf函数原型
#include <stdio.h>
typedef unsigned int u16;
typedef unsigned char u8;
sbit scl = P2^1;
sbit sda = P2^0;
void delay10us(void)
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=2;a>0;a--);
}
//scl=0 sda=0
void i2c_start(void)
{
sda = 1;
delay10us();
scl = 1;
delay10us();
sda = 0;
delay10us();
scl = 0;
delay10us();
}
//scl=1 sda=1 表示总线空闲
void i2c_stop(void)
{
sda = 0;
delay10us();
scl = 1;
delay10us();
sda = 1;
delay10us();
}
//发送完一个字节SCL=0,SDA=1
u8 i2c_send_byte(u8 dat)
{
u8 i = 0;
u8 timeout = 0;
for (i=0; i<8; i++)
{
sda = dat >> 7;
dat <<= 1;
delay10us();
scl = 1;
delay10us(); //建立时间>4.7us
scl = 0;
delay10us(); //时间大于4us
}
sda = 1;
delay10us();
scl = 1;
delay10us();
while (sda)
{
timeout++;
//如果超过2000us没有应答发送失败,或者为非应答,表示接收结束
if (timeout > 200)
{
scl = 0;
delay10us();
return 0;
}
}
scl = 0;
delay10us();
return 1;
}
u8 i2c_read_byte(void)
{
u8 dat = 0;
u8 i = 0;
delay10us();
for (i=0; i<8; i++)
{
scl = 1;
delay10us();
dat <<= 1;
dat |= sda;
delay10us();
scl = 0;
delay10us();
}
sda = 1;
delay10us();
scl = 1;
delay10us();
scl = 0;
return dat;
}
void at24c02_write(u8 addr, u8 dat)
{
i2c_start();
i2c_send_byte(0xa0);
i2c_send_byte(addr);
i2c_send_byte(dat);
i2c_stop();
}
u8 at24c02_read(u8 addr)
{
u8 dat = 0;
i2c_start();
i2c_send_byte(0xa0);
i2c_send_byte(addr);
i2c_start();
i2c_send_byte(0xa1);
dat = i2c_read_byte();
i2c_stop();
return dat;
}
void uart_init(void)
{
//波特率:4800
//设置为工作方式1
SCON=0X50;
//设置定时器工作方式2
TMOD=0X20;
//波特率加倍
PCON=0X80;
//计数器初始值设置,注意波特率是4800的
TH1=0XF3;
TL1=0XF3;
//串行口中断允许位(这个是包含串口的接收和发送中断的)
ES=1;
//打开总中断
EA=1;
//打开计数器
TR1=1;
TI=1;//直接使用printf必须加入此句才能实现发送
}
/*大概delay 1ms左右*/
void delay(unsigned int z)
{
unsigned int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
int main(void)
{
u8 dat = 0;
uart_init();
while (1)
{
at24c02_write(1, 'k');
delay(1000);
dat = at24c02_read(1);
printf("read: %c\n", dat);
delay(1000);
}
return 0;
}