找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2837

积分

0

好友

400

主题
发表于 7 小时前 | 查看: 1| 回复: 0

你是否在使用串口助手时感到困惑?为什么有时候可以直接输入“abc”这样的字符发送,而有时又必须输入“0x12, 0xFF”这样的十六进制数据才能成功下发指令?这两者之间究竟有什么联系和区别?

一、数据表示和数据传输

1.  数据本质 (Bits)

  • 串口在物理层传输的是 比特流 (Bits),即连续的 0 和 1。
  • 一个字节 (Byte) 由 8 个比特组成。
  • 所有数据,无论是文本、数字、图片还是控制指令,在传输时最终都是比特流。 串口本身并不关心数据的“意义”,它只负责搬运这些比特。

2.  数据表示 (Encoding)

  • ASCII: 一种 字符编码标准。它将常见的字母、数字、标点符号、控制字符(如回车、换行)映射到特定的 字节值
    • 例如: 'A' -> 0x41, '1' -> 0x31, ' ' (空格) -> 0x20, '\n' (换行) -> 0x0A
  • 范围: 标准 ASCII 使用 0x00 - 0x7F (0-127) 的字节值。

ASCII控制字符对照表

  • HEX (十六进制): 一种 数值表示方法,或者说是一种用文本表示字节值的方式,用于更直观地表示二进制数据。
    • 一个字节 (0x00 - 0xFF) 用两个十六进制字符表示 (0-9, A-F/a-f)。
    • 例如:字节值 0x41 可表示为字符串 "41""0x41"。字节值 0x0A 表示为 "0A""0x0A"
  • HEX 本身不是一种编码,而是一种显示和输入格式。
  • 二进制 (Binary): 最底层的表示(0 和 1 序列),但通常不适合人类直接输入或阅读。
  • 其他编码: 像 UTF-8, GBK 等用于支持更多字符(如中文),它们用 多个字节 表示一个字符。串口助手通常不直接处理这些编码的“字符输入”,而是处理它们对应的字节流。

3.  串口助手的作用

  • 发送端: 将用户输入(文本或 Hex 字符串) 转换 成要发送的 字节序列(比特流)。
  • 接收端: 将接收到的 字节序列(比特流) 转换 成人类可读的形式(ASCII 字符 或 Hex 字符串)显示出来。
  • 关键点: 串口助手在 “用户输入/显示”“实际发送/接收的字节” 之间进行转换。 Hex 显示Hex 发送 选项控制的就是这个转换的方式。

二、串口助手行为分析

场景 1:默认状态(未勾选 Hex 发送 和 Hex 显示)

串口助手默认模式发送“abc g”
串口助手默认模式接收显示“abc g”

发送框输入

  • 用户输入的 abc g空格 都被当作 ASCII 字符

发送过程

  1. 字符转成 ASCII 码: 串口助手将输入的每个字符转换为其对应的 ASCII 码值(字节)。
    • 'a' -> 0x61
    • 'b' -> 0x62
    • 'c' -> 0x63
    • 'g' -> 0x67
    • ' ' (空格) -> 0x20
  2. 发送字节: 串口助手依次发送这些字节 0x61, 0x62, 0x63, 0x20, 0x67 对应的 比特流
  3. 接收显示(未勾选 Hex 显示): 接收端串口助手将收到的字节流 0x61, 0x62, 0x63, 0x20, 0x67 按照 ASCII 编码解释 并显示为字符:a b c g(注意空格显示为空白)。

结论

  • 输入被当作 ASCII 字符处理,转换为对应字节发送。
  • 空格 (0x20) 被当作一个有效的 ASCII 字符发送出去。
  • 发送的是 字节。Hex 只是表示字节的一种方式。实际发送的是字节对应的比特流。

场景 2:勾选 Hex 显示(仅影响接收显示)

勾选HEX显示后的接收数据

  • 仅改变接收数据的显示方式,不影响发送行为。
  • 发送行为: 同场景 1。如果在发送框输入 abc g,发送的仍然是 0x61, 0x62, 0x63, 0x20, 0x67
  • 接收显示: 接收端串口助手将收到的字节流 0x61, 0x62, 0x63, 0x20, 0Hex 形式 显示:61 62 63 20 67,具体格式可能略有不同,如 0x61, 0x62...61h 62h...
  • 结论: 勾选 Hex 显示 只是改变了 接收数据在屏幕上的呈现方式,从尝试显示 ASCII 字符变成了直接显示每个字节的十六进制值。

