news 2026/9/27 23:53:09

ASCII码对照表详解:串口通信与字符编码转换的实用指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ASCII码对照表详解:串口通信与字符编码转换的实用指南

写代码这些年,我电脑里收藏夹里躺得最久的几张图,除了运维画的网络拓扑,就是各种版本的ASCII码对应表。别看它只是张密密麻麻的表格,串口通信、协议解析、字符编码转换、单片机调试,全都绕不开它。很多刚接触嵌入式和底层开发的朋友,第一次被十六进制字节折磨得头皮发麻,往往就是因为没把这张表在心里盘熟。这篇内容把我最常用、也最完整的那份ASCII码对应表整理出来,顺带把控制字符、可打印字符、常见编码坑都讲透,适合正在学C语言、搞单片机、写网络协议、做数据解析的开发者收藏,也适合所有想搞明白“字符在计算机里到底长什么样”的人。

1. 为什么ASCII码对应表值得你认真对待

1.1 字符与数字的第一座桥

计算机底层不认字母,不认标点,只认二进制。但人在读写数据的时候,总得用ABCD、用0到9来表达信息。ASCII(American Standard Code for Information Interchange,美国信息交换标准码)就是给每个常见字符分配一个固定编号的方案。一个字符用7位二进制表示,范围从0到127,这就是大家常说的128个字符。

你可以把它理解成一张字典:编号65对应大写字母A,编号97对应小写字母a。当你在串口助手里发送0x41,接收端如果按ASCII解释,显示出来就是字符A;如果按原始数值处理,它就是十进制的65。同样一串字节,解释方式不同,结果天差地别。所以搞通信、搞文件解析的人,必须随时能在“字符”和“数字”之间来回切换,这张对应表就是切换用的翻译词典。

1.2 谁需要这份表

说实话,工作这么多年,我认为这张表的使用频率比很多人想象中高得多。写串口调试工具、解析Modbus或自定义帧协议、处理HTTP报文、写编译器词法分析、做单片机按键扫描,都会频繁用到。甚至前端处理用户输入,把输入框里的数字字符串转成整数时,也脱不开字符与数值的转换逻辑。

新手最容易犯的错,是把字符‘5’和数字5混为一谈。在C语言里,‘5’被存储在内存中是十进制53,也就是0x35。你要是拿它直接参与数值计算,算出来的结果必然跑偏。这就是为什么我总跟刚入行的朋友说,先别急着背各种高级框架API,把ASCII表吃透,后面的坑能少踩一大半。

2. 完整ASCII码对照表(0-127)

2.1 控制字符区:0-31与127

先看0到31这32个字符,它们都是不可见控制符,再加上最后的127(DEL),英文简写、全称、含义都列在表里了。

十进制十六进制缩写英文全称含义说明
00x00NULNull空字符,早期用于填充,C语言字符串终止符就是它
10x01SOHStart of Heading标题开始,电报/通信中表示报头开始
20x02STXStart of Text正文开始
30x03ETXEnd of Text正文结束
40x04EOTEnd of Transmission传输结束
50x05ENQEnquiry请求应答
60x06ACKAcknowledge确认应答
70x07BELBell响铃,终端蜂鸣提示
80x08BSBackspace退格,光标向左移动一格
90x09HTHorizontal Tab水平制表符,跳到下一个制表位
100x0ALFLine Feed换行,Unix/Linux换行符
110x0BVTVertical Tab垂直制表符
120x0CFFForm Feed换页,打印机送纸一页
130x0DCRCarriage Return回车,光标回到行首,Windows换行符的一部分
140x0ESOShift Out切换字符集
150x0FSIShift In恢复字符集
160x10DLEData Link Escape数据链路转义
170x11DC1Device Control 1设备控制1,常作为XON软件流控信号
180x12DC2Device Control 2设备控制2
190x13DC3Device Control 3设备控制3,常作为XOFF软件流控信号
200x14DC4Device Control 4设备控制4
210x15NAKNegative Acknowledge否定应答
220x16SYNSynchronous Idle同步空闲
230x17ETBEnd of Transmission Block传输块结束
240x18CANCancel取消之前数据
250x19EMEnd of Medium介质结束
260x1ASUBSubstitute替换字符,DOS下常用作Ctrl+Z结束输入
270x1BESCEscape转义字符,ANSI终端控制序列由此开始
280x1CFSFile Separator文件分隔符
290x1DGSGroup Separator组分隔符
300x1ERSRecord Separator记录分隔符
310x1FUSUnit Separator单元分隔符
1270x7FDELDelete删除,来源于穿孔纸带“全部打孔”表示抹除

