⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 at24c02.c

📁 使用IO口模拟I2C功能 读写I2C设备。
💻 C
字号:
/********************************
  通用AT24CXX操作接口程序 
  本程序适合于AT24C32/64,AT24C128/256等器件
  文件名:at.c
  编译:WinAVR-20070122

  硬件:CA-M8X  
  注:本程序需要I/O模拟或硬件实现的I2C总线接口函数
  
  芯艺设计室 2004-2007  版权所有 
  转载请保留本注释在内的全部内容
  WEB: http://www.chipart.cn
  Email: changfutong@sina.com
*******************************/
#include <avr/io.h>
#include <stdint.h>

#include "twi.h" //i2c接口函数声明处

#define TW_WRITE 0
#define TW_READ  1

#define TW_ACK 1
#define TW_NOACK 0

/*以下两个宏控制AT24CXX的WP引脚,如未连接可定义为空:
  #define EEPROM_WRITE_ENABLE  
  #define EEPROM_WRITE_DISABLE 
  AT24CXX中WP引脚接地时写允许,接电源(高)时写保护,
  如不接,器件内部有接地电阻,即写允许.  */
//在CA-M8X板上该引脚通过S7(3)连接MEGA8的PC3
#define EEPROM_WRITE_ENABLE  PORTC&=~_BV(PC3),DDRC|=_BV(PC3)
#define EEPROM_WRITE_DISABLE PORTC|=_BV(PC3),DDRC|=_BV(PC3)

static uint8_t g_PageSize=0;//页大小(按字节)
static uint8_t g_DeviceAddr=0;//器件地址
static uint8_t g_PageBitCount;//一页所占用的位数(如一页为64字节,则6)

extern char I2CBuffer[64];

/*器件忙检测,原理:器件忙时不会对主机的写操作应答*/
//忙检测接口函数,只有一种情况才需要调用这个函数
//即:当刚写完成,要读数据时
//而连续的读或者写操作之间不需要调用这个函数

void At24cxxWaitBusy(void)
{
  uint8_t i;
  //检测EEPROM是否忙
  while(1)
  {
    TwiStart();
    i=TwiWriteByte(g_DeviceAddr);
    TwiStop();
    if(i==NO_BUSY)
      break;
  }  
  return ;
}


void At24cxxWaitBusy2(uint8_t addr)
{
  uint8_t i;
  //检测EEPROM是否忙
  while(1)
  {
    TwiStart();
    i=TwiWriteByte(addr);
    TwiStop();
    if(i==NO_BUSY)
      break;
  }  
  return ;
}

/* 设置当前操作器件的地址和页大小
device_addr最低位必须为0
只有在使用页访问器件时page_size有用
不使用页访问时可指定page_size为0 */
void At24cxxConfig(uint8_t device_addr,uint8_t page_size)
{
  uint8_t i;
  
  g_DeviceAddr=device_addr;
  g_PageSize=page_size;
  g_PageBitCount=0;
  
  if(page_size==0)
    return ;
  //计算一页所占用位数
  for(i=1;i<10;i++)//不能大于9次
  {
    if(page_size==(1<<i))
    {
      g_PageBitCount=i;
      break;
    }//if
  }//for
}

//AT24CXX通用随机写一字节函数
void At24cxxWriteByte(uint16_t addr,uint8_t dat)
{
  At24cxxWaitBusy();
  EEPROM_WRITE_ENABLE;
  TwiStart();
  TwiWriteByte(g_DeviceAddr );//= |TW_WRITE
  TwiWriteByte(addr>>8);//写地址高字节
  TwiWriteByte(addr);//写地址低字节  
  TwiWriteByte(dat);//写数据字节
  TwiStop();
  EEPROM_WRITE_DISABLE;
}



//AT24CXX通用随机读一字节函数
uint8_t At24cxxReadByte(uint16_t addr)
{
  uint8_t ret;
  
  TwiStart();
  TwiWriteByte(g_DeviceAddr);//写地址
  TwiWriteByte(addr>>8);
  TwiWriteByte(addr);
  
  TwiStart();
  TwiWriteByte(g_DeviceAddr | TW_READ);
  TwiReadByte(&ret,TW_NOACK);//NO ACK
  TwiStop();
  
  return ret;
}

