AT24C02介绍与应用
AT24C02介绍与应用

一、容量与地址数量
- 总容量:2Kbit = 256字节(Byte)
- 地址总数:256个,地址范围:0x00~0xFF(十进制0~255),8位地址寻址
- 页结构:32页 × 8字节/页(页写一次最多连续写8字节)
二、每个地址存多少数据
- 最小寻址单元:1字节(8bit),即每个地址只能存1字节(0~255)
三、如何选择地址写入(I2C写流程)
1. 硬件地址(选芯片)
- 从机地址:
1010 A2 A1 A0 0(写操作,最低位R/W=0) - A2/A1/A0引脚:接地=0,接VCC=1;多片时用来区分芯片(最多8片)
2. 片内地址(选存储位置)
- 发送完从机地址并收到应答后,发送1字节片内地址(0x00~0xFF),即要写入的目标地址
3. 写字节(单字节写)
- 起始信号 → 从机地址(写)→ 应答
- 发送片内地址 → 应答
- 发送1字节数据 → 应答
- 停止信号 → 等待5~10ms(内部编程)
4. 页写(连续写最多8字节)
- 流程同单字节写,但发完首地址后连续发1~8字节,地址自动递增;不能跨页(如0x07→0x08会回到页首0x00)

四、代码应用
#ifndef __IIC_24C02_H
#define __IIC_24C02_H
#include "stdint.h"
#include "main.h"
#include "nv128h_oneline.h" // 使用这里的延时函数 HAL_Delay_us(1);
// 可根据自己硬件修改引脚
#define IIC_SDA_PIN GPIO_PIN_14
#define IIC_SCL_PIN GPIO_PIN_13
#define IIC_GPIO_PORT GPIOB
// AT24C02 容量:256字节 地址0~255
#define AT24C02_ADDR 0xA0
// 底层IIC
void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Write_Byte(uint8_t dat);
uint8_t IIC_Read_Byte(uint8_t ack);
uint8_t IIC_Wait_Ack(void);
// AT24C02 功能函数
void AT24C02_Write_Byte(uint8_t addr, uint8_t data);
uint8_t AT24C02_Read_Byte(uint8_t addr);
void AT24C02_Write_Page(uint8_t addr, uint8_t *buf, uint8_t len);
void AT24C02_Read_Buf(uint8_t addr, uint8_t *buf, uint8_t len);
#endif
#include "main.h"
#include "gpio.h"
#include "IIC_24C02.h"
// 引脚位操作
#define SDA_OUT() HAL_GPIO_WritePin(IIC_GPIO_PORT,IIC_SDA_PIN,GPIO_PIN_RESET)
#define SDA_IN() HAL_GPIO_ReadPin(IIC_GPIO_PORT,IIC_SDA_PIN)
#define SCL_LOW() HAL_GPIO_WritePin(IIC_GPIO_PORT,IIC_SCL_PIN,GPIO_PIN_RESET)
#define SCL_HIGH() HAL_GPIO_WritePin(IIC_GPIO_PORT,IIC_SCL_PIN,GPIO_PIN_SET)
// IIC初始化
void IIC_Init(void)
{
GPIO_InitTypeDef gpio_conf = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
gpio_conf.Pin = IIC_SDA_PIN | IIC_SCL_PIN;
gpio_conf.Mode = GPIO_MODE_OUTPUT_PP;
gpio_conf.Pull = GPIO_PULLUP;
gpio_conf.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(IIC_GPIO_PORT, &gpio_conf);
SDA_OUT();
SCL_HIGH();
}
// IIC起始信号
void IIC_Start(void)
{
SDA_OUT();
SCL_HIGH();
HAL_Delay_us(1);
SDA_OUT();
HAL_Delay_us(1);
SCL_LOW();
}
// IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();
SCL_LOW();
HAL_Delay_us(1);
SDA_OUT();
HAL_Delay_us(1);
SCL_HIGH();
HAL_Delay_us(1);
SDA_OUT();
}
// IIC等待应答
uint8_t IIC_Wait_Ack(void)
{
uint8_t time = 0;
SDA_OUT();
HAL_Delay_us(1);
SCL_HIGH();
HAL_Delay_us(1);
while(SDA_IN())
{
time++;
if(time > 250)
{
IIC_Stop();
return 1;
}
}
SCL_LOW();
return 0;
}
// IIC写一个字节
void IIC_Write_Byte(uint8_t dat)
{
uint8_t i;
for(i=0;i<8;i++)
{
SCL_LOW();
HAL_Delay_us(1);
if(dat & 0x80)
SDA_OUT();
else
SDA_OUT();
dat <<= 1;
HAL_Delay_us(1);
SCL_HIGH();
HAL_Delay_us(1);
}
SCL_LOW();
}
// IIC读一个字节
uint8_t IIC_Read_Byte(uint8_t ack)
{
uint8_t i,dat=0;
for(i=0;i<8;i++)
{
SCL_LOW();
HAL_Delay_us(1);
dat <<= 1;
SCL_HIGH();
HAL_Delay_us(1);
if(SDA_IN()) dat |= 0x01;
}
if(ack)
SDA_OUT();
else
SDA_OUT();
HAL_Delay_us(1);
SCL_LOW();
return dat;
}
// AT24C02 单字节写入
void AT24C02_Write_Byte(uint8_t addr, uint8_t data)
{
IIC_Start();
IIC_Write_Byte(AT24C02_ADDR);
IIC_Wait_Ack();
IIC_Write_Byte(addr);
IIC_Wait_Ack();
IIC_Write_Byte(data);
IIC_Wait_Ack();
IIC_Stop();
HAL_Delay(5); // 必须等待烧录
}
// AT24C02 单字节读取
uint8_t AT24C02_Read_Byte(uint8_t addr)
{
uint8_t res;
IIC_Start();
IIC_Write_Byte(AT24C02_ADDR);
IIC_Wait_Ack();
IIC_Write_Byte(addr);
IIC_Wait_Ack();
IIC_Start();
IIC_Write_Byte(AT24C02_ADDR | 0x01);
IIC_Wait_Ack();
res = IIC_Read_Byte(0);
IIC_Stop();
return res;
}
// 页写:一页最多8字节,不要跨页
void AT24C02_Write_Page(uint8_t addr, uint8_t *buf, uint8_t len)
{
uint8_t i;
IIC_Start();
IIC_Write_Byte(AT24C02_ADDR);
IIC_Wait_Ack();
IIC_Write_Byte(addr);
IIC_Wait_Ack();
for(i=0;i<len;i++)
{
IIC_Write_Byte(buf[i]);
IIC_Wait_Ack();
}
IIC_Stop();
HAL_Delay(5);
}
// 批量读取任意长度
void AT24C02_Read_Buf(uint8_t addr, uint8_t *buf, uint8_t len)
{
uint8_t i;
IIC_Start();
IIC_Write_Byte(AT24C02_ADDR);
IIC_Wait_Ack();
IIC_Write_Byte(addr);
IIC_Wait_Ack();
IIC_Start();
IIC_Write_Byte(AT24C02_ADDR | 0x01);
IIC_Wait_Ack();
for(i=0;i<len;i++)
{
if(i == len-1)
buf[i] = IIC_Read_Byte(0);
else
buf[i] = IIC_Read_Byte(1);
}
IIC_Stop();
}
/**
* @brief 基于SysTick滴答定时器的精准微秒延时 (STM32G070 64MHz)
* @param us: 延时微秒数
* @retval 无
*/
void HAL_Delay_us(uint32_t us)
{
uint32_t ticks = 64U * us; // 64MHz = 64个tick = 1us
uint32_t start = SysTick->VAL;
uint32_t elapsed = 0;
while (1)
{
uint32_t now = SysTick->VAL;
// 正常递减
if (now <= start)
{
elapsed += start - now;
}
// 处理溢出(HAL默认LOAD=63999,1ms溢出一次)
else
{
elapsed += (SysTick->LOAD + 1) - now + start;
}
start = now;
if (elapsed >= ticks)
{
break;
}
}
}
应用示例:
// 初始化
IIC_Init();
// 1. 单字节读写
AT24C02_Write_Byte(0x00, 0x55); // 地址0写入0x55
uint8_t val = AT24C02_Read_Byte(0x00);
// 2. 数组批量写入读取
uint8_t wbuf[4] = {11,22,33,44};
uint8_t rbuf[4];
AT24C02_Write_Page(0x10, wbuf, 4);
AT24C02_Read_Buf(0x10, rbuf, 4);


参看资料:
浙公网安备 33010602011771号