2.2 可打印字符区之一:32-63

从32开始就都是肉眼可见的字符了。32是空格,它也是字符,别忽略。

十进制十六进制字符说明
320x20(空格)空格,最常用的分隔符
330x21!叹号
340x22"双引号
350x23#井号,C语言预处理指令、十六进制前缀都用它
360x24$美元符号,Shell脚本变量前缀
370x25%百分号,printf格式化占位符
380x26&和号,C语言取地址运算符
390x27'单引号,C语言字符常量定界符
400x28(左圆括号
410x29)右圆括号
420x2A*星号,乘法或指针解引用
430x2B+加号
440x2C,逗号
450x2D-减号 / 连字符
460x2E.句点,小数点
470x2F/斜杠,路径分隔符、除法运算符
480x300数字0
490x311数字1
500x322数字2
510x333数字3
520x344数字4
530x355数字5
540x366数字6
550x377数字7
560x388数字8
570x399数字9
580x3A:冒号
590x3B;分号
600x3C<小于号
610x3D=等号
620x3E>大于号
630x3F?问号

2.3 可打印字符区之二:64-95

十进制十六进制字符说明
640x40@邮箱地址中分隔用户名与域名
650x41A大写字母A
660x42B大写字母B
670x43C大写字母C
680x44D大写字母D
690x45E大写字母E
700x46F大写字母F
710x47G大写字母G
720x48H大写字母H
730x49I大写字母I
740x4AJ大写字母J
750x4BK大写字母K
760x4CL大写字母L
770x4DM大写字母M
780x4EN大写字母N
790x4FO大写字母O
800x50P大写字母P
810x51Q大写字母Q
820x52R大写字母R
830x53S大写字母S
840x54T大写字母T
850x55U大写字母U
860x56V大写字母V
870x57W大写字母W
880x58X大写字母X
890x59Y大写字母Y
900x5AZ大写字母Z
910x5B[左方括号,数组下标运算符
920x5C\反斜杠,转义字符前缀、Windows路径分隔符
930x5D]右方括号
940x5E^脱字符,C语言异或运算符
950x5F_下划线,命名字符的常用连接符

2.4 可打印字符区之三:96-126

