串口字符串-HEX格式

C++SerialSerialPortHEX

介绍

串口通信过程中 通常涉及一个数据的模拟过程以及数据发送过程, 一般来说, 我们会发送一串指令给下位机

68 05 00 84 01 02 03

例如这种, 我们明白 这是我们 将相应的字符转换成 hex 字符显示,用于表示ascii 字母的使用, 但是在程序中 我们可以直接使用 字符串表示我们想写入的字符, 容纳后转换之后 串口数据相应的ASCII码的过程,

下面 介绍一下常用的转换函数

数据格式

在我们的描述中,

首先给出一个 或者参考 Wikipedia ACII 的详细介绍

此处我们均使用 "abc123" 作为字符串在各个里面的显示来表示

  1. 字符串 string 指的是 "abc 123" 这种能用ascii 表示的 能够打出来的字符, 由于我们部分字符不能打出来,或者说是 不可显示字符,只用于控制指令, 存在缺陷 string str = "abc123"
  2. 字符串数组 char [] uchar[] 指 cpp 中 的一种数据, 存放的char 型或者 uchar 的字符, 我们可以使用 -128-127 或者 0-255的数字表示, 我们暂时均认为是 uchar 的数组 便于后续处理 uchar buffer= {97,98,99,49,50,51}
  3. 字符串指针 char* uchar * 是类型指针,一般指向的是字符串数据的首地址,由于我们处理过程中 很多函数 认为 0x00 '\0' 是结束,所以处理的时候尽量传入 长度 uchar *buffer = buffer
  4. hex 字符串 将字符串数组里面的值转换成16进制的两位值,然后使用空格分割, 便于输入指令, 例如 string command="61 62 63 31 32 33"

这种合适各有优劣, 比如我们在常用的 Modbus 控制中 使用 这种控制命令发送到下位机, 一般直接在串口输入, 然后使用 hex 发送即可, 但是如果我们测试过程中 需要将相应的数据按照两位的段, 填入txt 文本中, 每次读取一行数据, 然后将数据转换成 ascii 便能模拟 二进制流的输入输出

68 13 00 85 11 12 21 22 31 32 00 00 01 00 00 02 00 00 03 88 FF 01 02 03 04 05 0F

数据格式转换

1. uchar 数据和 char 字节数据的相互转换

char 类型的数据 -128-127, uchar 类型数据 0-255, 均是一个字节, char 类型的首位数据为符号位, 所以会存在从 127(0111 1111) +1 之后变成 -128(1000 0000) 的变换, 然后也会存在从-1(1111 1111) 到 0(0000 0000) 的变换, 详细可以搜索 char 溢出数据补码 的相关内容,

所以 uchar -char 的相互变换可以考虑成 两个部分

uchar 的 [0, 127] == char [0,127]

ucahr 的 [128, 255] == char [-128,-1]

// uchar 数据转换 char  >127   c1-256
char Utils_String::UChar2Char(uchar c1)
{
return static_cast<char>(c1 > 127 ? c1 - 256 : c1);
} // char 类型转换 uchar <0 -- c1 +256
uchar Utils_String::Char2UChar(char c1)
{
return static_cast<uchar>((c1 < 0 ? 256 + c1 : c1));
}

2. hex 与数字的相互转换

一般的 hex 表示的 16进制字符, 由于为了便于我们进行显示, 16进制由 0-9 a-f 供给16个字符依次表示 0-15 , 此处暂时不考虑 大写字母, 大写的A-F 等同于小写的a-f,

由于 uchar 类型的数据在 0-256之间, 正好可以表示成 2个16进制字符来进行表示, 使用前缀字符0x 表示16进制, 0o 表示8进制 0d 表示10进制 [0,255] ==[0x00,0xff]

我们建立一位字符0-f 与 0-15 之间的转换, 有两种转换方式, 一种就是if 判断进行强制转换, 另外一种 是使用 码表的排列进行一定 的优化处理

