串口字符串-HEX格式
串口字符串-HEX格式
介绍
串口通信过程中 通常涉及一个数据的模拟过程以及数据发送过程, 一般来说, 我们会发送一串指令给下位机
68 05 00 84 01 02 03
例如这种, 我们明白 这是我们 将相应的字符转换成 hex 字符显示,用于表示ascii 字母的使用, 但是在程序中 我们可以直接使用 字符串表示我们想写入的字符, 容纳后转换之后 串口数据相应的ASCII码的过程,
下面 介绍一下常用的转换函数
数据格式
在我们的描述中,
首先给出一个
或者参考 Wikipedia ACII 的详细介绍
此处我们均使用 "abc123" 作为字符串在各个里面的显示来表示
- 字符串 string 指的是 "abc 123" 这种能用ascii 表示的 能够打出来的字符, 由于我们部分字符不能打出来,或者说是 不可显示字符,只用于控制指令, 存在缺陷 string str = "abc123"
- 字符串数组 char [] uchar[] 指 cpp 中 的一种数据, 存放的char 型或者 uchar 的字符, 我们可以使用 -128-127 或者 0-255的数字表示, 我们暂时均认为是 uchar 的数组 便于后续处理 uchar buffer= {97,98,99,49,50,51}
- 字符串指针 char* uchar * 是类型指针,一般指向的是字符串数据的首地址,由于我们处理过程中 很多函数 认为 0x00 '\0' 是结束,所以处理的时候尽量传入 长度 uchar *buffer = buffer
- 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格式的更多相关文章
- 关于Matlab串口发送HEX格式字符
终于想起来更新一下关于使用Matlab串口发送HEX格式字符.这个用法主要来自于我使用Matlab对机器人进行实时轨迹跟踪的绘制,由于底层限制,自己又不想在中间增加转换模块,就需要直接发送HEX格式指 ...
- HEX格式数据转换成十六进制字符串
/** * Hex格式数据转换成十六进制字符串 * @param src */ public void bytesToHexString(byte[] by){ StringBuilder strin ...
- hex格式介绍及转bin格式的源程序
Intel HEX文件是记录文本行的ASCII文本文件,在Intel HEX文件中,每一行是一个HEX记录,由十六进制数组成的机器码或者数据常量.Intel HEX文件经常被用于将程序或数据传输存储到 ...
- elf格式转换为hex格式文件的两种方法
这周工作终于不太忙了,可以写点笔记总结一下了. 之前的文章如何在Keil-MDK开发环境生成Bin格式文件,介绍了如何在Keil开发环境使用fromelf软件,将生成的axf文件转换为bin文件,这次 ...
- string.Format出现异常:输入字符串的格式不正确 Exception during StringFormat
错误信息:Exception during StringFormat:输入字符串的格式不正确 “System.FormatException”类型的未经处理的异常在 mscorlib.dll 中发生 ...
- Python-4-设置字符串的格式字符串
字符串是不可变的,所有元素赋值和切片赋值都是非法的 1.替换字段名 可以按顺序和名称匹配 >>> "{foo} {} {bar} {}".format(1, ...
- Javascript将字符串日期格式化为yyyy-mm-dd的方法 js number 类型 没有length 属性 string类型才有
日期格式化相信对于大家来说再熟悉不过,最近工作中自己利用Javascript就写了一个,现在将实现的代码分享给大家,希望对有需要的朋友们能有所帮助,感兴趣的朋友们下面来一起看看吧. 这篇文章主要介绍的 ...
- DataGridView 中发生以下异常: System.Exception: 是 不是 Decimal 的有效值。 ---> System.FormatException: 输入字符串的格式不正确。
其实之前我自己是没测出这个问题的,但是一放到测试的手上就出来了,原因我知道在哪里改输什么东西,但是人家不知道啊.报错如下: --------------------------- “DataGridV ...
- JAVA代码解析String字符串(json格式的)
java解析String字符串(json格式) 需要jar包:json-lib-2.4-jdk15.jar 一. String str = "{\"name\":\&qu ...
随机推荐
- vulnhub~incllusiveness
这个机子相对简单一点,但是也是从中发现了自己不少问题 技能一: nmap 扫描发现了21,22 ,80三个端口,并且ftp服务允许匿名登录,在pub目录下面有writeable权限,这就好办了.我以 ...
- H - 遥远的糖果 HihoCoder - 1478
给定一个N x M的01矩阵,其中1表示人,0表示糖.对于每一个位置,求出每个位置离糖的最短距离是多少. 矩阵中每个位置与它上下左右相邻的格子距离为1. Input 第一行包含两个整数,N和M. 以下 ...
- MySQL服务使用cmd启动与停止服务
MySQL未设置自动启动,在使用时需要手动打开服务,方法如下 mysql服务的启动: 以管理员的身份运行cmd命令窗口,输入命名 net start mysql 提示:必须使用管理员身份运行cmd 如 ...
- Round 1A 2020 - Code Jam 2020
Problem A. Pattern Matching 把每个字符串分成第一个之前,最后一个之后,中间的部分 三个部分 每个字符串的中间的部分可以直接拼接 前后两个部分需要判断下是否合法 #inclu ...
- thinkphp中array_diff运行无效 Invalid opcode 153/1/8
经本人查证,发现是thinkPHP优化导致的与array_diff冲突.thinkPHP 报的错:Invalid opcode 153/1/8.有谁知道原理的,说说,让俺也明白.
- spring的jdbc具名参数
在jdbc的模板中使用具名参数: 1.就需要在之前的jdbc的例子中进行修改:需要在xml文件中重新配置一个bean.这是固定的格式.如下 对于使用具名参数而言.配置NamedParameterJdb ...
- 如何关闭php的所有错误提示
在调试PHP 应用程序时,应当知道两个配置变量.下面是这两个变量及其默认值:display_errors = Offerror_reporting = E_ALL E_ALL能从不良编码实践到无害提示 ...
- 31.2 try finally使用
package day31_exception; import java.io.FileWriter; import java.io.IOException; import java.lang.Exc ...
- JAVA debug 断点调试
更多调试参看 https://www.cnblogs.com/yjd_hycf_space/p/7483471.html 先编译好要调试的程序.1.设置断点 选定要设置断点的代码行,在行号的区域后面单 ...
- 数据结构和算法(Golang实现)(28)查找算法-AVL树
AVL树 二叉查找树的树高度影响了查找的效率,需要尽量减小树的高度,AVL树正是这样的树. 一.AVL树介绍 AVL树是一棵严格自平衡的二叉查找树,1962年,发明者Adelson-Velsky和La ...