串口通信中,上位机读取的16进制数据(可能是正数也可能是负数也可能是浮点数)转10进制数,及下发数据转16进制字符串数据
16进制字符串转2进制字符串 ,再经过2进制字符串转不同的类型
string CReadEncDlg::strHexTostrBin(string s)
{
string res;
for (int i = 0; i < s.size(); ++i)
{
switch (s[i])
{
case '0': res += "0000"; break;
case '1': res += "0001"; break;
case '2': res += "0010"; break;
case '3': res += "0011"; break;
case '4': res += "0100"; break;
case '5': res += "0101"; break;
case '6': res += "0110"; break;
case '7': res += "0111"; break;
case '8': res += "1000"; break;
case '9': res += "1001"; break;
case 'A':
case 'a': res += "1010"; break;
case 'B':
case 'b': res += "1011"; break;
case 'C':
case 'c': res += "1100"; break;
case 'D':
case 'd': res += "1101"; break;
case 'E':
case 'e': res += "1110"; break;
case 'F':
case 'f': res += "1111"; break;
}
}
return res;
}
//16进制字符串转int类型
int CReadEncDlg::strHexToInt(string s)
{
//应该是32bit
string sBin = strHexTostrBin(s);
//查询最高位是否为1,为1则说明是负数
//为0说明是正整数
int iNum=0;
iNum -= (sBin.at(0)-48) * (1<<31);
for (int i=1;i<32;++i)
{
iNum+= (sBin.at(i) - 48) * (1<<(31-i));
}
return iNum;
}
//16进制字符串转uint类型
unsigned int CReadEncDlg::strHexToUInt(string s)
{
//应该是32bit
string sBin = strHexTostrBin(s);
//查询最高位是否为1,为1则说明是负数
//为0说明是正整数
unsigned int iNum = 0;
for (int i = 0; i < 32; ++i)
{
iNum += (sBin.at(i) - 48) * (1 << (31 - i));
}
return iNum;
}
//16进制字符串转short类型
short CReadEncDlg::strHexToShort(string s)
{
//应该是16bit
string sBin = strHexTostrBin(s);
//查询最高位是否为1,为1则说明是负数
//为0说明是正整数
short iNum = 0;
iNum -= (sBin.at(0) - 48) * (1<<15);
for (int i = 1; i < 16; ++i)
{
iNum += (sBin.at(i) - 48) * (1<<(15 - i));
}
return iNum;
}
float CReadEncDlg::strHexToFloat(string s)
{
//应该是32bit
string sBin = strHexTostrBin(s);
//为0说明是正整数
float fNum = 0;
//符号位
int iSig =(sBin.at(0) - 48)?-1:1;
//指数位
int iE = 0;
for (int i = 1; i < 9; ++i)
{
iE += (sBin.at(i) - 48) * 1<<(8 - i);
}
//有效位
float fVal = 1;
for (int i = 9; i < 32; ++i)
{
fVal += (sBin.at(i) - 48.) / (1 << (i -8));
}
fNum = iSig * fVal* pow(2, (iE - 127));
return fNum;
}
stoi 或者strol 虽然可以把16进制字符串转为整形,但是不带负号的16进制的负数却不好用,好像是个bug,所以笔者将16进制字符串后,再处理二进制数据,按数据类型的存储逻辑进行编译。
32bit整形 ,16位整型,32位浮点数转16进制字符串
void CReadEncDlg::SetSwingLength(float fVal, short iCount)
{
if (fabs(fVal)<0.01)
{
fVal = lpED->dSwingLength;
}
//浮点数转16进制字符串,将浮点数内存数据复制到一个int类型中,然后将int输出16进制字符串既可
int iVal{ 0 };
memcpy(&iVal, &fVal, sizeof(float));
char ch[9] = {'\0'};
sprintf_s(ch, "%08X", iVal);
if (iCount==0)
{
iCount = lpED->iSwingCount;
}
//16bit整形转 16进制字符串 直接转为4个字符的16进制字符串
char chCount[5] = { '\0' };
sprintf_s(chCount, "%04X", iCount);
CString temp;
temp.Format("%%01#WDD3250632509%c%c%c%c0000%c%c%c%c%c%c%c%c**\r",
chCount[2], chCount[3], chCount[0], chCount[1],ch[6], ch[7], ch[4], ch[5], ch[2], ch[3], ch[0], ch[1]);
m_SerialPort.WriteToPort(temp.GetBuffer(), temp.GetLength());
}