利用union传递不同类型数据
本帖最后由 她叫小红 于 2016-12-10 15:50 编辑在下位机在与上位机进行通信的时候,通常遇到传输不同类型数据的情况,比如:“char”、“int”、“float”等等,而在用串口接收时,由于硬件限制,一次只能接收8bit,给传输造成不便。
以前在学习6050时用到“匿名上位机”时,采用的是移位的方式,将一个长的数据右移8位并截取低8位的形式进行传输的,例如:
void usart1_report_0x05(u16 a,u16 b,u16 c)
{
u8 i,tbuf;
for(i=0;i<6;i++)tbuf=0; //清0
tbuf=(a>>8)&0XFF; //横滚角
tbuf=a&0XFF;
tbuf=(b>>8)&0XFF; //俯仰角
tbuf=b&0XFF;
tbuf=(c>>8)&0XFF; //航向角
tbuf=c&0XFF; //上锁与否
usart1_niming_report(0X05,tbuf,6); //功能字
}而在mBlock固件中采用的是另一种方式,让我感到“要学习的东西真不少”了,先看两小段代码: 代码一://使用共用体数据结构实现short、float、double 向 char 转换,精妙!!学习了
/*--------单精度浮点型--------*///Datatype for floating-point numbers, a number that has a decimal point.
union{
byte byteVal; //四字节数组
float floatVal; //四个字节
long longVal; //四个字节
}val; 代码二:/*----------写float---------*/
void sendFloat(float value){ //该函数的作用是发送一个单精度浮点型数据给上位机
writeSerial(2); // 2 float //mBot固件协议:返回帧的功能字,2表示后面的数据是float型
val.floatVal = value; //赋值
writeSerial(val.byteVal);
writeSerial(val.byteVal);
writeSerial(val.byteVal);
writeSerial(val.byteVal);
} 在union 中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所有的数据成员具有相同的起始地址,而一个union 只配置一个足够大的空间以来容纳最大长度的数据成员。
代码一定义一个union类型的数据val,可以看出val中的各类数据长度都是一样的:4Byte。在代码二中当val.floatVal 被赋予初值是,由于val.floatVal与val.byteVal具有相同的起始地址,此时val.byteVal表示的是val.floatVal在内存中存储的最低字节(小端模式),这里可以理解为byteVal数组中存储的是数据floatVal在内存中的存储数据。更多详细关于union的知识可以参考:http://c.biancheng.net/cpp/html/450.html 下面看一段测试程序:#include <Arduino.h>
union{
byte byteVal;
float floatVal;
}val;
void sendFloat(float value){
//Serial.write(2); // 2 float
val.floatVal = value;
Serial.write(val.byteVal);
Serial.write(val.byteVal);
Serial.write(val.byteVal);
Serial.write(val.byteVal);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
sendFloat(-575);
}
void loop() {
// put your main code here, to run repeatedly:
}
上面的代码实现的是:Arduino复位后将内存中存储的数据“-575”打印到串口,打印出的数据是:00 C0 0F C4
由于是小端模式,-575存储在内存中正确的顺序应该是:C4 0F C0 00(11000100 00001111 11000000 00000000)。
这里涉及到数据在Arduino内存中的存储格式,以单精度浮点型为例:浮点在内存中的存储类似于科学记数法,一般形式为:
R = M * 2^ e
(R : real;M: 位数小数点前“1”被省略 ; e : 阶码,小数点移动位数,大于0右移,反之,左移)
其在内存中的表现形式为:
x x...x x...x...x...x
数符(1b) 阶码(8b) 尾码(23b)
则:-575 = 1 10001000 00011111 10000000 0000000
-575 = 负数 136-127= 9 1.000 1111 11
将1.000 1111 11小数点右移9位即可得到该数的绝对值,又因其数符为1,表示这是数为负,最后结果为:- 10 0011 1111 即 -575。更多详细关于float在内存中的存储格式的知识可以参考:http://www.cnblogs.com/dolphin0520/archive/2011/10/02/2198280.html
学习mBot的固件还是挺有收获的,最后附上固件一份里面写了一些注释,但不是很全o,希望能帮到大家~
感谢无私奉献的网友们~
页:
[1]