场景 3:勾选 Hex 发送

HEX发送模式下输入示例
无效HEX字符输入错误提示
HEX发送模式下分隔符的作用
HEX发送模式下输入“0x01 0x03”
字符模式下输入“0x01”的显示

  • 此选项彻底改变了发送框输入的处理逻辑。
  • 发送框输入: 输入框不再接受“字符”,而是期望输入 十六进制数字 (0-9, A-F, a-f) 组成的字符串。非 Hex 字符(空格、逗号、冒号、字母 g-z 等) 不会被转换或忽略,而是被当作分隔符

发送过程

  1. 解析 Hex 字符串: 串口助手扫描输入的字符串。
  2. 忽略分隔符: 遇到空格、逗号、分号、字母 g非 Hex 字符 (0-9, A-F, a-f 之外的字符),直接跳过,它们 仅起分隔作用
  3. 组合字节: 将连续的 Hex 字符 每两个一组 组合成一个字节。
    • "A" -> 0x0A ,单个字符会被视为 0x0A,而不是 0xA0 或错误。但 建议总是输入两个字符表示一个完整字节,避免歧义。
    • "41" -> 0x41
    • "1 A" -> 空格被忽略,"1""A" 被组合成 0x1A
    • "1,2" -> 逗号被忽略,"1""2" 被组合成 0x12
    • "abc" -> 'a' (0x61), 'b' (0x62), 'c' (0x63) 都是合法 Hex 字符!组合为 0xAB (注意:"a"+"b" = 0xAB,不是发送字母 'a''b' 的 ASCII 码!)
    • "ag" -> 'a' (0x61) 和 'g' (0x67) 都是合法 Hex 字符?错误。 'g' 的 ASCII 值是 0x67,但作为 Hex 字符,'g' 不是有效的十六进制数字,有效的是 0-9, A-F, a-f。'g' 会被当作分隔符忽略掉或者根本就无法输入到发送框!所以 "ag" 会被解析为 "a" -> 0x0A
  4. 发送字节: 将解析得到的所有字节依次发送出去。
  5. 接收显示
    • 如果接收端勾选 Hex 显示,则直接显示接收到的字节的 Hex 值。
    • 如果接收端未勾选 Hex 显示,它会尝试将接收到的字节 当作 ASCII 字符来解释。如果字节值在可打印 ASCII 范围 (0x20-0x7E),则显示对应字符;否则显示乱码(如点 . 或方框)或控制字符效果(如 0x0D 可能导致光标回车)。

结论

  • 勾选 Hex 发送 后,输入框期望的是 Hex 字符串,abc g 这样的字符:
    • a, b, c 是合法 Hex 字符,它们会被组合成字节 (如 abc 会被当作 0xAB0x0C)。
    • g非法 Hex 字符,会被当作 分隔符忽略或者根本无法输入
  • 空格(以及逗号、分号、下划线、|- 等任何非 0-9, A-F, a-f 的字符) 都会被当作分隔符忽略,不会发送任何对应字节。
  • 间隔符问题: 理论上,任何不属于 [0-9, A-F, a-f] 集合的字符都可以在 Hex 发送 模式下安全地用作字节间的分隔符(和串口助手的设计有关)。常见的有空格、逗号 、分号 ;、冒号 :、竖线 |、短横线 -、下划线 _ 等。它们的作用仅仅是提高 Hex 字符串的可读性(例如 A1 B2 C3A1B2C3 更容易看清字节边界),串口助手在解析时会自动忽略它们。
  • 不输入空格会怎样? 如果输入的是连续的合法 Hex 字符,如 "41",它会被解析为一个字节 0x41。如果输入 "4142",它会被解析为两个字节 0x410x42串口助手严格按照每两个连续 Hex 字符组合成一个字节的规则解析,与是否有空格无关。 空格只是视觉分隔,方便人看。"41""4 1"Hex 发送 模式下都会被解析为 一个 字节 0x41"4 1" 中的空格被忽略,剩下的 "4""1" 组合成 0x41。要发送两个字节 0x410x42,你需要输入 "41 42""4142""41,42" 等。

