串口通讯中传递的数据格式不外两种:ASCII码(即可见字符形式)和二进制数据格式(对应Modbus协议中有ASCII模式和RTU模式)。最初的想法是把浮点数的各位分别提取出来,保存成一个各元素都是ASCII码的数组,然后通过串口发送出去,对方接收到这个数组后再相应地组合成原来的浮点数。这是以前写过的一段代码:
//>>>>>>>>>>>>#### // 函数名:void Float2Char(float Value,char *array)
// 描 述:将浮点数的各个位的数值转换成字符串,通过串口发送至上位机显示
// 参 数:float Value为欲转换的正数浮点数值,转换结果保存在字符数组*array里
//>>>>>>>>>>>>####
void Float2Char(float Value,char *array)
{
Uint16 IntegerPart;
float DecimalPart;
Uint16 i = 0;
//>>>>>>>>>>>>#### // 函数名:void Float2Char(float Value,char *array)
// 描 述:将浮点数的各个位的数值转换成字符串,通过串口发送至上位机显示
// 参 数:float Value为欲转换的正数浮点数值,转换结果保存在字符数组*array里
//>>>>>>>>>>>>####
void Float2Char(float Value,char *array)
{
Uint16 IntegerPart;
float DecimalPart;
Uint16 i = 0;
Uint16 j = 0;
char temp;
//分离整数部分与小数部分:
//整数部分保存在IntegerPart中
//小数部分保存在DecimalPart中
if (Value>=1)
{
IntegerPart = (Uint16)Value;
DecimalPart = Value-IntegerPart;
}
else
{
IntegerPart = 0;
DecimalPart = Value-IntegerPart;
char temp;
//分离整数部分与小数部分:
//整数部分保存在IntegerPart中
//小数部分保存在DecimalPart中
if (Value>=1)
{
IntegerPart = (Uint16)Value;
DecimalPart = Value-IntegerPart;
}
else
{
IntegerPart = 0;
DecimalPart = Value-IntegerPart;
}
//转换整数部分
if (IntegerPart == 0)
{
array[0] = 0+48;
array[1] = '.';
i = 1;
}
else
{
while(IntegerPart>0)
{
array[i] = IntegerPart%10+48;
//转换整数部分
if (IntegerPart == 0)
{
array[0] = 0+48;
array[1] = '.';
i = 1;
}
else
{
while(IntegerPart>0)
{
array[i] = IntegerPart%10+48;
IntegerPart = IntegerPart/10;
i++;
}
i--;
//修正转换结果的顺序
for (j=0;j+1<=(i+1)/2;j++)
i++;
}
i--;
//修正转换结果的顺序
for (j=0;j+1<=(i+1)/2;j++)
{
temp = array[j];
array[j] = array[i-j];
array[i-j] = temp;
}
i++;
array[i] = '.';
}
temp = array[j];
array[j] = array[i-j];
array[i-j] = temp;
}
i++;
array[i] = '.';
}
//转换小数部分,此处设置最多转换到第四位小数
i++;
array[i++] = (Uint16)(DecimalPart*10)%10+48;
array[i++] = (Uint16)(DecimalPart*100)%10+48;
array[i++] = (Uint16)(DecimalPart*1000)%10+48;
// if (5 == i)
array[i++] = (Uint16)(DecimalPart*10000)%10+48;
array[i] = '\0'; //结束符
}
// End of line
这段代码没有考虑负数的转换,要转换带符号数只需加入符号判断后将正(负)号标志放
在数组的第一位即可。这段函数用起来挺好用,但是这种方法有很多不完善的地方,比如要预先设置字符数组*array的大小以足够存储转换后的各位,小数点位置不确定,给接收方还原数据带来了麻烦。
硬件存储浮点数,统一的标准是IEEE754标准,因此更好的方法是通过这个统一的标准来实现串口传送浮点数据的转换和还原。嵌入式硬件使用的float型数据即单精度32位浮点数格式,这在一般应用中已经足够。IEEE754规定了32位数据的格式,分别规定1位符号位、23位尾数位和数组格式字符串转数组8位指数位(不知有没有记错?)。比如浮点数34.9,IEEE754标准十六进制显示是0x42 0x0B 0x99 0x9A,二进制显示则是 0 10000100 00010111001100110011010。我最初的想法是根据这个标准规定的各部分位数,写出转换和还原的代码来;但这样确实太麻烦了。因此何妨直接借助编译器来实现这个转换??这样多方便啊
以下的代码我没有直接写,直接借用了这篇博客文章(blog.sina/s/blog_4b94ff130100ejyb.html)里的程序:
/*******************************************
函数名称:Float2Byte
硬件存储浮点数,统一的标准是IEEE754标准,因此更好的方法是通过这个统一的标准来实现串口传送浮点数据的转换和还原。嵌入式硬件使用的float型数据即单精度32位浮点数格式,这在一般应用中已经足够。IEEE754规定了32位数据的格式,分别规定1位符号位、23位尾数位和数组格式字符串转数组8位指数位(不知有没有记错?)。比如浮点数34.9,IEEE754标准十六进制显示是0x42 0x0B 0x99 0x9A,二进制显示则是 0 10000100 00010111001100110011010。我最初的想法是根据这个标准规定的各部分位数,写出转换和还原的代码来;但这样确实太麻烦了。因此何妨直接借助编译器来实现这个转换??这样多方便啊
以下的代码我没有直接写,直接借用了这篇博客文章(blog.sina/s/blog_4b94ff130100ejyb.html)里的程序:
/*******************************************
函数名称:Float2Byte
功 能:浮点数转换成字节型数组
参 数:入口参数floatNum,欲转换的浮点数
返 回 值:byteArry,转换后的字节数组
********************************************/
void Float2Byte(float floatNum,unsigned char* byteArry)
{
char* pchar=(char*)&floatNum;
for(int i=0;i<sizeof(floatNum);i++)
{
*byteArry=*pchar;
pchar++;
byteArry++;
}
}
参 数:入口参数floatNum,欲转换的浮点数
返 回 值:byteArry,转换后的字节数组
********************************************/
void Float2Byte(float floatNum,unsigned char* byteArry)
{
char* pchar=(char*)&floatNum;
for(int i=0;i<sizeof(floatNum);i++)
{
*byteArry=*pchar;
pchar++;
byteArry++;
}
}
/*******************************************
函数名称:Byte2Float
功 能:字节型(16进制格式)转换成浮点数
参 数:入口参数*byteArry,转换成的字节数组,每四个字节转换成一个单精度浮点数
返 回 值:转换后的浮点数
********************************************/
float Byte2Float(unsigned char* byteArry)
{
return *((float*)byteArry);
}
// End of line
将以上的代码应用到MSP430单片机的串口通讯中,成功实现了430单片机与PC机通过串口进行浮点数据的传送。PC机的串口发送和接收代码,可直接根据上述程序修改。
后来我想将Modbus协议移植到TMS320F28x的DSP上,但上述浮点数转换还原代码却不能
函数名称:Byte2Float
功 能:字节型(16进制格式)转换成浮点数
参 数:入口参数*byteArry,转换成的字节数组,每四个字节转换成一个单精度浮点数
返 回 值:转换后的浮点数
********************************************/
float Byte2Float(unsigned char* byteArry)
{
return *((float*)byteArry);
}
// End of line
将以上的代码应用到MSP430单片机的串口通讯中,成功实现了430单片机与PC机通过串口进行浮点数据的传送。PC机的串口发送和接收代码,可直接根据上述程序修改。
后来我想将Modbus协议移植到TMS320F28x的DSP上,但上述浮点数转换还原代码却不能
正确运行。经调试后很快发现问题,MSP430单片机的开发环境IAR C430里规定的Char(Unsigned char )类型是1个字节(8位),而28x的开发环境CCS里规定的Char(Unsigned char )类型是双字节(16位)。知道这点后,改动起来也很容易:
//定义一个unsigned char型的临时数组,用来保存接收到的十六进制字节
unsigned char temp_char[2];
float FloatNum;
//将接收到的信号参数解码,按IEEE754浮点数标准还原
//假设DSP的SCI接收到的4个字节依次保存在RxBuffer[1]~ RxBuffer[4]里
temp_char[0] = RxBuffer[2]<<8 | RxBuffer[1];
temp_char[1] = RxBuffer[4]<<8 | RxBuffer[3];
//还原成原来的浮点数
FloatNum = *((float*)temp_char);
好了,问题解决了。</sizeof(float);i++)
//定义一个unsigned char型的临时数组,用来保存接收到的十六进制字节
unsigned char temp_char[2];
float FloatNum;
//将接收到的信号参数解码,按IEEE754浮点数标准还原
//假设DSP的SCI接收到的4个字节依次保存在RxBuffer[1]~ RxBuffer[4]里
temp_char[0] = RxBuffer[2]<<8 | RxBuffer[1];
temp_char[1] = RxBuffer[4]<<8 | RxBuffer[3];
//还原成原来的浮点数
FloatNum = *((float*)temp_char);
好了,问题解决了。</sizeof(float);i++)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论