1位hex 与num 的相互转换代码
/**
* @fn int Utils_String::Hex2Num(const char ch)
*
* @brief 根据 各种情况 转换字母 一位字母 大于 48 的 +9 然后取后4位的值
* *
*
* @author IRIS_Chen
* @date 2019/12/16
*
* @param ch The ch
*
* @return An int
*/
int Utils_String::Hex2Num(const char ch)
{
//int res = (ch & '@' ? ch + 9 : ch) & 0x0F;
//LInfo("ch:{},res:{}", ch, res);
return (ch & '@' ? ch + 9 : ch) & 0x0F;
} /**
* @fn char Utils_String::Num2Hex(int num, bool Up )
*
* @brief 将 0-15 转换成 0-F
*
* @author IRIS_Chen
* @date 2019/12/18
*
* @param num Number of
* @param Up True to up
*
* @return The total number of 2 hexadecimal
*/
char Utils_String::Num2Hex(int num, bool Up /* = true */)
{
char res;
if (num >= 10 && num <= 15)
{
res = num - 10 + (Up ? 'A' : 'a');
}
else
res = num + '0';
return res;
}
1位hex 与num 的相互转换代码
2位hex 与 uchar相互转换
/**
* @fn uchar Utils_String::Hex2Uchar(const std::string & str)
*
* @brief Hexadecimal 2 uchar 将两个 hex 字符 转换成 0-256
*
* @author IRIS_Chen
* @date 2019/12/18
*
* @param str The string 默认初始两位字符 FF == 255 00 = 0 0D = 14
*
* @return An uchar
*/
uchar Utils_String::Hex2Uchar(const std::string & str)
{
uchar res = 0;
for (const auto &s:str)
{
res = (res << 4) + Hex2Num(s);
}
return res;
} /**
* @fn std::string Utils_String::Num2Hex(uchar num, bool Up)
*
* @brief Number 2 hexadecimal 得到的结果只有 小写
*
* @author IRIS_Chen
* @date 2019/12/18
*
* @param num Number of
* @param Up True to up
*
* @return The total number of 2 hexadecimal
*/
std::string Utils_String::Num2Hex(uchar num, bool Up)
{
std::map<int, char> t_base = {
{ 8,'o' },
{ 10,'d' },
{ 16,'x' } };
if (!t_base.count(base))
return ""; // 使用 sprintf 格式化输出, 将数字 转换成相应的进制值
std::string format = "%0" + std::to_string(width) + t_base.find(base)->second;
char *buf = new char[20];
sprintf(buf, format.c_str(), num); std::string res=std::string(buf); // 转换大小写
return Up ? StringUpper(res) : StringLowwer (res);
}

3. 给定字符串转换成字符串数组

由于 原生的 string 存在字符转指针的转换

可以使用 原生的指针来处理

/**
* @fn const uchar * Utils_String::String2Uchar(const std::string & str)
*
* @brief String 2 uchar
*
* @author IRIS_Chen
* @date 2019/12/16
*
* @param str The string
*
* @return Null if it fails, else a pointer to a const uchar
*/
const uchar * Utils_String::String2Uchar(const std::string & str)
{
return (uchar*)str.c_str();
}
/**
* @fn std::string Utils_String::Uchar2String(const uchar * buffer)
*
* @brief Uchar 2 string
*
* @author IRIS_Chen
* @date 2019/12/16
*
* @param buffer The buffer
*
* @return A std::string
*/
std::string Utils_String::Uchar2String(const uchar * buffer)
{
std::string str = (char*)buffer;
return str;
}

4. hex 字符串 转换 字符串数组

依次取两个字符, 转换成一个 ucahr 值 存入数据中即可

