STM32——AT24C02
- 简介
-
- 特点
- 地址意义
- 时序图
- 代码
简介
AT24C02是一个2K位串行CMOS E2PROM, 内部含有256个8位字节,CATALYST公司的先进CMOS技术实质上减少了器件的功耗。AT24C02有一个8字节页写缓冲器。该器件通过IIC总线接口进行操作,有一个专门的写保护功能。
特点
与 400KHz I2C 总线兼容 。
1.8 到 6.0 伏工作电压范围
低功耗 CMOS 技术
写保护功能 当 WP 为高电平时进入写保护状态
页写缓冲器
自定时擦写周期
1,000,000 编程/擦除周期
可保存数据 100 年
8 脚 DIP SOIC 或 TSSOP 封装
温度范围 商业级 工业级和汽车级
地址意义
时序图
写操作
读操作(读之前要进行一边写操作才能获取地址)
代码
#define SCL PBout(8)
#define SDA_IN PBin(9)
#define SDA_OUT PBout(9)
void Iic_Init(void) //IIC引脚配置
{
GPIO_InitTypeDef GPIO_InitStruct; //结构体
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //使能GPIO B组时钟
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; //引脚8 9
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; //输出模式
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //输出推挽
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //输出速度
GPIO_Init(GPIOB, &GPIO_InitStruct);
//总线空闲
SCL = 1;
SDA_OUT = 1;
}
//引脚模式变更
void Iic_Sda_Mode(GPIOMode_TypeDef mode)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //第9号引脚
GPIO_InitStructure.GPIO_Mode = mode; //输入/输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出,增强驱动能力,引脚的输出电流更大
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //引脚的速度最大为100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //没有使用内部上拉电阻
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//启动信号
void Iic_Start(void)
{
Iic_Sda_Mode(GPIO_Mode_OUT);
//总线空闲
SCL = 1;
SDA_OUT = 1;
delay_us(5);
//启动信号
SDA_OUT = 0;
delay_us(5);
SCL = 0;
}
//停止信号
void Iic_Stop(void)
{
Iic_Sda_Mode(GPIO_Mode_OUT);
SCL = 0;
SDA_OUT = 0;
delay_us(5);
SCL = 1;
delay_us(5);
SDA_OUT = 1;
}
//引脚发送一位数据
void Iic_Send_Ack(u8 ack)
{
Iic_Sda_Mode(GPIO_Mode_OUT);
SCL = 0;
//发数据1
if(ack == 1)
{
SDA_OUT = 1; //引脚输出
}
//发数据0
if(ack == 0)
{
SDA_OUT = 0; //引脚输出
}
delay_us(5);
SCL = 1;
delay_us(5);
SCL = 0;
}
//引脚发送一个字节数据
void Iic_Send_Byte(u8 data)
{
u8 i;
Iic_Sda_Mode(GPIO_Mode_OUT);
SCL = 0;
//0 1 1 1 1 0 0 0
for(i=0; i<8; i++)
{
//发数据1
if(data & (1<<(7-i)))
{
SDA_OUT = 1; //引脚输出
}
//发数据0
else
{
SDA_OUT = 0; //引脚输出
}
delay_us(5);
SCL = 1;
delay_us(5);
SCL = 0;
}
}
//接受一位数据
u8 Iic_Rcv_Ack(void)
{
u8 ack;
Iic_Sda_Mode(GPIO_Mode_IN);
SCL = 0;
delay_us(5);
SCL = 1;
delay_us(5);
if(SDA_IN == 1) //引脚为电平为1
{
ack = 1;
}
if(SDA_IN == 0) //引脚为电平为1
{
ack = 0;
}
SCL = 0;
return ack;
}
//接受一个字节数据
u8 Iic_Rcv_Byte(void)
{
u8 i, data = 0; //0 0 0 0 0 0 0 0 比如有数据:1 1 0 0 1 0 0 0
Iic_Sda_Mode(GPIO_Mode_IN);
SCL = 0;
//0 1 1 1 1 0 0 0
for(i=0; i<8; i++)
{
delay_us(5);
SCL = 1;
delay_us(5);
//接受数据
if(SDA_IN == 1) //引脚为电平为1
{
data |= (1<<(7-i));
}
SCL = 0;
}
return data;
}
void AT24c02_Write(u8 addr, u8 *write_buff, u8 len)
{
u8 ack;
//启动信号
Iic_Start();
//发送设备地址
Iic_Send_Byte(0xA0);
ack = Iic_Rcv_Ack();
if(ack == 1)
{
printf("ack failure\n");
return ;
}
//发送写数据起始地址
Iic_Send_Byte(addr);
ack = Iic_Rcv_Ack();
if(ack == 1)
{
printf("ack failure\n");
return ;
}
//数据:hello
while(len--)
{
//发送数据
Iic_Send_Byte(*write_buff);
ack = Iic_Rcv_Ack();
if(ack == 1)
{
printf("ack failure\n");
return ;
}
write_buff++;
}
Iic_Stop();
printf("write finish\n");
}
void AT24c02_Read(u8 addr, u8 *read_buff, u8 len)
{
u8 ack;
//启动信号
Iic_Start();
//发送设备地址
Iic_Send_Byte(0xA0);
ack = Iic_Rcv_Ack();
if(ack == 1)
{
printf("ack failure\n");
return ;
}
//发送写数据起始地址
Iic_Send_Byte(addr);
ack = Iic_Rcv_Ack();
if(ack == 1)
{
printf("ack failure\n");
return ;
}
//启动信号
Iic_Start();
//发送设备地址
Iic_Send_Byte(0xA1);
ack = Iic_Rcv_Ack();
if(ack == 1)
{
printf("ack failure\n");
return ;
}
//数据:hello 5
while(len--)
{
*read_buff = Iic_Rcv_Byte();
if(len > 0)
Iic_Send_Ack(0); //发送有效应答
read_buff++;
}
Iic_Send_Ack(1);
Iic_Stop();
printf("read finish\n");
}