ZYNQ_IIC读写M24M01记录板子状态

ZYNQ_IIC读写M24M01记录板子状态

1 M24M01特点

1.1 特征

1,兼容IIC的模式:1MHz;400kHz;100kHz;

2,内存大小:1Mbit = 128Kbyte;页大小为256byte;

3,写要求:字节写在5ms内完成;页写在5ms内完成

4,操作温度范围:-40摄氏度到+85摄氏度;

5,支持随机读模式和序列读模式;

6,整个内存都可以进行写保护;

7,可进行超过400万次写;

8,寿命可达到200年;

1.2 引脚分布

引脚分布图如图1所示。

ZYNQ_IIC读写M24M01记录板子状态_第1张图片

图1 引脚分布

Scl:IIC的时钟信号,需要上拉;

Sda:IIC的数据信号,数据的输入和输出线,需要上拉;

E1,E2:输入信号,用来决定eeprom从设备地址(总共是7位从设备地址)的b3和b2位,这两个信号必须是接到vcc或者vss,如果悬空的话,那么其输入会被认为是(0,0);

WC:写控制信号,用来保护数据的正确写入,而不是误操作而写入到内存中的,当其为高电平的时候数据不允许写入到内存中,只有当该信号为低电平或者悬空的时候才能进行写操作;当这个信号为高电平时,设备选择和地址字节被识别,而数据字节不被识别;

2 操作

2.1 设备地址

在主设备和从设备之间进行IIC通信的时候,主设备必须发出一个起始信号,然后主设备发送一个从设备地址,然后才能正常通信,该从设备地址的描述如图2所示。

ZYNQ_IIC读写M24M01记录板子状态_第2张图片

图2 从设备地址描述

B0位表示IIC的操作是写或者读,如果1表示读,如果0表示写;

B1位表示操作地址的最高位A16位,读写操作时发送的地址为低16位,最高位A16位用来做从设备地址中做地址区分,当A16位选0,则表示需要写入EEPROM的低64KB,当A16位选1,则表示需要写入EEPROM的高64KB;

B2、B3位是E1和E2匹配的输入信号,连接VCC表示1,连接VSS表示0;

2.2 写操作

Eeprom的写操作可分为单个字节的写入和页数据的写入,单字节写入,每一次操作写入到eeprom指定的地址一个字节数据;页数据写入:每一次操作写入到eeprom数据为指定为一页以内(1-256)。其操作如图3所示。

字节写:

  1. 主设备发送一个起始信号;
  2. 主设备发送从设备地址(写),等待一个ACK信号;
  3. 发送字节存储在eeprom中的地址的高8位,等待一个ACK信号;
  4. 发送字节存储在eeprom中的地址的低8位,等待一个ACK信号;
  5. 发送需要写入eeprom的字节数据,等待一个ACK信号;
  6. 主设备发送一个停止信号;

页写入:

  1. 主设备发送一个起始信号;
  2. 主设备发送从设备地址(写),等待一个ACK信号;
  3. 发送页数据存储在eeprom中的首地址的高8位,等待一个ACK信号;
  4. 发送页数据存储在eeprom中的首地址的低8位,等待一个ACK信号;
  5. 发送需要写入eeprom的页数据的第一个字节数据,等待一个ACK信号;
  6. 发送需要写入eeprom的页数据的第二个字节数据,等待一个ACK信号;
  7. 。。。
  8. 发送需要写入eeprom的页数据的最后字节数据,等待一个ACK信号;
  9. 主设备发送一个停止信号;

ZYNQ_IIC读写M24M01记录板子状态_第3张图片

图3 写操作模式

2.3 读操作

当成功完成一个读操作后,设备内部的地址计数会自动增加1,指向下一个地址字节数据。在每一个数据读出到总线后,在第9个时钟周期,eeprom会等待主设备发送一个ACK信号,如果此时总线没有ACK信号,那么总线将进入standby状态,停止数据的继续传输。

读模式有当前地址读,随机地址读,当前地址序列读,随机地址序列读四个模式,其操作如图4所示。

当前地址读:

  1. 主设备发送一个起始信号;
  2. 主设备发送从设备地址(读),等待一个ACK信号;
  3. 将字节数据读出,然后主设备设置为NOACK模式;
  4. 主设备发送一个停止信号;

