• AT24C02存储与读取数据


    1.前言

    项目资源:

    https://download.csdn.net/download/YLG_lin/86541001

    1.1实验现象

    LCD1602液晶屏上显示一个无符号整型数字,按下K1按键数字减一,按下K2数字加一,按下K3数字向AT24C02写入该数据,断电重启后按下K4可以从AT24C02中读取该数据。

    1.2 AT24C02介绍

    AT24C02是一种可以实现掉电不丢失的存储器,可用于保存单片机运行时想要永久保存的数据信息
    存储介质:E2PROM
    通讯接口:I2C总线
    容量:256字节

    2. 相关程序及解释

    2.1 引脚定义

    1. sbit I2C_SCL=P2^1;
    2. sbit I2C_SDA=P2^0;

    2.2 I2C起始信号

    起始条件:SCL高电平期间,SDA从高电平切换到低电平

    空闲状态下 SDA与SCL默认置高电平;值得注意的是在应答之后SDA有可能为高电平也有可能为低电平(复合格式如下图),所以开始时要置高电平;

    1. void I2C_Start()
    2. {
    3. I2C_SDA=1;
    4. I2C_SCL=1;
    5. I2C_SDA=0;
    6. I2C_SCL=0;
    7. }

     2.3 I2C停止信号

    终止条件:SCL高电平期间,SDA从低电平切换到高电平

    1. void I2C_Stop()
    2. {
    3. I2C_SDA=0;
    4. I2C_SCL=1;
    5. I2C_SDA=1;
    6. }

     2.4 I2C主机向从机发送一个字节数据

    SCL低电平期间,主机将数据位依次放到SDA线上(高位在前),然后拉高SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节

    SCL置高后立马置低,不用加延迟,从机是能在高电平期间读到数据的;如果换到更快的单片机的话就要考虑它能承受的最快时间了,具体参考芯片手册;

    1. void I2C_SendByte(unsigned char Byte)
    2. {
    3. unsigned char i;
    4. for(i=0;i<8;i++)
    5. {
    6. I2C_SDA=Byte&(0x80>>i);
    7. I2C_SCL=1;
    8. I2C_SCL=0;
    9. }
    10. }

    2.5 I2C主机接收一个字节数据

    SCL低电平期间,从机将数据位依次放到SDA线上(高位在前),然后拉高SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)

    1. unsigned char I2C_ReceiveByte(void)
    2. {
    3. unsigned char i,Byte=0x00;
    4. I2C_SDA=1;
    5. for(i=0;i<8;i++)
    6. {
    7. I2C_SCL=1;
    8. if(I2C_SDA){Byte|=(0x80>>i);}
    9. I2C_SCL=0;
    10. }
    11. return Byte;
    12. }

    2.6 发送应答

    发送应答:在接收完一个字节之后,主机在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答

    1. void I2C_SendAck(unsigned char AckBit)
    2. {
    3. I2C_SDA=AckBit;
    4. I2C_SCL=1;
    5. I2C_SCL=0;
    6. }

    2.7 接收应答

    接收应答:在发送完一个字节之后,主机在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)

    1. unsigned char I2C_ReceiveAck(void)
    2. {
    3. unsigned char AckBit;
    4. I2C_SDA=1;
    5. I2C_SCL=1;
    6. AckBit=I2C_SDA;
    7. I2C_SCL=0;
    8. return AckBit;
    9. }

     2.8 主机向从机发数据(多字节)

     AT24C02的固定地址为1010,可配置地址本开发板上为000
     所以SLAVE ADDRESS+W为0xA0,SLAVE ADDRESS+R为0xA1

    字节写:在WORD ADDRESS处写入数据DATA

    1. void AT24C02_WriteByte(unsigned char WordAddress,Data)
    2. {
    3. I2C_Start();
    4. I2C_SendByte(AT24C02_ADDRESS);
    5. I2C_ReceiveAck();
    6. I2C_SendByte(WordAddress);
    7. I2C_ReceiveAck();
    8. I2C_SendByte(Data);
    9. I2C_ReceiveAck();
    10. I2C_Stop();
    11. }

    2.9 从机向主机发数据(多字节)

    随机读:读出在WORD ADDRESS处的数据DATA

    1. unsigned char AT24C02_ReadByte(unsigned char WordAddress)
    2. {
    3. unsigned char Data;
    4. I2C_Start();
    5. I2C_SendByte(AT24C02_ADDRESS);
    6. I2C_ReceiveAck();
    7. I2C_SendByte(WordAddress);
    8. I2C_ReceiveAck();
    9. I2C_Start();
    10. I2C_SendByte(AT24C02_ADDRESS|0x01);
    11. I2C_ReceiveAck();
    12. Data=I2C_ReceiveByte();
    13. I2C_SendAck(1);
    14. I2C_Stop();
    15. return Data;
    16. }

    3.0 main.c

    读取数据的时候不用Delay(5);写的时候要加延时函数,写的时候需改变AT24C02的物理特性,让它永久保存数据,所以需要的时间长一点;具体时间可以查用户手册;ROM比RAM慢一些,就与ROM有个写入时间有关;keynum==3 中num是16位数据,在地址0写入num低8位,在地址1写入高八位;

    1. void main()
    2. {
    3. LCD_Init();
    4. LCD_ShowNum(1,1,Num,5);
    5. while(1)
    6. {
    7. KeyNum=Key();
    8. if(KeyNum==1) //K1按键,Num自增
    9. {
    10. Num++;
    11. LCD_ShowNum(1,1,Num,5);
    12. }
    13. if(KeyNum==2) //K2按键,Num自减
    14. {
    15. Num--;
    16. LCD_ShowNum(1,1,Num,5);
    17. }
    18. if(KeyNum==3) //K3按键,向AT24C02写入数据
    19. {
    20. AT24C02_WriteByte(0,Num%256);
    21. Delay(5); //延迟5ms,查芯片手册可知
    22. AT24C02_WriteByte(1,Num/256);
    23. Delay(5);
    24. LCD_ShowString(2,1,"Write OK");
    25. Delay(1000);
    26. LCD_ShowString(2,1," ");
    27. }
    28. if(KeyNum==4) //K4按键,从AT24C02读取数据
    29. {
    30. Num=AT24C02_ReadByte(0);
    31. Num|=AT24C02_ReadByte(1)<<8;
    32. LCD_ShowNum(1,1,Num,5);
    33. LCD_ShowString(2,1,"Read OK ");
    34. Delay(1000);
    35. LCD_ShowString(2,1," ");
    36. }
    37. }
    38. }

  • 相关阅读:
    Python基于循环神经网络的情感分类系统设计与实现,附源码
    【PyTorch】MSELoss的详细理解(含源代码)
    Spring全局异常处理
    ECCV 2022 | MVDG:一种用于域泛化的统一多视图框架
    简单学习OSM(OpenStreetMap)文件格式的最基础结构
    11月了,焦虑烦躁,然后是无悲无喜
    GaussDB数据库SQL系列-UNION & UNION ALL
    OpenGL ES google angle
    flink的起源、概念、特点、应用
    numpy教程:Universal Functions 通用函数 伪随机数
  • 原文地址:https://blog.csdn.net/YLG_lin/article/details/126891135