【原】发个模拟I2C代码!
0赞
发表于 9/28/2011 7:42:08 PM
阅读(4214)
前几天说了下I2C的问题,博友说发个来参考,现在发上来一起共勉下,时序基本没问题,该代码也在我的板上运行过了
平台移植的话主要关注下延迟多少。
#define SCL P1_0
#define SDA P1_1
#define WP P1_3
#define SDA_OUT() DDRP1|=0X02 //输出
#define SDA_IN() DDRP1&=~0X02 //输入
#define SDA_IN() DDRP1&=~0X02 //输入
#define WP_OPEN() P1_3=1
#define WP_CLOSE() P1_3=0
#define WP_CLOSE() P1_3=0
#define WRITE_ADDR 0x0A0 //定义器件在I2C总线中的写地址
#define READ_ADDR 0x0A1 //定义器件在I2C总线中的读地址
#define I2C_DELAY 5 //需根据时钟来确定该延迟多少
#define READ_ADDR 0x0A1 //定义器件在I2C总线中的读地址
#define I2C_DELAY 5 //需根据时钟来确定该延迟多少
//延时子程序
void I2C_delay(u8 i)
{
while(--i);
}
//I2C开始
void I2C_start()
{
SDA=1;
SCL=1;
I2C_delay(I2C_DELAY);
SDA=0;
I2C_delay(I2C_DELAY);
SCL=0;
I2C_delay(I2C_DELAY);
}
//I2C结束
void I2C_stop()
{
SDA=0;
SCL=1;
I2C_delay(I2C_DELAY);
SDA=1;
I2C_delay(I2C_DELAY);
SDA=0;
SCL=0;
}
//发送应答位信号
void I2C_sendACK()
{
SDA=1;
SCL=1;
I2C_delay(I2C_DELAY);
SDA=1;
SCL=0;
}
void I2C_stop()
{
SDA=0;
SCL=1;
I2C_delay(I2C_DELAY);
SDA=1;
I2C_delay(I2C_DELAY);
SDA=0;
SCL=0;
}
//发送应答位信号
void I2C_sendACK()
{
SDA=1;
SCL=1;
I2C_delay(I2C_DELAY);
SDA=1;
SCL=0;
}
//发送非应答位信号
void I2C_sendNACK()
{
SDA=1;
SCL=1;
I2C_delay(I2C_DELAY);
SDA=0;
SCL=0;
}
//检测从机应答信号
bit I2C_checkACK()
{
bit flag;
SDA=1;
SCL=1;
SDA_IN(); //配置SDA输入模式
I2C_delay(I2C_DELAY);
flag=SDA;
SDA_OUT(); //配置SDA输出模式
SCL=0;
return(flag);
}
//--------写一个字节
void I2C_Write8bit(u8 input)
{
u8 temp;
void I2C_sendNACK()
{
SDA=1;
SCL=1;
I2C_delay(I2C_DELAY);
SDA=0;
SCL=0;
}
//检测从机应答信号
bit I2C_checkACK()
{
bit flag;
SDA=1;
SCL=1;
SDA_IN(); //配置SDA输入模式
I2C_delay(I2C_DELAY);
flag=SDA;
SDA_OUT(); //配置SDA输出模式
SCL=0;
return(flag);
}
//--------写一个字节
void I2C_Write8bit(u8 input)
{
u8 temp;
for(temp=0;temp<8;temp++)
{
SDA=(bit)(input&0x80);
SCL=1;
I2C_delay(I2C_DELAY);
SCL=0;
input=input<<1;
}
}
{
SDA=(bit)(input&0x80);
SCL=1;
I2C_delay(I2C_DELAY);
SCL=0;
input=input<<1;
}
}
//从EEPROM中读出8个bit
u8 I2C_Read8bit()
{
u8 temp,rbyte;
u8 I2C_Read8bit()
{
u8 temp,rbyte;
rbyte = 0;
for(temp=0;temp<8;temp++)
{
SDA=1;
SCL=1;
SDA_IN(); //配置SDA输入模式
rbyte=rbyte|((u8)(SDA));
if(temp<7) //注意:仅左移7次
{
rbyte=rbyte<<1;
}
SDA_OUT(); //配置SDA输入模式
SCL=0;
}
return(rbyte);
}
//-------------------------------------------------------外部调用函数
//-----写入一个字节到EEPROM中
void I2C_WriteByte(u8 ch,u16 address)
{
I2C_start();
I2C_Write8bit(WRITE_ADDR);
while(I2C_checkACK());
I2C_Write8bit(address/256);
while(I2C_checkACK());
I2C_Write8bit(address%256);
while(I2C_checkACK());
I2C_Write8bit(ch);
while(I2C_checkACK());
I2C_stop();
}
for(temp=0;temp<8;temp++)
{
SDA=1;
SCL=1;
SDA_IN(); //配置SDA输入模式
rbyte=rbyte|((u8)(SDA));
if(temp<7) //注意:仅左移7次
{
rbyte=rbyte<<1;
}
SDA_OUT(); //配置SDA输入模式
SCL=0;
}
return(rbyte);
}
//-------------------------------------------------------外部调用函数
//-----写入一个字节到EEPROM中
void I2C_WriteByte(u8 ch,u16 address)
{
I2C_start();
I2C_Write8bit(WRITE_ADDR);
while(I2C_checkACK());
I2C_Write8bit(address/256);
while(I2C_checkACK());
I2C_Write8bit(address%256);
while(I2C_checkACK());
I2C_Write8bit(ch);
while(I2C_checkACK());
I2C_stop();
}
//-----写入N个字节到EEPROM中
void I2C_WriteNByte(u16 address,u8 len,u8 *dat)
{
I2C_start();
I2C_Write8bit(WRITE_ADDR);
while(I2C_checkACK());
I2C_Write8bit(address/256);
while(I2C_checkACK());
I2C_Write8bit(address%256);
while(I2C_checkACK());
while(len)
{
I2C_Write8bit(*dat);
while(I2C_checkACK());
len--;dat++;
}
I2C_stop();
}
void I2C_WriteNByte(u16 address,u8 len,u8 *dat)
{
I2C_start();
I2C_Write8bit(WRITE_ADDR);
while(I2C_checkACK());
I2C_Write8bit(address/256);
while(I2C_checkACK());
I2C_Write8bit(address%256);
while(I2C_checkACK());
while(len)
{
I2C_Write8bit(*dat);
while(I2C_checkACK());
len--;dat++;
}
I2C_stop();
}
//----------从EEPROM中读出1个字节
u8 I2C_ReadByte(u16 address)
{
u8 ch;
I2C_start();
I2C_Write8bit(WRITE_ADDR);
while(I2C_checkACK());
I2C_Write8bit(address/256);
while(I2C_checkACK());
I2C_Write8bit(address%256);
while(I2C_checkACK());
I2C_start();
I2C_Write8bit(READ_ADDR);
while(I2C_checkACK());
ch=I2C_Read8bit();
I2C_sendNACK();
I2C_stop();
return(ch);
}
//----------从EEPROM中读出N个字节
void I2C_ReadNByte(u16 address,u8 len,u8 *dat)
{
I2C_start();
I2C_Write8bit(WRITE_ADDR);
while(I2C_checkACK());
I2C_Write8bit(address/256);
while(I2C_checkACK());
I2C_Write8bit(address%256);
while(I2C_checkACK());
I2C_start();
I2C_Write8bit(READ_ADDR);
while(I2C_checkACK());
len=len-1;
while(len)
{
*dat=I2C_Read8bit();
I2C_sendACK();
len--;
dat++;
}
*dat=I2C_Read8bit();
I2C_sendNACK();
I2C_stop();
//return 1;
}
u8 I2C_ReadByte(u16 address)
{
u8 ch;
I2C_start();
I2C_Write8bit(WRITE_ADDR);
while(I2C_checkACK());
I2C_Write8bit(address/256);
while(I2C_checkACK());
I2C_Write8bit(address%256);
while(I2C_checkACK());
I2C_start();
I2C_Write8bit(READ_ADDR);
while(I2C_checkACK());
ch=I2C_Read8bit();
I2C_sendNACK();
I2C_stop();
return(ch);
}
//----------从EEPROM中读出N个字节
void I2C_ReadNByte(u16 address,u8 len,u8 *dat)
{
I2C_start();
I2C_Write8bit(WRITE_ADDR);
while(I2C_checkACK());
I2C_Write8bit(address/256);
while(I2C_checkACK());
I2C_Write8bit(address%256);
while(I2C_checkACK());
I2C_start();
I2C_Write8bit(READ_ADDR);
while(I2C_checkACK());
len=len-1;
while(len)
{
*dat=I2C_Read8bit();
I2C_sendACK();
len--;
dat++;
}
*dat=I2C_Read8bit();
I2C_sendNACK();
I2C_stop();
//return 1;
}