hex 字符串 与字符串数组的相互转换
/**
* @fn uchar * Utils_String::Hex2CharArr(uchar *&buffer, const std::string & str, bool flg_space)
*
* @brief Hexadecimal 2 character array hex 字符串 转换成 数组
*
* @author IRIS_Chen
* @date 2019/12/18
*
* @param [in,out] buffer [in,out] If non-null, the buffer
* @param str The string
* @param flg_space True to flg space hex 是否使用空格分割
*
* @return Null if it fails, else a pointer to an uchar
*/
uchar * Utils_String::Hex2CharArr(uchar *&buffer, const std::string & str, bool flg_space)
{
// 出错 只有两个值 默认不符合 操作
if (str.size() < 3) return nullptr;
// 默认够长 判断是否存在空格
if (str[2] == ' ') flg_space = true; int step = flg_space ? 3 : 2; buffer = new uchar[(str.size() + 1) / step +1 ]; std::string str2 = ""; for (int i = 0; i < static_cast<int>(str.size());)
{
uchar ch = Hex2Uchar(str.substr(static_cast<size_t>(i), 2));
// 根据是否有空格选择 移动
*(buffer + i/step) = ch;
i += step; str2 += std::to_string((int)ch) + "-";
}
// LInfo("charArr:{}", str2);
return buffer;
} /**
* @fn std::string Utils_String::CharArr2Hex(uchar * buffer, int length, int flg_space)
*
* @brief Character array 2 hexadecimal 数组 转换成 hex 字符
* * 将UCHAR 字符串依次转换成 string 字符串
*
* @author IRIS_Chen
* @date 2019/12/18
*
* @param [in,out] buffer If non-null, the buffer
* @param length The length
* @param flg_space The flg space
*
* @return A std::string
*/
std::string Utils_String::CharArr2Hex(uchar * buffer, int length, int flg_space)
{
std::string str = "";
// 读取数组中所有字符
for (int i = 0; i < length; i++)
{
str += Num2Hex(*buffer++);
// 如果开启空格的话 每两个字符 之间加入一个空格 最后一个不加
if (flg_space && i != length - 1)
str += " ";
}
return str;
}

更多

大概就这么多常用的转换过程, 还存在一个 单独 数组转换 字符串的函数, 可以使用 sprintf 格式化输出, 或者使用 暴力循环取余得到最后的结果值

数字与字符串的转换 可多位 多进制
/**
* @fn std::string Utils_String::NumToString(int num, int width, int base)
*
* @brief Number to string 整型数据 前补 0 占位符显示 进制 为 8 10 16 如果超过给出的宽度 原始宽度显示
*
* @author IRIS_Chen
* @date 2019/12/3
*
* @param num Number of
* @param width The width
* @param base The base
*
* @return The total number of to string
*/
std::string Utils_String::NumToString(int num, int width, int base)
{
#if 0
// 保证 存在进制 只考虑 2 8 , 10 16 进制
static std::map<int, char> t_base = {
{ 2,'0' },
{ 8,'o' },
{ 10,'d' },
{ 16,'x' } };
if (!t_base.count(base))
return "";
// 二进制 特殊处理
if (base == 2)
{
std::string str_8 = NumToString(num, width, 8);
// 设置8进制 转2进制码表, 转换之后 去除前缀0 即可
static const std::vector<std::string> table = { "000","001","010","011","100","101","110","111" }; std::string str_2 = "";
for (auto s : str_8)
{
if(s =='0')
continue;
str_2 += table[s - '0'];
}
// 去掉前面所有的 0值 从1 开始
int pos = static_cast<int>(str_2.find_first_of('1')); // #TODO(Schen00) 处理, 得到的长度小于width 的情况
return pos == std::string::npos ?"":str_2.substr (pos);
} std::string format = "%0" + std::to_string(width) + t_base.find(base)->second; char *buf = new char[20];
sprintf(buf, format.c_str(), num);
return std::string(buf);
#else
std::string res = ""; while (num)
{
res = base == 16 ? Num2Hex(num % base) : (num % base + '0') + res;
num /= base;
} // 不足位 补0 足位 不删除
int cnt = width - res.size();
while (cnt--)
{
res = '0' + res;
}
return res;
#endif
}

