#include "./head/Head.h"
#include <intrins.h>
#define OP_READ 0xa1 // 器件地址以及读取操作
#define OP_WRITE 0xa0 // 器件地址以及写入操作
#define MAX_ADDR 0x7f // AT24C02最大地址
#define ACK 0
#define NACK 1
sbit SDA = P1^0;
sbit SCL = P1^1;
void I2C_Start();
void I2C_Stop();
unsigned char I2C_Shift_In(void);
uchar I2C_Shift_Out(unsigned char write_data);
unsigned char Eeprom_Read_Random(unsigned char random_addr,uchar RdData);
uchar Eeprom_Write_Byte( unsigned char addr, unsigned char write_data);
uchar Eeprom_Write_Page(uchar Addr,uchar *pWrData,uchar Len);
void delay_i2c(unsigned char ms);
uchar Eeprom_Read_Sequential(uchar Addr,uchar *RdBuf,uchar Len);
static void SomeNop(void)
{
uchar n;
for(n=0;n<30;n++)
_nop_();
}
/*---------------------------------------------------------
---------------------------------------------------------*/
void I2C_ACK(void)
{
SDA = 0;
SomeNop();
SCL = 1;
SomeNop();
SCL = 0;
_nop_();
SDA = 1;
}
void I2C_NACK(void)
{
SDA = 1;
SomeNop();
SCL = 1;
SomeNop();
SCL = 0;
SomeNop();
}
/*---------------------------------------------------------
---------------------------------------------------------*/
void I2C_Start()
// 开始位
{
SDA = 1;
SomeNop();
SCL = 1;
SomeNop();
SDA = 0;
SomeNop();
SCL = 0;
SomeNop();
}
/*---------------------------------------------------------
---------------------------------------------------------*/
void I2C_Stop()
{
SCL = 0;
SomeNop();
SDA = 0;
SomeNop();
SCL = 1;
SomeNop();
SDA = 1;
}
/*---------------------------------------------------------
// 从AT24Cxx移入数据到MCU
---------------------------------------------------------*/
unsigned char I2C_Shift_In(void)
{
unsigned char i,read_data;
SomeNop();
for(i = 0; i < 8; i++)
{
SCL = 1; SomeNop();
read_data <<= 1;
read_data |= (unsigned char)SDA;
SCL = 0; SomeNop();
}
return(read_data);
}
/*---------------------------------------------------------
// 从MCU移出数据到AT24Cxx
---------------------------------------------------------*/
uchar I2C_Shift_Out(unsigned char write_data)
{
unsigned char i;
uchar ack_bit;
SomeNop();
for(i = 0; i < 8; i++) // 循环移入8个位
{
SDA = (bit)(write_data & 0x80);
SomeNop();
SCL = 1;
SomeNop();
SCL = 0;
write_data <<= 1;
SomeNop();
}
SDA = 1; //应答已出现在数据线上,释放数据线
SomeNop();
SCL = 1;
SomeNop(); //应答信号应在此SCL为高电平期间保持稳定
ack_bit = SDA;
SCL = 0;
SomeNop();
return ack_bit; // 返回AT24Cxx应答位
}
/*---------------------------------------------------------
// 在指定地址addr处写入数据write_data
---------------------------------------------------------*/
uchar Eeprom_Write_Byte(unsigned char addr, unsigned char write_data)
{
I2C_Start();
if(NACK == I2C_Shift_Out(OP_WRITE))
return FALSE;
if(NACK == I2C_Shift_Out(addr))
return FALSE;
if(NACK == I2C_Shift_Out(write_data))
return FALSE;
I2C_Stop();
delay_i2c(255); // 写入周期
return TRUE;
}
/*---------------------------------------------------------
---------------------------------------------------------*/
uchar Eeprom_Write_Page(uchar Addr,uchar *pWrData,uchar Len)
{
unsigned char i;
I2C_Start();
if(NACK == I2C_Shift_Out(OP_WRITE))
return FALSE;
if(NACK == I2C_Shift_Out(Addr))
return FALSE;
for(i = 0; i < Len; i++)
{
if(NACK == I2C_Shift_Out(*pWrData++))
return FALSE;
delay_i2c(255); // 写入周期
}
I2C_Stop();
delay_i2c(255);
return TRUE;
}
/*---------------------------------------------------------
// 在当前地址读取
---------------------------------------------------------*/
unsigned char Eeprom_Read_Current(uchar RdData)
{
I2C_Start();
if(NACK == I2C_Shift_Out(OP_READ))
return FALSE;
RdData = I2C_Shift_In();
I2C_NACK();
I2C_Stop();
return TRUE;
}
/*---------------------------------------------------------
// 在指定地址读取
---------------------------------------------------------*/
unsigned char Eeprom_Read_Random(unsigned char random_addr,uchar RdData)
{
I2C_Start();
if(NACK == I2C_Shift_Out(OP_WRITE))
return FALSE;
if(NACK == I2C_Shift_Out(random_addr))
return FALSE;
if(FALSE == Eeprom_Read_Current(RdData))
return FALSE;
return TRUE;
}
/*---------------------------------------------------------
---------------------------------------------------------*/
uchar Eeprom_Read_Sequential(uchar Addr,uchar *RdBuf,uchar Len)
{
I2C_Start();
if(NACK == I2C_Shift_Out(OP_WRITE)) //a0
return FALSE;
if(NACK == I2C_Shift_Out(Addr))
return FALSE;
I2C_Start();
if(NACK == I2C_Shift_Out(OP_READ))
return FALSE;
while(Len)
{
*RdBuf++ = I2C_Shift_In();
Len--;
if(Len == 0)
I2C_NACK();
else
I2C_ACK();
}
/*
for(n=0;n<Len;n++) //哈哈,一字之差害我找了好久!
{
*RdBuf++ = I2C_Shift_In();
if(n==Len)
I2C_NACK();
else
I2C_ACK();
} */
I2C_Stop();
return TRUE;
}
/*---------------------------------------------------------
//i=220,延时68us
//i=250,延时76us
//i=164,延时50.4us
---------------------------------------------------------*/
void delay_i2c(unsigned char n)
// 延时子程序
{
unsigned char i;
while(n--)
{
for(i = 0; i < 164; i++);
}
}
C8051F340,48M系统时钟.I2C时钟速度大概35K左右.奉献给楼主拉! |