IIC通信中接受和发送float、int数据类型

最近学IIC通信的时候发现一个问题,IIC通信(包括某些串口通信、SPI通信),接受和发送数据都是以字节为单位的。如果要发送的是u8的数据那还好说,对于int(2kb)和float(4kb)的话就比较麻烦了,需要把他们拆成许多单字节数据逐个发送,接收的时候再把这些单字节数据拼起来。
怎么拆拼呢,笔者这里想到了三种方法(可以直接看第三种方法

1.用类似于atof和atoi的函数,把int型或float型变成字符串发出去,接收的时候再变回来。

具体怎么操作比较简单,就不说了。这里谈一下这种方法的缺点。一是耗费内存,一个u16的数据,范围是-32768~32767,也就是说,一个两字节的数据“-32768”在传输过程中变成了六字节的字符串“-32768”,float型更甚。这样传输速度肯定是变慢的,内存占用可能也会大好多。二是从读到这个数据开始,要读几位才能读完,这是不确定的,需要加个终止位吗?反正处理起来就很麻烦。

2.把原数据切成几个u8型的数据,然后依照int型和float型的内存储存方式拼回去。

举个例子,16 =0000 0000 0001 0000,那就切成两个u8:c1 = 0000 0000,c2 = 0001 0000,分别发送过去,然后那边接收到的就是 (c1 << 8) + c2。这种方法看起来好像还挺好的,然后我就兴致勃勃的把int型的转化写了,需要注意的是由于符号位的存在,要先把原数据的补码变成原码,然后拆分成u8,然后拼起来,然后再变成原码。int型就挺麻烦的,不过也还好,但是处理float的时候我真的就要裂开了,有兴趣可以试一下,那个指数位的处理是真的反人类。

3.把原数据切成几个u8的数据,然后用memcpy()函数来拼

在查资料的时候我发现了一个宝藏函数(好吧是我C语言太蔡了,之前没接触过这类内存处理函数)

memcpy函数
原型:void * memcpy(void dest, const void src,unsigned int count);
功能:由src所指内存区域复制count个字节到dest所指内存区域。
说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。

比如说memcpy(p_char,p_int,2)就可以把p_int所指向的内存区域,复制两个字节,然后粘贴到p_char的内存区域上,(我真的傻,我单单知道strcpy可以copy字符串,竟然想不到内存函数也有相似的copy函数)。这样的话就不用处理方法2中的反人类问题了。
话说够了,直接贴代码。

int型 --> char型

char *int2char(int x)
{
	char *p_Char;
	p_Char = (char *)malloc(sizeof(int));
	memcpy(p_Char, &x, sizeof(int));
	return p_Char;
}

char型 --> int型

int char2int(char *p)
{
	int *p_Int;
	p_Int = (int *)malloc(sizeof(int));
	memcpy(p_Int, p, sizeof(int));
	int x = *p_Int;
	free(p_Int);
	return x;
}

float型 --> char型

char *float2char(float x)
{
	char *p;
	p = (char *)malloc(sizeof(float));
	memcpy(p, &x, sizeof(float));
	return p;
}

char型 --> float型

float char2float(char *p)
{
  float *p_Int;
  p_Int = (float *)malloc(sizeof(float));
  memcpy(p_Int, p, sizeof(float));
  float x = *p_Int;
  free(p_Int);
  return x;
}

需要注意的是malloc申请内存空间后,一定要在用完后free掉,我就是在测试的时候一时兴起,写了个1e7层的循环,结果忘了free掉,电脑直接崩掉了(雾…)

下面是一个两块Arduino的板子间IIC传递float型数据的实例

主机程序

#include <Wire.h>

void setup() {

  Wire.begin();

}
float x = -10;
void loop() {
  
  Wire.beginTransmission(4);
  char *p1 = float2char(x);
  Wire.write(p1,sizeof(float));
  free(p1);
  Wire.endTransmission();
  delay(500);
  x = x + 0.1;
}
char *float2char(float x)
{
  char *p;
  p = (char *)malloc(sizeof(float));
  memcpy(p, &x, sizeof(float));
  return p;
}

从机程序

#include <Wire.h>
void setup() {
  Wire.begin(4);
  Wire.onReceive(Event1);
  Serial.begin(9600);

}

void loop() {
  delay(100);
}
void Event1(int n)
{
  char c;
  int j;
  char *p1 =(char *) malloc(sizeof(float));
  for(j = 0;j < sizeof(float);j++)
  {
    *(p1 + j) = Wire.read();
    //Serial.println(Wire.available());
  }
    
  float x = char2float(p1);
  Serial.println(x);
  free(p1);
}

float char2float(char *p)
{
  float *p_Int;
  p_Int = (float *)malloc(sizeof(float));
  memcpy(p_Int, p, sizeof(float));
  float x = *p_Int;
  free(p_Int);
  return x;
}

在从机的串口监视器中观察到:

在这里插入图片描述
看起来是没有什么问题的

以上

废话虽多,码字不易,转载请注明出处啦!

  • 9
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值