void At24cxxWriteSomeByte(uint16_t device_addr,uint16_t addr,char *buf,uint8_t Size)
{
  uint8_t i;  

  //检测EEPROM是否忙
  At24cxxWaitBusy();
  
  //写一页
  EEPROM_WRITE_ENABLE;
  TwiStart();
  TwiWriteByte(device_addr );//= |TW_WRITE
  TwiWriteByte(addr);//写地址低字节
  
  for(i=0;i<Size;i++)
  {
    TwiWriteByte(I2CBuffer[i]);
	//SendHex(I2CBuffer[i]);
  }
    
  TwiStop();
  EEPROM_WRITE_DISABLE;
}

//AT24CXX通用写页函数,page_index为页地址,即表示第几页
void At24cxxWritePage(uint16_t page_index,uint8_t *buf)
{
  uint8_t i;  
  
  //页索引调整到绝对地址
  page_index<<=g_PageBitCount;
  
  //检测EEPROM是否忙
  At24cxxWaitBusy();
  
  //写一页
  EEPROM_WRITE_ENABLE;
  TwiStart();
  TwiWriteByte(g_DeviceAddr );//= |TW_WRITE
  TwiWriteByte(page_index>>8);//写地址高字节
  TwiWriteByte(page_index);//写地址低字节
  
  for(i=0;i<g_PageSize;i++)
    TwiWriteByte(buf[i]);
    
  TwiStop();
  EEPROM_WRITE_DISABLE;
}

//AT24CXX通用读页函数,page_index为页地址,即表示第几页
void At24cxxReadPage(uint16_t page_index,uint8_t *buf)
{
  uint8_t i;
  
  //页索引调整到绝对地址
  page_index<<=g_PageBitCount;
  
  TwiStart();
  TwiWriteByte(g_DeviceAddr);//写地址
  TwiWriteByte(page_index>>8);
  TwiWriteByte(page_index);
  
  TwiStart();
  TwiWriteByte(g_DeviceAddr | TW_READ);
  for(i=0;i<g_PageSize-1;i++)
    TwiReadByte(&buf[i],TW_ACK);

  TwiReadByte(&buf[i],TW_NOACK);//最后一字节不应答
  TwiStop();
}

void At24cxxReadSomeByte(uint8_t device_addr,uint16_t num,uint8_t addr,uint8_t *buf)
{
  uint8_t i;
  
  TwiStart();
  TwiWriteByte(device_addr);//写地址
  
  TwiStart();
  TwiWriteByte(device_addr | TW_READ);
  TwiWriteByte(addr);//写地址低字节
  for(i=0;i<num-1;i++)
    TwiReadByte(&buf[i],TW_ACK);

  TwiReadByte(&buf[i],TW_NOACK);//最后一字节不应答
  TwiStop();
}

void I2CWriteData(uint16_t device_addr,uint16_t addr,char *buf,uint8_t NumByteToRead)
{
  uint8_t i;  

  I2CWaitBusy(device_addr);

  EEPROM_WRITE_ENABLE;
  TwiStart();
  TwiWriteByte(device_addr );//= |TW_WRITE
  TwiWriteByte(addr);//写地址低字节
  
  for(i=0;i<NumByteToRead;i++)
  {
    TwiWriteByte(buf[i]);
  }
    
  TwiStop();
  EEPROM_WRITE_DISABLE;
}

void I2CReadData(uint8_t device_addr,uint8_t addr,char *buf,uint8_t NumByteToRead)
{
  uint8_t i;
  
  TwiStart();
  TwiWriteByte(device_addr);//写地址  
  TwiWriteByte(addr);//写地址低字节
  
  TwiStart();
  TwiWriteByte(device_addr | TW_READ);
  for(i=0;i<NumByteToRead-1;i++)
    TwiReadByte(&buf[i],TW_ACK);
  TwiReadByte(&buf[i],TW_NOACK);//最后一字节不应答
  TwiStop();
}

void I2CWaitBusy(uint8_t device_addr)
{
  uint8_t i;
  //检测EEPROM是否忙
  while(1)
  {
    TwiStart();
    i=TwiWriteByte(device_addr);
    TwiStop();
    if(i==NO_BUSY)
      break;
  }  
  return ;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -