0
点赞
收藏
分享

微信扫一扫

STM32学习 IIC读写EEPROM AT24C02


1 24C02简介

24C02 是一个 2K bit 的串行 EEPROM 存储器,内部含有 256 个字节。在 24C02 里面还有

一个 8 字节的页写缓冲器。该设备的通信方式 IIC,通过其 SCL 和 SDA 与其他设备通信

STM32学习 IIC读写EEPROM AT24C02_学习


上图的 WP 引脚是写保护引脚,接高电平只读,接地允许读和写,我们的板子设计是把该

引脚接地。每一个设备都有自己的设备地址,24C02 也不例外,但是 24C02 的设备地址是包括

不可编程部分和可编程部分,可编程部分是根据上图的硬件引脚 A0、A1 和 A2 所决定。设备

地址最后一位用于设置数据的传输方向,即读操作/写操作,0 是写操作,1 是读操作

STM32学习 IIC读写EEPROM AT24C02_学习_02

2 24C02 读写时序图

写时序图

STM32学习 IIC读写EEPROM AT24C02_内存地址_03


上图展示的主机向 24C02 写操作时序图,主机在 IIC 总线发送第 1 个字节的数据为 24C02

的设备地址 0xA0,用于寻找总线上找到 24C02,在获得 24C02 的应答信号之后,继续发送第

2 个字节数据,该字节数据是 24C02 的内存地址,再等到 24C02 的应答信号,主机继续发送

第 3 字节数据,这里的数据即是写入在第 2 字节内存地址的数据。主机完成写操作后,可以发

出停止信号,终止数据传输。

页写时序图

STM32学习 IIC读写EEPROM AT24C02_内存地址_04


在单字节写时序时,每次写入数据时窦需要先写入设备的内存地址才能实现,在页写时序

中,只需要告诉 24C02 第一个内存地址 1,后面数据会按照顺序写入到内存地址 2,内存地址 3

等,大大节省了通信时间,提高了时效性。因为 24C02 每次只能写 8bit 数据,所以它的页大小

也就是 1 字节。页写时序的操作方式跟上面的单字节写时序差不多,所以不作过多解释了。参

考以上说明去理解页写时序。

读时序图

STM32学习 IIC读写EEPROM AT24C02_学习_05


24C02 读取数据的过程是一个复合的时序,其中包含写时序和读时序。先看第一个通信过

程,这里是写时序,起始信号产生后,主机发送 24C02 设备地址 0xA0,获取从机应答信号后,

接着发送需要读取的内存地址;在读时序中,起始信号产生后,主机发送 24C02 设备地址 0xA1,

获取从机应答信号后,接着从机返回刚刚在写时序中内存地址的数据,以字节为单位传输在总

线上,假如主机获取数据后返回的是应答信号,那么从机会一直传输数据,当主机发出的是非

应答信号并以停止信号发出为结束,从机就会结束传输。

3示例代码

myiic.h

#ifndef _24C02_H
#define _24C02_H

#include "myiic.h"

#define   AT24C02  255

void at24c02_init(void);                                                /* 初始化IIC */
uint8_t at24c02_read_byte(uint8_t addr);                                /* 指定地址读取一个字节 */
void at24c02_write_byte(uint8_t addr,uint8_t data);                     /* 指定地址写入一个字节 */
void at24c02_read( uint8_t addr,uint8_t *pbuf, uint8_t datalen);        /* 从指定地址开始读出指定长度的数据 */
void at24c02_write(uint8_t addr,uint8_t *pbuf, uint8_t datalen);        /* 从指定地址开始写入指定长度的数据 */
uint8_t at24c02_check(void);                                            /* 检查器件 */

#endif

24c02.c

#include "24c02.h"


/**
 * @brief       初始化IIC接口
 * @param       无
 * @retval      无
 */
 
 void at24c02_init(void)
 {
    iic_init();
 }
 
/**
 * @brief       在AT24C02指定地址读出一个数据
 * @param       readaddr: 开始读数的地址
 * @retval      读到的数据
 */

 uint8_t at24c02_read_byte(uint8_t addr)
 {
    uint8_t temp=0;
    /* 1 发送起始信号 */
    iic_start();               /* 发送IIC开始信号 */
    /* 2 发送设备地址 写 */
    iic_send_byte(0xA0);       /* IIC发送一个字节 */
    iic_wait_ack();            /* 每次发送完一个字节,都要等待ACK */
    /* 3 发送内存地址 */
    iic_send_byte(addr);       /* IIC发送一个字节 */
    iic_wait_ack();            /* 每次发送完一个字节,都要等待ACK */
    
    /* 4 发送起始信号 */
    iic_start();               /* 发送IIC开始信号 */
    /* 5 发送设备地址 读 */
    iic_send_byte(0xA1);       /* IIC发送一个字节 */
    iic_wait_ack();            /* 每次发送完一个字节,都要等待ACK */
    /* 6 接收数据 主机发nack*/
    temp=iic_read_byte(0); /* IIC读取一个字节 */
    /* 7 停止*/
    iic_stop();                /* 发送IIC停止信号 */
    return temp;
    
 }
 
 
 /**
 * @brief       在AT24C02指定地址写入一个数据
 * @param       addr: 写入数据的目的地址
 * @param       data: 要写入的数据
 * @retval      无
 */
 
void at24c02_write_byte(uint8_t addr,uint8_t data)
{
    /* 1 发送起始信号 */
    iic_start();               /* 发送IIC开始信号 */
    /* 2 发送设备地址 写 */
    iic_send_byte(0xA0);       /* IIC发送一个字节 */
    iic_wait_ack();            /* 每次发送完一个字节,都要等待ACK */
    /* 3 发送内存地址 */
    iic_send_byte(addr);       /* IIC发送一个字节 */
    iic_wait_ack();            /* 每次发送完一个字节,都要等待ACK */
    /* 4 发送数据 */
    iic_send_byte(data);       /* IIC发送一个字节 */
    iic_wait_ack();            /* 每次发送完一个字节,都要等待ACK */
    /* 5 停止 */
    iic_stop();                /* 发送IIC停止信号 */
    delay_ms(10);/* 注意: EEPROM 写入比较慢,必须等到10ms后再写下一个字节 */

}

/**
 * @brief       在AT24C02里面的指定地址开始读出指定个数的数据
 * @param       addr    : 开始读出的地址 对24c02为0~255
 * @param       pbuf    : 数据数组首地址
 * @param       datalen : 要读出数据的个数
 * @retval      无
 */

void at24c02_read( uint8_t addr,uint8_t *pbuf, uint8_t datalen)
{
    while(datalen--)
    {
       *pbuf++=at24c02_read_byte(addr++);
    }
}

/**
 * @brief       在AT24C02里面的指定地址开始写入指定个数的数据
 * @param       addr    : 开始写入的地址 对24c02为0~255
 * @param       pbuf    : 数据数组首地址
 * @param       datalen : 要写入数据的个数
 * @retval      无
 */
void at24c02_write(uint8_t addr,uint8_t *pbuf, uint8_t datalen)
{
    while(datalen--)
    {
      at24c02_write_byte(addr,*pbuf);
      addr++;
      pbuf++;
    }
}

/**
 * @brief       检查AT24C02是否正常
 *   @note      检测原理: 在器件的末地址写如0X55, 然后再读取, 如果读取值为0X55
 *              则表示检测正常. 否则,则表示检测失败.
 *
 * @param       无
 * @retval      检测结果
 *              0: 检测成功
 *              1: 检测失败
 */

uint8_t at24c02_check(void)
{
    uint8_t addr;
    uint8_t temp;
    
    addr = AT24C02;
    
    temp=at24c02_read_byte(addr);
    
    if(temp==0x55)
    {
       return 0;
    }
    else
    {
      at24c02_write_byte(addr,0x55);
      temp=at24c02_read_byte(addr);
      if(temp==0x55)
      {
        return 0;
      }
    }
    return 1;
}

main.c

#include "24c02.h"


int main(void)
{
    uint8_t len;
    uint16_t times = 0;
    uint8_t rec_data=0;
    uint8_t at24c02_chk=0;

    HAL_Init();                                             /* HAL库初始化 */
    HAL_ICACHE_Enable();                                    /* 使能指令缓存 */
    sys_stm32_clock_init(250, 4, 2, 2);                     /* 系统时钟初始化, 250Mhz */
    delay_init(250);                                        /* 延时初始化 */
    usart_init(115200);                                     /* 串口初始化 */
    led_init();                                             /* LED初始化 */
    at24c02_init();                                         /* 24c02初始化 */
    printf("at24c02 init Ok !\r\n");
    while(1)
    {
        at24c02_chk=at24c02_check();
        
        if(at24c02_chk==0)
        {
           printf("at24c02 Check Ok !\r\n");
        }
        else
        {
           printf("at24c02 Check Failed !\r\n");
        }
        
        at24c02_write_byte(10,100);/* 指定地址写入一个字节 */
        printf("at24c02 write addr 10 data 100 !\r\n");
        delay_ms(500);
        rec_data =at24c02_read_byte(10);/* 指定地址读取一个字节 */
        printf("at24c02 read addr 10 data %d\r\n",rec_data);
        delay_ms(500);
        LED0_TOGGLE();
    }
}

STM32学习 IIC读写EEPROM AT24C02_数据_06


举报

相关推荐

0 条评论