最近学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;
}
在从机的串口监视器中观察到:
看起来是没有什么问题的
以上
废话虽多,码字不易,转载请注明出处啦!