STM32 IIC读写AT24C02(三)

接口/总线/驱动

1117人已加入

描述

现在我们已经实现了AT24C02的单字节读写,但是对于对于2K内存来说,如果对全部数据的读取或者写入都只用单字节读写来完成,这样就会很不方便。为了解决对大量数据的读写,现在介绍下AT24C02的页写和顺序读。

STM32

AT24C02器件按8字节/页执行页写。页写初始化与字节写相同,只是主器件不会在第一个数据后发送停止条件,而是在AT24C02的ACK以后,接着发送7个数据。AT24C02收到每个数据后都应答“0”。最后仍需由主器件发送停止条件,终止写序列。

//页写
void AT24C02_PageWrite(u8 wordAdd,u8 *str,u8 size,s8 *err)
{
  u8 ack = 0;
  u8 i = 0;

  IIC_Start();
  IIC_SendByte(AT24C02_ADD< < 1);//发器件地址
  ack = IIC_CheckAck();
  if(ack != 0)                 //不应答
  {
    IIC_Stop();
    *err = -7;
    return;
  }

  IIC_SendByte(wordAdd);      //发字地址
  ack = IIC_CheckAck();
  if(ack != 0)                 //不应答
  {
    IIC_Stop();
    *err = -8;
    return;
  }

  for(i=0;i< size;i++)
  {
    IIC_SendByte(*str);      //发字地址
    str++;
    ack = IIC_CheckAck();
    if(ack != 0)                 //不应答
    {
      IIC_Stop();
      *err = -9;
      return;
    }
  }

  IIC_Stop();
  *err = 0;
}

接收到每个数据后,字地址的低3位或4位或5位内部自动加1,高位地址位不变,维持在当前页内。当内部产生的子地址达到该页边界地址时,随后的数据将写入该页的页首。为了解决这个问题,实现连续写的操作,下面介绍下连续写的方法。

连续写,首先要根据计算要写入首地址计算当前页剩多少字节可写,再判断要写的字节是否超过当前页可写字节数,如果不超过,直接调用页写函数写入即可;如果超过当前页可写字节数,则写完当前页,再依次页写剩余字节。

//连续写操作
void AT24C02_ContinueWrite(u8 wordAdd,u8 *str,u8 size,s8 *err)
{
  u8 CanWriteBytes = 0;

  while(1)
  {
    CanWriteBytes = 8 - wordAdd%8;          //计算当前页可写字节
    if(CanWriteBytes >= size)
    {
      AT24C02_PageWrite(wordAdd,str,size,err);
      break;
    }
    else
    {
      AT24C02_PageWrite(wordAdd,str,CanWriteBytes,err);
      wordAdd += CanWriteBytes;
      str += CanWriteBytes;
      size -= CanWriteBytes;
    }
  }
}

STM32

和连续写对应的是顺序读,顺序读可以通过“随机读”启动。主器件接收到一个数据后,应答ACK。只要AT24C02接收到ACK,将自动增加字地址并继续随时钟发送后面的数据。若达到存储器地址末尾,地址自动会转到0,仍可继续顺序读取数据。

主器件不应答“0”,而发送停止条件,即可结束顺序读操作。

void AT24C02_ContinueRead(u8 wordAdd,u8 *str,u8 size,s8 *err)
{
  u8 ack = 0;
  u8 i = 0;

  IIC_Start();
  IIC_SendByte(AT24C02_ADD< < 1);//发器件地址
  ack = IIC_CheckAck();
  if(ack != 0)                 //不应答
  {
    IIC_Stop();
    *err = -10;
    return;    
  }

  IIC_SendByte(wordAdd);      //发字地址
  ack = IIC_CheckAck();
  if(ack != 0)                 //不应答
  {
    IIC_Stop();
    *err = -11;
    return;    
  }

  IIC_Start();
  IIC_SendByte(AT24C02_ADD< < 1 | 1);//发器件地址(读)
  ack = IIC_CheckAck();
  if(ack != 0)                 //不应答
  {
    IIC_Stop();
    *err = -12;
    return;    
  }

  for(i = 0;i< size-1;i++)
  {
    *str++ = IIC_ReadByte();
    IIC_AcktoSlave();
  }
  *str = IIC_ReadByte();
  IIC_NoAcktoSlave();
  IIC_Stop();

  *err = 0;
}

最后,在主文件中调用连续写和顺序读两个函数。将程序烧入开发板中,打开串口助手,读出的数据和写入的完全一样,连续写和顺序读就成功了。AT24C02就介绍到这里,感兴趣的还可以自己拓展下,用AT24C02尝试下其他小项目。

#include "stm32f4xx.h"
#include "led.h"
#include "usart.h"
#include "delay.h"
#include "stdio.h"
#include "AT24C02.h"


u8 str[40]="hello world!rnhello world!rn";
u8 buf[40]={0};


int main()
{
  s8 err = 0;

  Usart1_Init(115200);
  LED_Init();              //初始化LED灯
  AT24C02_Init();

  AT24C02_ContinueWrite(6,str,sizeof(str),&err);
  AT24C02_ContinueRead(6,buf,sizeof(str),&err);
  printf("buf = %srn",buf);

  while(1)              
  {

  }
}

STM32

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分