STM32学习笔记——I2C——void*的作用(写入浮点型数据到EEPROM)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

STM32F103ZET6学习笔记
I2C读写EEPROM,写入long double类型,野火教程里写了通过(void*)实现long double类型数据的读/写。本篇用于分析这样写的理由

主函数

long double DATA_WRITE_32_BUFFER[4] ={12.56,77.89,-11.5,0.01};
long double DATA_READ_32_BUFFER[4] 	={0};
#define Add32 0
int main(void)	
{
	USART1_INIT();
	AT24CXX_Init();
	while(1)
	{
		if(!AT24CXX_Check())
		{	
			printf("\r\nAT24C02存在,且标志位为:0x%x\r\n",AT24CXX_ReadLenByte(255,1));
			printf("\r\n现在开始写入数据!\r\n");

			AT24CXX_Write(Add32,(void*)DATA_WRITE_32_BUFFER,sizeof(DATA_WRITE_32_BUFFER));
			printf("\r\n数据写入完成!\r\n");
			printf("\r\n开始读出数据!\r\n");
			AT24CXX_Read(Add32,(void*)DATA_READ_32_BUFFER,sizeof(DATA_READ_32_BUFFER));
			
			for(num = 0;num<4 ;num++)
			{
				printf("\r\DATA_READ_32_BUFFER[%d] = %Lf\r\n",num,DATA_READ_32_BUFFER[num]);
			}
			printf("\r\n输出已结束!\r\n");
		}
		else
		{
			printf("这是第一次运行程序,标志位已写入,请按复位键重新开始!");
		}	
		while(1);
	}
}

写函数

//在AT24CXX里面的指定地址开始写入指定个数的数据
//WriteAddr :开始写入的地址 对24c02为0~255
//pBuffer   :数据数组首地址
//NumToWrite:要写入数据的个数
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
	while(NumToWrite--)
	{
		AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
		WriteAddr++;
		pBuffer++;
	}

}
读函数

//在AT24CXX里面的指定地址开始读出指定个数的数据
//ReadAddr :开始读出的地址 对24c02为0~255
//pBuffer  :数据数组首地址
//NumToRead:要读出数据的个数
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{
	while(NumToRead)
	{
		*pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);	
		NumToRead--;
	}
}  

以上写入和读取代码来自正点原子

void*作用

下面这篇博客详细的讲述了各类型指针的本质区别:不同指针的跳跃力不同
在这里插入图片描述

https://blog.csdn.net/yangbodong22011/article/details/53224856

long double BUFFER[] = {255.63,553.98};

long double类型占用8个字节(STM32中),那么数组BUFFER中,每一个数据都占据8个字节。那么这个BUUFER一共占据16个字节。
但EEPROM一次只能写入1个字节,然后接下来的数据就要放到下一个地址,所以需要8个地址才能写完。

AT24CXX_Write(Add32,(void*)DATA_WRITE_32_BUFFER,sizeof(DATA_WRITE_32_BUFFER));

但是写完一个字节,地址会+1,这时候,指针会直接跳8个字节,指向下一个数据的地址,因为long double类型的数据就是8个字节,所以第一个数据仅仅写了1/8,就跳过了

void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
	while(NumToWrite--)
	{
		AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
		WriteAddr++;
		pBuffer++;
	}

所以我们希望,在写入数据的时候,能把指针类型改变一下,变成一次仅跳过一个字节AT24CXX_Write里的是u8*,这样每次地址+1,会继续读取第一个数据的第二个字节,一直读完8个字节,这样我们一个8个字节的数据就存在EEPROM的8个地址内了。
同时如果我们直接将long double类型的数组传进去**,会报错,指针类型不匹配**
所以我们可以直接将long double类型的数组强制转换为(void*)void*可以兼容不同类型的指针,这样传进去后,经过u8转换为跳跃力为1个字节的指针,这样就可以读取每一个字节,不会跳过某些字节。

读数据时也一样,我们是一个字节一个字节的读出来的,同时放到我们所定义的数组里,由于我们的数组时是long double类型的,所以输出时,会按8个字节为一个数据来输出。

AT24CXX_Read(Add32,(void*)DATA_READ_32_BUFFER,sizeof(DATA_READ_32_BUFFER));
//在AT24CXX里面的指定地址开始读出指定个数的数据
//ReadAddr :开始读出的地址 对24c02为0~255
//pBuffer  :数据数组首地址
//NumToRead:要读出数据的个数
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{
	while(NumToRead)
	{
		*pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);	
		NumToRead--;
	}
}  

这样就实现了多字节数据的写入与读取.

总结

本质上就是进行了**数据格式转换,**因为写入的时候指针为u8类型,若传入其他类型指针,一定会报错,所以void*的兼容性很好的处理了这个问题。所以我们也可以把void*变为u8*,这样也是可以的,但是void*更加具有通用性。
void*可以解决第一和第二步

  1. 写入的时候按照一个字节一个字节的写入
  2. 读的时候一个字节一个字节读出
  3. printf时我们用我们想要的数据格式来输出,比如8个字节、4个字节等等
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值