在与串口通信时,我需要给串口发送指定报文格式的命令,在接收到串口返回的数据后需要转换成浮点数并且显示出来。这里讲一下我自己碰到的问题,以及我发现的解决方法,如果大家有更好的方法可以在下方留言一起讨论。
为了模拟真实的串口通信环境,我这里是用自己写的软件和在网上下载的串口助手进行数据交互。由串口助手发送"42F6CCCD",在自己写的窗口中转换成浮点数并显示。然而本应该显示"123.4",但是显示出来却变成"6.27543e-41",显然肯定是有问题的。
QByteArray strhex = my_serialport->readAll();
qDebug()<<strhex;
//输出"B\xF6\xCC\xCD"
经过排查我发现如果将读取的数据直接打印出来会输出"B\xF6\xCC\xCD",然后按照Qt中十六进制的表示方法应该是"x42\xF6\xCC\xCD"。
我尝试输入不同的数据,发现当高位字节为"2~6"时打印出来的数据就会出错,但是在网上也没有找到类似的问题,于是换了一种思路,将读取的数据按字节转换为十六进制。
这里先放出在网上找到的十六进制转换的函数:
char MainWindow::ConvertHexChar(char ch)//十六进制转换工具
{
if((ch >= '0') && (ch <= '9'))
return ch-0x30;
else if((ch >= 'A') && (ch <= 'F'))
return ch-'A'+10;
else if((ch >= 'a') && (ch <= 'f'))
return ch-'a'+10;
else return (-1);
}
QString MainWindow::hexToDec(QString strHex)//十六进制转十进制
{
int i;
int v = 0;
for(i=0;i<strHex.length();i++)
{
v*=16;
v+=ConvertHexChar(strHex[i].toLatin1());
}
return QString::number(v);
}
QString MainWindow::Hex2Float(QString strHex)//转浮点数
{
//strHex = strHex.right(4)+strHex.left(4);
int c = hexToDec(strHex).toInt();
float d = *(float*)&c;
QString strFloat = QString("%1").arg(d);
return strFloat;
}
这里借鉴了QDataStream对二进制读写的方式,用atEnd()来遍历整个数据流,并按字节数转换:
//把读到的数据储存在QByteArray类的requestData里
requestData = my_serialport->readAll();
//转换成QDataStream数据流格式
QDataStream hexData(&requestData,QIODevice::ReadWrite);
QString temp,hexRecv;
//遍历数据流
while(!hexData.atEnd())
{
qint8 outChar = 0;
//每字节填充一次,直到结束
hexData>>outChar;
//arg(a,b,c,QLatin1Char('0'))
//a表示要处理的数字,b表示字宽,c表示数字基数,QLatin1Char('0')其余由0补充
temp = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0'));
//每次转换一个字节,放到新的字符串后面
hexRecv=hexRecv.append(temp.toUpper());
}
//打印转成浮点数的数据
QString hex2float=Hex2Float(hexRecv);
这样可以保证十六进制的数据可以正常读取,并且可以正确转换为浮点数。