Hex 发送选项的核心作用

  • 改变输入数据的解释方式: 从“解释为 ASCII 字符并转成对应字节”变为“解释为十六进制数字并解析成对应的字节值(直接发送十六进制数字对应的bit)”。
  • 发送任意字节值: 这是最重要的。允许用户 直接指定并发送任意字节值 (0x00 - 0xFF),包括:
    • 不可打印的 ASCII 控制字符:0x00 (NUL), 0x01 (SOH), 0x0D (CR), 0x0A (LF), 0x1B (ESC) 等。这些在 ASCII 发送 模式下是无法通过键盘直接输入的。
    • 超出标准 ASCII 范围的字节值 (0x80-0xFF): 这些可能代表扩展 ASCII 字符、二进制数据、自定义协议中的特定命令或数据。
    • 二进制文件/图片/音频的原始数据。
  • 避免双重编码: 如果想发送的“数据”本身就是一个 Hex 字符串的字面值,例如想发送包含字符 'A''B''1''2' 的字符串,则应该使用 ASCII 发送 模式。如果错误地在 Hex 发送 模式下输入 "AB12",发送的将是 0xAB, 0x12 这两个字节,而不是 'A'(0x41), 'B'(0x42), '1'(0x31), '2'(0x32) 这四个字节。

三、总结与深入理解要点

1. 类比

  • ASCII 发送 像用英文发电报。你写单词(字符),邮局(串口)把每个字母转换成电报码(ASCII 字节)发出去。
  • Hex 发送 像直接发送电报码手册里的数字。你在单子上写 48 65 6C 6C 6F(代表 Hello 的电报码)。邮局直接按这些数字发报,不再查字母表。空格/逗号只是让你写码时看得更清楚,发报时忽略。

2. 总结

  1. 数据本质是比特流: 串口传输的是字节(8位)组成的比特流。
  2. 编码/表示是视图: ASCII, Hex, UTF-8 等都是给 字节流 赋予“意义”或提供一种人类可读/可写表示的方法。
  3. 串口助手是转换器
    • 发送: 用户输入 -> (根据 Hex 发送 选项) -> 字节序列 -> 比特流
    • 接收: 比特流 -> 字节序列 -> (根据 Hex 显示 选项) -> 显示内容
  4. Hex 发送 vs ASCII 发送 (默认):
    • ASCII 发送 (默认未勾选 Hex 发送): 输入框是 文本编辑器。你输入的每个字符(字母、数字、空格、符号)都转换成其 ASCII 码值 发送。g 发送 0x67,空格发送 0x20
    • Hex 发送 (勾选): 输入框是 Hex 解析器。你输入的是 代表字节值的十六进制数字对。非Hex字符(空格、逗号、g等)是 分隔符,被忽略。"41" 发送 0x41"g" 被忽略," " (空格) 被忽略。"abc" 发送 0xAB (因为 'a''b' 被当作 Hex 字符组合成 0xAB),'c' 被当作单个 Hex 字符发送 0x0C (但易出错,不推荐)。
  5. Hex 显示 仅影响接收数据显示方式。勾选则显示字节的十六进制值;不勾选则尝试将字节解释为 ASCII 字符显示(不可打印字符显示乱码)。

四、典型案例分析与注意事项

1.  案例:发送换行回车 (CRLF)

  • 需求: 让接收端光标移动到下一行开头。
  • 方法1 (ASCII 发送): 在发送框输入 \r\n (如果串口助手支持转义) 或直接按回车键(通常串口助手会将按回车键映射为发送 \r\n)。实际发送字节 0x0D, 0x0A
  • 方法2 (Hex 发送): 勾选 Hex 发送,输入 0D 0A。发送字节 0x0D, 0x0A
  • 错误做法 (ASCII 发送): 输入字符 '0''D''0''A'。这会发送 0x30, 0x44, 0x30, 0x41 ('0','D','0','A'),不是 CRLF 指令。

