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 封装
温度范围 商业级 工业级和汽车级

地址意义

在这里插入图片描述

时序图

写操作
在这里插入图片描述
读操作(读之前要进行一边写操作才能获取地址)
在这里插入图片描述

代码

/*
引脚说明
SCL -- PB8
SDA -- PB9

*/

#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");
}

猜你喜欢

转载自blog.csdn.net/weixin_46026429/article/details/108716771