蓝桥杯嵌入式快速通关篇,IIC通讯及EEPROM

目录

基本部分

IIC及EEPROM在蓝桥杯中的考法

举例:
第九届省赛


第七届省赛


第六届省赛
在ct1117e上的EEPROM的通常使用方法就如上图所示 扩展板上还有三轴加速度计使用iic通讯,这里我们稍微提一下,其使用的通讯方式还是iic通讯。只不过使用的地址和要读取的寄存器有所不同(使用扩展板时,IIC引脚也要相应改变。

IIC的基本使用方法

在赛点资源包中是由iic的驱动文件的,省赛的一般在如下路径

赛点资源数据包_嵌入式_2019\3-底层驱动代码参考\i2c.c

使用时将i2c.h,和i2c.c两个文件复制到工程里,并在i2c.c文件末尾写上自己的读写函数,代码如下:

void i2c_write(u8 add ,u8 reg ,u8 data){
	I2CStart();
	
	I2CSendByte(add);
	I2CWaitAck();
	
	I2CSendByte(reg);
	I2CWaitAck();
	
	I2CSendByte(data);
	I2CWaitAck();
	
	I2CStop();
	
}

u8 i2c_read(u8 add ,u8 reg){
	u8 data ;
	I2CStart();
	I2CSendByte(add);
	I2CWaitAck();
	
	I2CSendByte(reg);
	I2CWaitAck();
	I2CStart();
	I2CSendByte(add+1);
	I2CWaitAck();
	data =I2CReceiveByte();
	I2CWaitAck();

	I2CStop();
	return data;
	
	
}
	

第一个函数void i2c_write(u8 add ,u8 reg ,u8 data);
是iic通讯的写函数,第一个 add是设备的地址,如0xa0是EEPROM的地址,0x38 是扩展板上的三轴加速度计的通讯地址。
第二个形参是寄存器的地址,需要注意的是AT24C02的地址是从0x00~0xff,如果超出该地址值会出现错误。地址和写入或读取的数据的类型都是无符号字符型,其他类型的数据有可能出现错误。就是说,但个地址存入读出的值不会超过255,即存取的的数据范围是0 ~255,那我们如何存入更大范围的数据呢,这个我在后面会介绍。
第二个函数是
u8 i2c_read(u8 add ,u8 reg)
在指定的从机的指定第地址中读取一个字节数据,add是从机地址,reg是寄存器地址。
以上代码能理解就结合文档中的时序图理解,不好理解的话直接背下来也是可以的,自己多敲几遍就好了,关键要熟练。
为了帮助理解,可以参考这篇文章
iic的读取时序问题

代码需要注意的点(出现问题也可依次检查)

读取的操作结束后,都建议延迟几毫秒,实测如果不延迟数据极有可能会出错,延迟操作可以加到函数末尾,也可在函数调用后。

调用函数之前,要先使用i2c.c文件中已有的函数i2c_init()来初始化iic要使用到的时钟,引脚等。

读写函数并不能直接存取超过范围的数,如果存入的数不在0到255之间,肯定会出错,地址也一样,要注意范围。

在读取iic的值时,需要再进行一次I2CStart(),不然读取的值也可能会出错!
在这里插入图片描述

应用部分

简单应用

存取标志位,阈值等:

u8 flag=0;//也可以是0-255的数,不能超范围
i2c_write(0xa0,0,flag);
//0xa0 是从机的通讯地址,0 是寄存器的地址,这里取0 ~0xff的范围都可以
//读取时
flag=i2c_write(0xa0,0,flag);

进阶应用

存取更大的数,比如无符号16进制数,范围是0-65535

u16 data;
u8 data_h,data_l;
data_h=(data&0xff00)>>8;
data_l=data&0x00ff;
i2c_write(0xa0,0,data_h);
Delay_Ms(5);
i2c_write(0xa0,1,data_l);
Delay_Ms(5);
//即分别取出数据的高八位和低八位,,分别存入两个地址。
//读取
data_h=i2c_read(0xa0,0);
Delay_Ms(5);
data_l=i2c_reaad(0xa0,1);
Delay_Ms(5);
data=((u16)data_h<<8)|data_l;

实际上,更大的数,或者浮点数都可以用类似的方法储存,只是就更为繁琐了,下面给出一种更为通用的方法。

存取结构体,在结构体中就可以放各种类型的数据了,不管是多大的数,是整型,浮点,还是数组,都可以放到一起,具体代码如下:

//先定义两个函数,来存取数组
void writebuffer(u8 *buffer ,int len){
	int i=0 ;
	for(i=0;i<len;i++){//用循环将数组传入,读也一样,
		i2c_write(0xa0,i,buffer[i]);
		Delay_Ms(5);
	}

}
void readbuffer(u8 *buffer ,int len){
	int i=0;
	for(i=0;i<len;i++){
		buffer[i]=i2c_read(0xa0,i);
		Delay_Ms(5);
	}
}

//要存储的结构体
typedef struct{
	u8 data1;
	int data2;
	float data3;
}Data;

Data data_tosave={0,-1,2.2};
u8 length=sizeof(Data);
u8 buffer[length];
memcpy(buffer,&data_tosave,length)//将结构体的数据拷贝到buffer中
writebuffer(buffer,length);//保存数据
readbuffer(buffer,length);//读取数据

其关键思想是将结构体的数据拷贝到一个数组中,再依次存储和读去,当然,代码量较大,没有必要还是尽量不要使用。

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值