串口字符串-HEX格式的更多相关文章

  1. 关于Matlab串口发送HEX格式字符

    终于想起来更新一下关于使用Matlab串口发送HEX格式字符.这个用法主要来自于我使用Matlab对机器人进行实时轨迹跟踪的绘制,由于底层限制,自己又不想在中间增加转换模块,就需要直接发送HEX格式指 ...

  2. HEX格式数据转换成十六进制字符串

    /** * Hex格式数据转换成十六进制字符串 * @param src */ public void bytesToHexString(byte[] by){ StringBuilder strin ...

  3. hex格式介绍及转bin格式的源程序

    Intel HEX文件是记录文本行的ASCII文本文件,在Intel HEX文件中,每一行是一个HEX记录,由十六进制数组成的机器码或者数据常量.Intel HEX文件经常被用于将程序或数据传输存储到 ...

  4. elf格式转换为hex格式文件的两种方法

    这周工作终于不太忙了,可以写点笔记总结一下了. 之前的文章如何在Keil-MDK开发环境生成Bin格式文件,介绍了如何在Keil开发环境使用fromelf软件,将生成的axf文件转换为bin文件,这次 ...

  5. string.Format出现异常:输入字符串的格式不正确 Exception during StringFormat

    错误信息:Exception during StringFormat:输入字符串的格式不正确 “System.FormatException”类型的未经处理的异常在 mscorlib.dll 中发生 ...

  6. Python-4-设置字符串的格式字符串

    字符串是不可变的,所有元素赋值和切片赋值都是非法的   1.替换字段名 可以按顺序和名称匹配 >>> "{foo} {} {bar} {}".format(1, ...

  7. Javascript将字符串日期格式化为yyyy-mm-dd的方法 js number 类型 没有length 属性 string类型才有

    日期格式化相信对于大家来说再熟悉不过,最近工作中自己利用Javascript就写了一个,现在将实现的代码分享给大家,希望对有需要的朋友们能有所帮助,感兴趣的朋友们下面来一起看看吧. 这篇文章主要介绍的 ...

  8. DataGridView 中发生以下异常: System.Exception: 是 不是 Decimal 的有效值。 ---> System.FormatException: 输入字符串的格式不正确。

    其实之前我自己是没测出这个问题的,但是一放到测试的手上就出来了,原因我知道在哪里改输什么东西,但是人家不知道啊.报错如下: --------------------------- “DataGridV ...

  9. JAVA代码解析String字符串(json格式的)

    java解析String字符串(json格式) 需要jar包:json-lib-2.4-jdk15.jar 一. String str = "{\"name\":\&qu ...

随机推荐

  1. javascript实现组合列表框中元素移动效果

    应用背景:在页面中有两个列表框,需要把其中一个列表框的元素移动到另一个列表框 .  实现的基本思想: (1)编写init方法对两个列表框进行初始化: (2)为body添加onload事件调用init方 ...

  2. C、Guard the empire(贪心)

    链接:https://ac.nowcoder.com/acm/contest/3570/C 来源:牛客网 题目描述 Hbb is a general and respected by the enti ...

  3. 程序开发中的术语,如IDE,OOP等等

    我们在开发程序过程中,会用到一些与编译有关的术语,比如:[编辑器.编译器.调试器.连接器,链接器.解释器,集成开发环境(Integrated Development Environment,IDE). ...

  4. 多线程学习笔记(五)---- 在JDK文档的使用

    1.前言 我们经常在JDK文档中见到一些类上的介绍说,该类是"安全的"."不安全"."效率高"."效率低"的词眼.这里, ...

  5. 玩转控件:对Dev的GridControl控件扩展

    缘由 一切实现来源于需求,目的在于不盲目造轮子,有小伙伴儿在看了<玩转控件:对Dev中GridControl控件的封装和扩展>文章后,私信作者说,因公司业务逻辑比较复杂,展示字段比较多,尤 ...

  6. PTA | 1009说反话(20分)

    给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出. 输入格式: 测试输入包含一个测试用例,在一行内给出总长度不超过80的字符串.字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有 ...

  7. 原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么

    开心一刻 女孩睡醒玩手机,收到男孩发来一条信息:我要去跟我喜欢的人表白了! 女孩的心猛的一痛,回了条信息:去吧,祝你好运! 男孩回了句:但是我没有勇气说不来,怕被打! 女孩:没事的,我相信你!此时女孩 ...

  8. Python入门学习指导(VS Code配置向)

    代码编辑器或IDE 推荐Vs Code,Atom和Sublime(本文以Vs Code为例,Sublime对中文支持不是很好,时常弄好了Sublime的乱码,却在复制到其他编辑器时出了问题) Vs C ...

  9. day28作业

    import os import uuid import pickle from conf import settings class School: def __init__(self,name,a ...

  10. python白帽子/黑客/实战编程教程

    Python搜索爬虫抓取超高清视频教程_第一期Python搜索爬虫抓取超高清视频教程_第二期Python搜索爬虫抓取视频教程_第三期Python搜索爬虫抓取视频教程_第四期Python搜索引擎爬虫抓取 ...