十进制十六进制字符说明
960x60`反引号,Shell命令替换符
970x61a小写字母a
980x62b小写字母b
990x63c小写字母c
1000x64d小写字母d
1010x65e小写字母e
1020x66f小写字母f
1030x67g小写字母g
1040x68h小写字母h
1050x69i小写字母i
1060x6Aj小写字母j
1070x6Bk小写字母k
1080x6Cl小写字母l
1090x6Dm小写字母m
1100x6En小写字母n
1110x6Fo小写字母o
1120x70p小写字母p
1130x71q小写字母q
1140x72r小写字母r
1150x73s小写字母s
1160x74t小写字母t
1170x75u小写字母u
1180x76v小写字母v
1190x77w小写字母w
1200x78x小写字母x
1210x79y小写字母y
1220x7Az小写字母z
1230x7B{左花括号,代码块定界符
1240x7C|竖线,Shell管道符、逻辑或
1250x7D}右花括号
1260x7E~波浪号,按位取反运算符、用户主目录缩写

2.5 值得背下来的三个区段

完整表格参考价值大,但工作中真正需要即时反应的,其实就是三个区段加两个特殊值。

  • 数字:48到57,十六进制0x30到0x39。取数字字符的值用c - '0',本质上就是减去48。
  • 大写字母:65到90,十六进制0x41到0x5A。
  • 小写字母:97到122,十六进制0x61到0x7A。
  • 空格:32,十六进制0x20。
  • 回车/换行:13/10,十六进制0x0D/0x0A。

大写A是65,小写a是97,两者相差32。这句话我建议你刻在脑子里。因为ASCII这套编号在设计时非常讲究,大小写字母之间正好错开32,也就是二进制第5位翻转一下就能完成大小写转换。后头写代码时,ch |= 0x20转小写,ch &= ~0x20转大写,都是这么来的。

3. 控制字符没你想的那么简单

3.1 从电报与打孔纸带走来

很多人看到0到31这些控制字符,第一反应是“这都什么鬼”。实际上这些字符的来历和电报、打孔纸带、早期终端高度相关。比如BEL原来就是物理电铃的触发信号,终端收到它就会“叮”一声;DEL更直接,纸带上打满孔代表删除,后来计算机里就用来表示Delete。

搞清楚这一点,你就不会觉得SOH、STX、ETX是莫名其妙的存在。当时的通信是面向字节流的,一帧报文发出去,总得告诉对方“从哪开始、到哪结束”。SOH标识报头,STX标识正式数据开始,ETX标识数据结束,这就是最原始的帧协议设计。现在很多工业总线和自定义串口协议,表面上没用这些字符,但分帧、定界的思路一脉相承。

3.2 通信协议里的帧控制与流控

在我调试串口设备的经验里,控制字符里出现频率最高的几个,一个是0x0D/0x0A这对“回车换行”,另一个是0x1B转义符。很多触摸屏、扫码枪、打印机的串口指令都以CR或LF结尾,解析时先按行切割,再去掉行尾的\r和\n,剩下的才是有效数据。

DC1和DC3也就是Ctrl+Q和Ctrl+S,在老式的串口软流控里承担暂停/恢复发送的作用。如果在调试老设备时发现数据传着传着突然卡住,八成是远端发来一个0x13(XOFF),要你停下来等它处理完,然后收到0x11(XON)再继续。现在串口参数里默认关闭软流控,但遇到老协议还是要留个心眼。

3.3 换行字符的恩怨

CR、LF这对组合,堪称跨平台开发的头号刺客。

Unix/Linux习惯只用LF(0x0A)表示换行,Windows用CR LF(0x0D 0x0A)两个字符表示一行结束,老Mac甚至只用CR。你从Windows拷贝脚本到Linux,经常会看到结尾一堆^M,那就是回车符没被识别为换行,直接显示成字符了。处理方式也简单,sed -i 's/\r$//'或者dos2unix一把梭。反过来从Linux往Windows传文件,有些编辑器会显示成一行西瓜(所有换行消失),本质也是换行符不匹配。

这一类问题排查起来不算难,但特别费时间。我的习惯是一拿到陌生环境的日志文件,先看文件里0x0D出现的频率,如果一行结尾挨着0x0D 0x0A,立刻就要意识到换行风格和当前系统不一致。

3.4 转义符与终端操作

ESC(0x1B)在终端控制里简直就是“魔法开关”。ANSI转义序列就是ESC加方括号再加参数,例如ESC[2J清屏、ESC[31m设置前景色为红色。很多嵌入式设备的LCD菜单、联网模块的AT指令集,也会用ESC做多级菜单的层级跳转标志。

写串口屏驱动的时候,我踩过这么个坑:厂商协议把ESC定义成“进入命令模式”,但图画文本里头换行也是ESC加别的字符组成的序列。结果有一次数据显示里包含0x1B,屏幕就直接切到命令模式,显示全乱。后来实现在解析层做了严格状态机,只有特定前置条件下才把ESC解释成控制字符,数据区里的ESC一律按普通字节处理。这个思路也推荐给你,处理任何“元字符”时都不要无脑转义。

3.5 不可见控制符到底是什么意思

所谓“不可见控制符”,就是这33个字符在普通终端上不显示图形,只影响设备行为。它们不是没有意义,而是意义不在“长什么样”,而在“做什么事”。比如你在Windows记事本里看到一行结束,背后是两个字节0x0D 0x0A;按下退格键,终端收到的是0x08;按下Delete键,终端收到的是0x7F。这些行为肉眼不可见,但文件格式、协议语义全压在上面。

新人学到这里最绕的一个弯,是也把0x08和0x7F搞混。按Backspace和按Delete发送的ASCII码不一样,用串口工具调试终端时特别注意,很多设备对这两个码的响应策略截然不同。

4. 从ASCII走向扩展编码

4.1 128-255是怎么来的

ASCII原本只是7位编码,但计算机存储单元是8位,一个字节有256种组合,只用0到127未免浪费。于是各家厂商开始在128到255这段填充各自喜欢的字符,这就导致了“扩展ASCII”乱象。

最有名的是IBM PC时代的Code Page 437,里面塞进了制表符、希腊字母、甚至扑克牌花色。国内很多人记忆里的“ASCII里152是人民币符号”,其实是GB2312或者ANSI时代本地化字符集产生的错觉,并非标准ASCII内容。

如果从编程角度理解,就是同一个字节0x80,在不同的代码页下可能显示成完全不同的字符。这也是“外一字节就乱码”的根源之一:两个端点的代码页不一致。

4.2 ISO-8859-1与Latin-1的欧洲视角

ISO-8859-1又叫Latin-1,算是最常见的单字节扩展方案,覆盖了西欧主要语言。它保留0x00-0x7F与ASCII完全一致,又用0xA0-0xFF塞进了很多带重音的字母、货币符号、分数符号。

我对这个字符集印象深,是因为早年写网页的人都知道,在HTTP响应头里如果没指定charset,很多浏览器默认按ISO-8859-1解析。没有统一UTF-8的岁月里,西班牙语的ñ、法语的重音é、德国的ß、欧元的€,全都依赖这张扩展表才能正常显示。后来大家统一转向Unicode,才把这种混乱终结掉。

4.3 为什么ASCII至今没被淘汰

很多人会问:现在都用UTF-8了,还背ASCII表干什么?核心原因是ASCII的0x00到0x7F被Unicode原封不动继承下来,Unicode码点U+0000到U+007F和ASCII是一一对应的。UTF-8编码里,这个区段的字符也直接用单字节表示,和当年ASCII字节一模一样。

也就是说,你写的任何一段UTF-8编码的英文文本,本质上就是一段ASCII流。协议头、文件头、控制指令这些“结构性文字”为了保证通用性,几乎都会刻意选择ASCII字符。比如HTTP报文头、JSON键名、PNG文件头、ELF魔数,全都在ASCII区段内。所以解析任何文件格式,第一步仍然要对照ASCII码。

5. 实战:程序里怎么快速查表、怎么换算

5.1 命令行三件套

调试时不想开在线表格,最顺手的是这几个命令。

先看某个字符对应的ASCII码:

# 注意是单引号,shell会把'A改成字符而不是字符串 printf '%d\n' "'A" # 输出 65

把一个字节按十六进制看:

echo -n "A" | od -An -tx1 # 输出 41

如果看文件里有哪些不可见字符,cat -A非常直观:

echo -e "hello\r\nworld" | cat -A # 输出 # hello^M$ # world$

其中^M就是回车符的显示形式。xxd也值得装,它能输出带偏移量和ASCII对照区的完整十六进制视图,我做协议分析时基本天天用。

5.2 用Python一键生成贯穿表

如果你像我一样经常要打印一份ASCII表贴显示器边上,用Python生成最省事:

for i in range(128): if i >= 32 and i <= 126: ch = chr(i) else: ch = ' ' print(f"{i:3d} 0x{i:02X} {ch}")

这段代码会把0到127全部列出来,控制字符区字符位留空,可打印字符区直接显示字符。如果想要更完整的双向查询,可以写成字典:

char_to_code = {chr(i): i for i in range(128)} code_to_char = {i: chr(i) for i in range(128)} print(char_to_code['A']) # 65 print(ord('A')) # 65 print(chr(65)) # A

Python自带的ord和chr已经是天然的ASCII查询函数,不需要任何第三方库。

5.3 手工换算的速算技巧

现场没有工具时,把十六进制转十进制可以用一个口诀:高位乘16加低位。0x41就是4×16+1=65,0x61就是6×16+1=97。因为ASCII里字母区段很规整,你只需要记住A是0x41,a是0x61,然后往后一个个数就行。

数字字符更简单,0是0x30,9就是0x39。做过C语言字符串转数字的朋友应该都写过c - '0',本质上就是把ASCII值映射回数值本身。

我还常用一个技巧:大小写互转用异或32。大写A是65(0b1000001),小写a是97(0b1100001)。中间就差一位,也就是0x20这一位。ch ^= 0x20就能完成互换,在写简洁的协议处理代码时非常漂亮。

6. 常见问题与排查速查

6.1 问题速查表

症状常见原因处理思路
终端显示字符前出现^M文件或数据流用CRLF换行,当前系统只认LF去掉0x0D,或统一换行风格
串口发0x41,设备当成数字65处理而非字符A协议字段是二进制数值,不是文本明确字段类型与编码规则
大小写转换后结果不对用了加减32但方向搞反,或误对数字做转换判断字符范围,再用异或0x20
把‘5’和5混淆,数值计算得到错误结果未减‘0’就参与运算c - '0'
解析文本时字符串提前终止数据结构里出现0x00,被当成字符串结束符使用带长度的缓冲区解析,别依赖strlen
网页表单或日志出现大量菱形问号扩展编码不一致,比如UTF-8被按Latin-1解码统一用UTF-8,确认charset
Backspace按下去终端没反应或删错位置收到0x08和0x7F的处理策略不同查终端配置和驱动对两个码的响应

6.2 逐个排查与避坑

第一个常见坑是“用十六进制却写成了十进制”。协议文档写0x41,有人看表时盯着十进制65,然后写常量时直接写成十进制的41,数据彻底报废。我的习惯是:凡是和字节流打交道,常量一律写成0x开头,彻底消灭进制错觉。

第二个坑是“把数据当文本,把文本当数据”。串口收上来0x30,可能既是字符‘0’,也是数值48。是文本协议还是二进制协议,取决于双方约定。在协议结构体里,一个字段到底是uint8还是char,完全决定了后面的解析路径。不要因为正好打印出可打印字符,就默认它是字符串。

第三个坑是隐藏的半角全角问题。比如同一个数字字符,全角‘5’在Unicode里根本不是ASCII的0x35,而是U+FF15。你在代码里判断c >= '0' && c <= '9'只能过滤半角ASCII数字,遇到全角就会放进来。做输入校验时,先确认输入字符编码范围。

我调试时还习惯性地在打印日志里保留十六进制视图。不要只打%s看可读文本,因为不可见字符一旦混进去,肉眼完全看不出来。最稳妥的日志格式是“十六进制+ASCII对照”,这样既能看到真实字节,又能快速识别可读内容。

7. 最后说两句

做底层和通信越久,我越觉得ASCII表不是背完就完事的东西,它更像一把钥匙,打开的是“字符如何编码、字节如何解释”这扇门。我自己电脑桌面背景就有一张ASCII码对应表,平时调试时瞟一眼就够,比翻网页省几秒钟,但积累下来省下的时间真不少。另外一个小建议:把常用字符的十六进制写法练成肌肉记忆,例如空格0x20、LF是0x0A、CR是0x0D、ESC是0x1B,这几个字符在我处理过的协议里出场率最高。遇到复杂的协议和数据格式,能随口报出这些码值,很多问题在刚露苗头时就能直接掐掉,不至于在日志海洋里翻半天才回过神来。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/27 23:52:20

新飞鸟采集框架:Docker化部署与YAML规则驱动的防封爬虫实践

简介&#xff1a;本资源是一套基于H5技术栈的完整开源飞鸟系统修改版&#xff0c;面向Web开发者与站长群体&#xff0c;解决传统CMS部署复杂、易被封禁等实际运营痛点。资源包含经深度优化的系统源码、详尽的Linux环境&#xff08;ApacheMySQL 5.5PHP 5.4&#xff09;安装配置教…

作者头像 李华
网站建设 2026/9/27 23:42:54

二手车价格预测数据挖掘大作业:从源码到实验报告的完整解析

简介&#xff1a;这是一份面向计算机相关专业学生的数据挖掘课程大作业资源&#xff0c;以二手车价格预测为实战主题&#xff0c;适合作为课程设计、期末大作业或自学练习的完整案例。项目经导师指导并评审通过&#xff0c;得分98分&#xff0c;内容覆盖数据预处理、特征工程、…

作者头像 李华