本帖最后由 她叫小红 于 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[6];
- for(i=0;i<6;i++)tbuf=0; //清0
- tbuf[0]=(a>>8)&0XFF; //横滚角
- tbuf[1]=a&0XFF;
- tbuf[2]=(b>>8)&0XFF; //俯仰角
- tbuf[3]=b&0XFF;
- tbuf[4]=(c>>8)&0XFF; //航向角
- tbuf[5]=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[4]; //四字节数组
- float floatVal; //四个字节
- long longVal; //四个字节
- }val;
复制代码 代码二:- /*----------写float---------*/
- void sendFloat(float value){ //该函数的作用是发送一个单精度浮点型数据给上位机
- writeSerial(2); // 2 float //mBot固件协议:返回帧的功能字,2表示后面的数据是float型
- val.floatVal = value; //赋值
- writeSerial(val.byteVal[0]);
- writeSerial(val.byteVal[1]);
- writeSerial(val.byteVal[2]);
- writeSerial(val.byteVal[3]);
- }
复制代码 在union 中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所有的数据成员具有相同的起始地址,而一个union 只配置一个足够大的空间以来容纳最大长度的数据成员。
代码一定义一个union类型的数据val,可以看出val中的各类数据长度都是一样的:4Byte。在代码二中当val.floatVal 被赋予初值是,由于val.floatVal与val.byteVal具有相同的起始地址,此时val.byteVal[0]表示的是val.floatVal在内存中存储的最低字节(小端模式),这里可以理解为byteVal数组中存储的是数据floatVal在内存中的存储数据。更多详细关于union的知识可以参考:http://c.biancheng.net/cpp/html/450.html 下面看一段测试程序: - #include <Arduino.h>
- union{
- byte byteVal[4];
- float floatVal;
- }val;
- void sendFloat(float value){
- //Serial.write(2); // 2 float
- val.floatVal = value;
- Serial.write(val.byteVal[0]);
- Serial.write(val.byteVal[1]);
- Serial.write(val.byteVal[2]);
- Serial.write(val.byteVal[3]);
- }
- 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,希望能帮到大家~
感谢无私奉献的网友们~
|