天天

【原】发个模拟I2C代码!

0
阅读(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 WP_OPEN()  P1_3=1
#define WP_CLOSE() P1_3=0
#define WRITE_ADDR 0x0A0 //定义器件在I2C总线中的写地址
#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_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;
 }
}
//从EEPROM中读出8个bit 
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();
}
//-----写入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();
}
//----------从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;
}