2.  案例:发送二进制数据 (如 0x00, 0xFF)

  • 唯一可靠方法: 勾选 Hex 发送,输入 00 FF
  • ASCII 发送问题:
    • 0x00 (NUL):无法通过键盘输入。即使某些助手允许输入 \0\x00,也可能被错误处理。
    • 0xFF:超出标准 ASCII 范围。在 ASCII 发送 模式下输入任何字符都无法直接对应 0xFF。尝试输入可能被解释为其字符的编码(如某些编码下字符 'ÿ' 可能是 0xFF,但依赖编码且不可靠)。

3.  案例:发送字符串 “41”

  • 需求: 发送字符 '4' (ASCII 0x34) 和 '1' (ASCII 0x31)。
  • 正确方法 (ASCII 发送): 输入 41,串口会发送 0x34, 0x31
  • 错误方法 (Hex 发送): 勾选 Hex 发送,输入 41。串口会发送 一个 字节 0x41 (即字符 'A' 的 ASCII 码)。

4.  案例:发送协议帧 (如 STX 0x02 + Data + ETX 0x03)

  • 正确方法 (Hex 发送): 输入 02 48 65 6C 6C 6F 03 (例如发送 Hello48 65 6C 6C 6FHello 的 ASCII Hex)。
  • 混合方法 (易错):ASCII 发送 模式下,尝试输入特殊字符代表 STX/ETX(如 Ctrl+B 可能被映射为 STX 0x02,Ctrl+C 映射为 ETX 0x03),然后输入 Hello。但这种方法依赖助手映射且不直观,容易出错。Hex 发送 更直接可靠。

5. 注意事项

  1. 通信双方约定一致: 这是最重要的原则!发送端和接收端(设备或另一端的串口助手)必须对数据的 含义(协议、格式、编码)有相同的理解。Hex 发送 只解决“如何把用户输入变成字节”,不解决“这些字节代表什么”的问题。
  2. Hex 发送 用于发送精确字节值: 当需要发送控制字符、扩展字符、原始二进制数据或精确符合协议要求的字节序列时,务必使用 Hex 发送
  3. ASCII 发送 用于发送可读文本: 当主要发送人类可读的英文文本消息时,使用默认的 ASCII 发送 最方便。
  4. Hex 显示 用于查看原始数据: 在调试、分析协议或接收非文本数据时,勾选 Hex 显示 查看原始字节值至关重要,避免因 ASCII 解释错误(如将控制符显示为乱码)而误解数据。
  5. 分隔符自由但需一致: Hex 发送 模式下,分隔符可以自由选择(空格、逗号等),但需确保输入时使用一致的分隔符(或不使用)。接收端显示的分隔符通常是串口助手添加的,便于阅读,不影响实际接收的字节。
  6. 警惕 g 等非法 Hex 字符:Hex 发送 模式下,g, z, ?, ! 等字符会被当作分隔符忽略,可能导致你输入的 Hex 数字被错误组合(如 "ag" -> 0x0A)。只输入 0-9, A-F, a-f 和分隔符。
  7. 字节组合规则: Hex 发送 严格按 两个连续 Hex 字符组合成一个字节。奇数个 Hex 字符时,最后一个字符会被当作 0x0X 发送(如 "A" -> 0x0A)。建议总是输入偶数个 Hex 字符,并用分隔符明确字节边界。
  8. 波特率等参数匹配: 除了数据表示,确保通信双方的波特率、数据位、停止位、校验位设置完全相同,否则数据会完全错乱。

理解串口助手中 HEX 与 ASCII 模式的区别,本质上是理解 数据表示数据传输 之间的关系。掌握这些基础知识,能让你在嵌入式开发、硬件调试或任何涉及串口通信的场景中更加得心应手。如果你想与更多开发者交流此类底层通信技术,欢迎到 云栈社区 的相关板块参与讨论。




上一篇:AI SDK与OpenAI Responses API实战指南:构建智能体与实现持久化对话
下一篇:C语言基于FreeRTOS的嵌入式日志系统简易设计实现详解
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-26 19:53 , Processed in 0.366666 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表