蓝桥杯嵌入式 ----“空手套白狼“ 之 IIC--EEPROM读写


前言

本文是基于嵌入式开发板CT117E,stm32f103RBT6。"空手套白狼"就是直接利用官方给的库(v3.5),进行拷贝修改形成可以正常运行的代码。

一、原理图

在这里插入图片描述

二、由原理图得到的信息

  • 获取8位地址: 前四位是固定的1010, 最后一位为0表示写,为1表示读,中间三位对应上面的电路图,E0,E1,E2, 都是接的GND,所以为E0=0,E1=0,E2=0;可以知道M24C02MN6的从设备写地址为10100000(0xa0),读设备地址为10100001(0xa1)。

三、iic对e2prom的读写函数

  1. 给的资源包里面有i2c的驱动源码,所以只需要写e2prom的读和写的函数就可以了。

  2. 我们要了解e2prom的读写时序和他的地址,地址是8位的,最后一位是读写标志,0–写,1–读,其他需要参考原理图进行地址的判断,蓝桥杯的开发板看原理图可以看出,写的时候应该是0xa0,读的时候是0xa1,接下来就是时序的编程,这个需要记住,不能错任何一步;EEPROM一个地址,存入一个字节的数据,所以针对不同类型的数据,需要分离成单个字节的数据;所以地址和数据的变量都是定为u8。

  3. 写的函数较为容易: 开始—发送e2prom的地址(0xa0)—等待回应—发送我们要写的地址—等待回应–发送我们要写入的一个字节数据—等待回应----发出结束信号。


void i2c_write(u8 addr,u8 data)
{
	I2CStart();

	I2CSendByte(0xa0);
	I2CWaitAck();

	I2CSendByte(addr);
	I2CWaitAck();

	I2CSendByte(data);
	I2CWaitAck();

	I2CStop();
}
  1. 读函数: 开始信号—发送e2prom的地址( 0xa0先是写我们要读的地址给它)–等待回应—发送我们要读的地址----等待回应—再次发送开始信号----发送 0xa1(表示要读)—等待回应—接收数据—发送应答信号–结束信号。
u8 i2c_read(u8 addr)
{
	u8 t;
	I2CStart();

	I2CSendByte(0xa0);
	I2CWaitAck();

	I2CSendByte(addr);
	I2CWaitAck();

	I2CStart();

	I2CSendByte(0xa1);
	I2CWaitAck();

	t=I2CReceiveByte();
	I2CWaitAck();

	I2CStop();

	return t;
}

四、存取数据应用

①存取32位的数据

void u32_write(u8 addr,u32 data)
{
	i2c_write(addr,data&0xff);
	Delay_Ms(5);

	i2c_write(addr+1,data>>8&0xff);
	Delay_Ms(5);

	i2c_write(addr+2,data>>16&0xff);
	Delay_Ms(5);

	i2c_write(addr+3,data>>24&0xff);
	Delay_Ms(5);	
}

u32 u32_read(u8 addr)
{	
    u32 t;
	t+=i2c_read(addr);
	Delay_Ms(5);

	t+=(i2c_read(addr+1))<<8;
	Delay_Ms(5);

	t+=(i2c_read(addr+2))<<16;
	Delay_Ms(5);

	t+=(i2c_read(addr+3))<<24;
	Delay_Ms(5);

	return t;

}
u32_write(0x55,14253675);
read_32=u32_read(0x55);

②存取2位小数的浮点型数据

void float_2_write(u8 addr,float data)	   //2位小数的写入
{
	u32 t;
	t=100*data;

	i2c_write(addr,t&0xff);
	Delay_Ms(5);

	i2c_write(addr+1,t>>8&0xff);
	Delay_Ms(5);
	
		
}

float float_2_read(u8 addr)	   //2位小数的读出
{
	float t;
	

	t+=i2c_read(addr);
	Delay_Ms(5);

	t+=(i2c_read(addr+1))<<8;
	Delay_Ms(5);
	
	return t/100;	
}
float_2_write(0x55,100.85);
float_2=float_2_read(0x55);

③存取字符串字符以ASCII码存储

for(i=0;i<sizeof(str_write);i++)       //存
{
	i2c_write(0x10+i,str_write[i]);
	Delay_Ms(5);
}

for(i=0;i<sizeof(str_write);i++)   //取
{
	str_read[i]=i2c_read(0x10+i);
}

④存取负数

  • 负数: 存的时候判断一下是否为符数,是的话,腾出一个地址存放一个标识,例如"-",第二个地址直接存他的相反数,在读的时候进行判断标志,读出后的结果用0减去就行了,达到人为的负数存取效果。
if(minus_write<0)
{
	i2c_write(0x06,'-');
	Delay_Ms(5);
	i2c_write(0x07,-minus_write);  //存正数
	Delay_Ms(5);
}
if(i2c_read(0x06)=='-')
{
	minus_read = 0 - i2c_read(0x07);
}

五、在主函数的应用方法

  • 主函数应用:
if(i2c_read(0x14)!=5)			 //这里按道理说程序只会执行一次;
{
        LCD_DisplayStringLine(Line0,"123456");
	i2c_write(0x14,5);
	Delay_Ms(2);             //这里一定要加延时,cpu的速度太快了,需要等待一下e2PROM
	i2c_write(0x21,0);    //初始化我们要写的地址
	Delay_Ms(2);
}
i2c_num=i2c_read(0x21);
i2c_num++;
i2c_write(0x21,i2c_num);
sprintf((char *)i2c_buff,"i2c_num: %d   ",i2c_num);
LCD_DisplayStringLine(Line0,i2c_buff);
  • 这里有1/256的概率可能会翻车,因为我们一般都需要初始化我们在内存的值为0,这个初始化如果和平时一样,每次掉电重启都会初始化一次,达不到我们要掉电后值不变的效果,而会变成每次都初始化为0,所以这里巧妙地使用读内存的值,如果不是这个值,我们就给内存赋值为这个值,然后顺便在这里初始化我们本来要存的地址的值,这个只会执行一次,但这样设计不太靠谱…
  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值