随机地址读:

  1. 主设备发送一个起始信号;
  2. 主设备发送从设备地址(写),等待一个ACK信号;
  3. 主设备发送字节存储在eeprom中的地址的高8位,等待一个ACK信号;
  4. 主设备发送字节存储在eeprom中的地址的低8位,等待一个ACK信号;
  5. 主设备发送一个起始信号;
  6. 主设备发送从设备地址(读),等待一个ACK信号;
  7. 将字节数据读出,然后主设备设置为NOACK模式;
  8. 主设备发送一个停止信号;

当前地址开始序列读:

  1. 主设备发送一个起始信号;
  2. 主设备发送从设备地址(读),等待一个ACK信号;
  3. 将字节数据1读出,等待一个ACK信号;
  4. 将字节数据2读出,等待一个ACK信号;
  5. 。。。
  6. 将最后的字节数据读出,然后主设备设置为NOACK模式;
  7. 主设备发送一个停止信号;

随机地址序列读:

  1. 主设备发送一个起始信号;
  2. 主设备发送从设备地址(写),等待一个ACK信号;
  3. 主设备发送字节存储在eeprom中的地址的高8位,等待一个ACK信号;
  4. 主设备发送字节存储在eeprom中的地址的低8位,等待一个ACK信号;
  5. 主设备发送一个起始信号;
  6. 主设备发送从设备地址(读),等待一个ACK信号;
  7. 将字节数据1读出,等待一个ACK信号;
  8. 将字节数据2读出,等待一个ACK信号;
  9. 。。。
  10. 将字节数据读出,然后主设备设置为NOACK模式;
  11. 主设备发送一个停止信号;

ZYNQ_IIC读写M24M01记录板子状态_第4张图片

图4 读操作模式

3 zynq的IIC配置

3.1 IIC驱动封装

Zynq有两个IIC,板子上用到了IIC1,IIC的sck和sda连接到MIO的mio50和mio51上。

其IIC初始化配置流程:

  1. 根据IIC的设备ID配置IIC的数据结构;
  2. 进行IIC的自检;
  3. 配置IIC的操作时钟;
  4. 配置IIC操作模式为7位地址模式;

源代码:

int Init_IIC(XIicPs *IIC_Ptr)

{

      XIicPs_Config *IIC_ConfigPtr;

      //1,find device

      IIC_ConfigPtr = XIicPs_LookupConfig(XPAR_XIICPS_0_DEVICE_ID);

      //2,config iic struct data

XIicPs_CfgInitialize(IIC_Ptr,IIC_ConfigPtr,IIC_ConfigPtr->BaseAddress);

      //3,iic selftest

      status = XIicPs_SelfTest(IIC_Ptr);

      //4,config iic clk

      XIicPs_SetSClk(IIC_Ptr, IIC_SCLK_RATE);

      //5,config iic mode

      XIicPs_SetOptions(IIC_Ptr,XIICPS_7_BIT_ADDR_OPTION);

      return XST_SUCCESS;

}

IIC的写操作流程:

  1. 配置好写buffer,在buffer中填充需要向eeprom中写入数据的地址和需要写入的数据;
  2. 调用板级开发包的IIC轮询写操作函数,将写buffer中的数据发送到总线上;
  3. 等待总线数据传输完成,进入空闲模式,方便下一次操作总线;

源代码:

int IIC_Random_Write(XIicPs *iic_Ptr,u16 slave_device_addr,u16 addr,u8 *data,u16 ByteCount)

{

      Int i = 0;

      u8 writebuf[16];

      //1,config wtire data

      writebuf[0] = (addr >> 8);

      writebuf[1] = addr;

      for(i = 0;i < ByteCount;i++)

      {

             writebuf[2 + i] = data[i];

      }

      //2,send addr and data to iic bus

      XIicPs_MasterSendPolled(iic_Ptr,writebuf,

2 + ByteCount,slave_device_addr);

      //3,Wait until bus is idle to start another transfer

      while(XIicPs_BusIsBusy(iic_Ptr))

             ;

      return XST_SUCCESS;

}

IIC的读操作流程:

  1. 配置好写buffer,在buffer中填充需要向eeprom中写入数据的地址;
  2. 调用板级开发包的IIC轮询写操作函数,将写buffer中的地址数据发送到总线上;
  3. 调用板级开发包的IIC轮询读操作函数,读出需要读出的数据;
  4. 等待总线数据传输完成,进入空闲模式,方便下一次操作总线;

