模拟IIC读取EEPROM存储单元AT24C02(新唐M051系列单片机)

本文只包含IIC协议和AT24C02的单字节读取,写入部分也是类似就不赘述了。

AT24C02资料链接-->点我

详细理解描述可以看这位老哥-->跳转


 本文代码需要的声明和宏定义如下:

#define IIC_SDA E_PORT1,E_PIN5
#define IIC_SCL E_PORT1,E_PIN6

#define IIC_SDA_SET DrvGPIO_SetBit(IIC_SDA)
#define IIC_SDA_CLR DrvGPIO_ClrBit(IIC_SDA)

#define IIC_SCL_SET DrvGPIO_SetBit(IIC_SCL)
#define IIC_SCL_CLR DrvGPIO_ClrBit(IIC_SCL)

#define SDA_READ DrvGPIO_GetBit(IIC_SDA)

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;

IIC协议起始和终止

游戏起始的规则:数据线(SDA)在时钟线(SCL)保持在高位的情况下产生变化:高→低

游戏终止的规则:数据线(SDA)在时钟线(SCL)保持在高位的情况下产生变化:低→高

代码如下(延时一般保证大于4.7us就行,可稍微大些):

void IIC_Start(void)
{
  IIC_SDA_SET;
  IIC_SCL_SET;
  DrvSYS_Delay(8);
  IIC_SDA_CLR;
  DrvSYS_Delay(8);
  IIC_SCL_CLR;
}

void IIC_Stop(void)
{
  IIC_SCL_CLR;
  IIC_SDA_CLR;
  DrvSYS_Delay(8);
  IIC_SCL_SET;
  DrvSYS_Delay(8);
  IIC_SDA_SET;
}

IIC协议等待响应

void IIC_Wait_Ack(void)
{
  u8 i=0;

  IIC_SDA_SET;
  DrvSYS_Delay(8);

  IIC_SCL_SET;
  DrvSYS_Delay(8);
  while(SDA_READ&&i<200)
  {
    i++;
    SendString("ack fail \n");
  }    
  IIC_SCL_CLR;//<--------这里千万不能忘,漏掉读出来的全都是255
  DrvSYS_Delay(8); 
}
 

IIC协议发送一个字节

void IIC_Send_Byte(u8 byte)
{
    char str[20];
    u8 i;
    
    for(i=0;i<8;i++)
    {
        IIC_SCL_CLR;
        DrvSYS_Delay(8);
        
        if(byte&(1<<(7-i)))
            IIC_SDA_SET;
        else
            IIC_SDA_CLR;
        
        DrvSYS_Delay(8);

        IIC_SCL_SET;
        DrvSYS_Delay(8);

    }
        IIC_SCL_CLR;
        IIC_SDA_SET;
        DrvSYS_Delay(8);
        sprintf(str,"--%x--",byte);
        SendString(str);
}

IIC协议接收一个字节

u8 IIC_Read_Byte(void)
{
    char str[22];
    u8 i,dat=0;
    IIC_SDA_SET;
    IIC_SCL_CLR;
    DrvSYS_Delay(8);
    for(i=0;i<8;i++)
    {
        IIC_SCL_SET;
        DrvSYS_Delay(8);
        dat<<=1;
        
        dat|=SDA_READ;
        DrvSYS_Delay(8);
        
        IIC_SCL_CLR;
        DrvSYS_Delay(8);
        sprintf(str,"--%d--",dat);
        SendString(str);
    }
        
    return dat;
}

以上是IIC协议的部分,下面是对AT24C02进行操作

初始化

首先模拟的IIC需要对两时钟和数据线连接的引脚进行配置,时钟线让它保持输出就行,数据线则需要设置为准双向,代码如下:

void IIC_Init(void)
{
    DrvGPIO_Open(IIC_SDA, E_IO_QUASI);
    DrvGPIO_Open(IIC_SCL, E_IO_OUTPUT);
}

向EEPROM中写数据

u8 AT24C02_ReadOneByte(u16 ReadAddr) 
{ 
    u8 temp=0; 
    IIC_Start(); 

    IIC_Send_Byte(0XA0); //发送器件地址0XA0,写数据
    IIC_Wait_Ack();
    IIC_Send_Byte(ReadAddr); //发送低地址
    IIC_Wait_Ack(); 
    IIC_Start(); 
    IIC_Send_Byte(0XA1); //进入接收模式 
    IIC_Wait_Ack(); 

    temp=IIC_Read_Byte(); 
    IIC_Stop();//产生一个停止条件 

    return temp;
}

猜你喜欢

转载自www.cnblogs.com/fancyop/p/iic_at24c02.html