3.2 记录板子上电次数和上电累计时间策略

记录板子上电次数:

通过EEPROM将主控上电次数记录下来,这样当设备在掉电的情况下也能将该数据保留下来。为了避免EEPROM在执行写操作的过程中突然断电导致数据没法更新到EEPROM,采用两个地址来存储上电次数,这两个地址为从设备地址0x56的0x0000和从设备地址0x57的0x0000。以两个地址互相备份,这样可以预防其中一个地址在意外断电导致eeprom中记录数据丢失的发生。

根据上电次数的阈值分析,一个32位的数据能够满足要求,所以上电次数的存储值以一个32位数据来存储。但是,eeprom中一个地址只能存储一个8位数据,所以需要将32位数据拆分为4个8位数据,存储在地址从0x0000开始的4个地址中,为了保证数据的正确性,把前四个字节数据的校验和存储到第5个地址中(校验和=字节1+字节2+字节3+字节4,若是超过了8位阈值则取低8位)。

记录过程:

  1. 首次操作EEPROM,需要将从设备(0x56)的0x0000开始后的5个地址全部刷写为0x00,将从设备(0x57)的0x0000开始的5个地址全部刷写为0x00,这样上电次数为0,而且校验和也为0;(随后不需要做此操作);
  2. 每次上电,先读出两个地址存储的上电次数数据,并且计算其校验和,判断其校验和是否正确,(不正确可能是上一次写失败了);
  3. 根据校验和的判断分三种情况更新数值:第一种,两个数值校验和都是正确的,比较两个地址数值的大小,取两者之中大的,数值加一后更新到两个地址中;第二种,第一个地址数值校验和正确,而第二个地址数值校验和错误,则将第一个数值加1后更新到两个地址中;第三种,第一个地址数值校验和错误,而第二个地址数值校验和正确,则将第二个数值加1后更新到两个地址中。

记录板子上电累计时间:

过EEPROM将主控上电累计上电时间记录下来,这样当设备在掉电的情况下也能将该数据保留下来。为了避免EEPROM在执行写操作的过程中突然断电导致数据没法更新到EEPROM,采用两个地址来存储上电次数,这两个地址为从设备地址0x56的0x0100和从设备地址0x57的0x0100。以两个地址互相备份,这样可以预防其中一个地址在意外断电导致eeprom中记录数据丢失的发生。

根据上电次数的阈值分析,一个32位的数据能够满足要求,所以上电次数的存储值以一个32位数据来存储。但是,eeprom中一个地址只能存储一个8位数据,所以需要将32位数据拆分为4个8位数据,存储在地址从0x0000开始的4个地址中,为了保证数据的正确性,把前四个字节数据的校验和存储到第5个地址中(校验和=字节1+字节2+字节3+字节4,若是超过了8位阈值则取低8位)。

记录过程:

  1. 首次操作EEPROM,需要将从设备(0x56)的0x0100开始后的5个地址全部刷写为0x00,将从设备(0x57)的0x0100开始的5个地址全部刷写为0x00,这样上电累计时间为0,而且校验和也为0;(随后不需要做此操作);
  2. 每次上电,先读出两个地址存储的累计时间数据,并且计算其校验和,判断其校验和是否正确,(不正确可能是上一次写失败了);
  3. 根据校验和的判断分三种情况更新数值:第一种,两个数值校验和都是正确的,比较两个地址数值的大小,取两者之中大的,将其更新到两个地址中;第二种,第一个地址数值校验和正确,而第二个地址数值校验和错误,则将第一个数值更新到两个地址中;第三种,第一个地址数值校验和错误,而第二个地址数值校验和正确,则将第二个数值更新到两个地址中;
  4. 板子正常运行以后,每隔5s中刷新一次EEPROM中的数据。第一次5s刷写第一个地址中的累计时间:先读出第二个地址的累计时间数据,然后将其加5后写入到第一个地址中。第二次5s刷写第二个地址中的累计时间:先读出第一个地址的累计时间数据,然后将其加5后写入到第二个地址中。以此类推,ping-pong刷写。

你可能感兴趣的:(zynq学习)