前言
正常情況下,使用 printf 向串口打印調(diào)試信息,在串口調(diào)試工具界面只能看到一種顏色的字符,且使用不同的串口調(diào)試工具,字符默認的顏色都不一樣。
如果你在 VSCode 上使用過 ESP-IDF 開發(fā) ESP32 應用程序,你會發(fā)現(xiàn)其終端上輸出的調(diào)試信息是五顏六色的,十分花哨。 而且不同類型的調(diào)試信息使用不同的顏色區(qū)分,能夠快速地定位到程序中的問題,非常便捷實用。
那么我們使用 printf 函數(shù)通過串口能否輸出彩色的調(diào)試信息呢? 答案是肯定的,只是需要一丟丟小技巧罷了。
ANSI 轉(zhuǎn)義序列
在介紹如何打印彩色調(diào)試信息之前,我們先來了解一些背景知識 —— ANSI 轉(zhuǎn)義序列。
我們將信息打印到終端上顯示時,可以控制信息顯示成粗體、斜體、下劃線等形式,也可以控制字符顯示不同的顏色。
例如執(zhí)行如下代碼,會在終端上顯示紅色 ---testing---:
printf("\\033[31m---testing---\\n");
為什么有些字符會被當做信息顯示,有些字符會被當做命令處理? 其實這一切都歸功于轉(zhuǎn)義字符。
在C語言中,用反斜杠 "" 作為轉(zhuǎn)義字符,正常情況下,"" 和 "n" 都是普通的字符,但是將這兩個字符組合起來變成 "\\n" 的字符序列后,就表示換行符了。
在終端中也有類似的用法,只不過終端中的轉(zhuǎn)義字符不是反斜杠 "" ,而是 "ESC"。 終端使用 "ESC" 作為轉(zhuǎn)義字符,而 "ESC" 在 ASCII 表中的序號是 27,也就是 0x1b,因此終端中與 0x1b 組合起來的字符序列就會被轉(zhuǎn)義成命令,不同的字符組合表示不同的終端命令,這些轉(zhuǎn)義規(guī)則被規(guī)范化以后,就叫做 ANSI 轉(zhuǎn)義序列(ANSI Escape Sequences), 主要用來控制終端上光標位置、顏色及其他選項。
ANSI 轉(zhuǎn)義序列起始標志
ANSI 轉(zhuǎn)義序列起始標志由兩個字節(jié)組成,第一個字節(jié)是終端轉(zhuǎn)義字符 "ESC" 也就是 0x1b,第二個字節(jié)的取值范圍是0x40–0x5F(即 ASCII:@ A – Z [ \\ ] ^ _),也就是說 ANSI 轉(zhuǎn)義序列的起始標志共有如下幾種:
- x1b@(ESC@)
- x1bA(掃描)
- x1b-(電調(diào)-)
- x1bZ(ESCZ)
- x1b[(ESC[)
- x1b\\(ESC\\)
- x1b](ESC])
- x1b^(ESC^)
- x1b_(ESC_)
上述那么多種起始標志,常見的起始標志就是 " x1b[ " ,其他的起始標志現(xiàn)在都很少用到了。
控制符起始標志 CSI
當 0x1b 與 "[" 組合時,就叫做控制符起始標志(Control Sequence Introducer),簡稱為 CSI ,其基本格式如下:
x1b[<code><tail>
code: 轉(zhuǎn)義序列的具體內(nèi)容,多個內(nèi)容之間使用分號 ";" 隔開
tail : 轉(zhuǎn)義序列結(jié)束標志,不同 tail 表示不同功能的序列
以 CSI 開頭的轉(zhuǎn)義序列有很多,不同的序列表示不同的終端指令,大致可以分為如下幾類:
- 字符渲染指令(SGR)
- 光標移動指令
- 清屏指令
- 終端控制指令
字符渲染指令
字符渲指令(Select Graphic Rendition),簡稱為 SGR 。主要用于設置字符顯示效果,其基本格式如下:
CSI編號
CSI:控制符起始標志 " 0x1b[ "
n :取值范圍 0 ~ 107
m :轉(zhuǎn)義序列結(jié)束標志,字母 m 作為結(jié)尾,表明是字符渲染序列
示例:
x1b[3m
n 的取值范圍是 0 ~ 107,主要分為如下兩類功能:
- 字符樣式控制
- 字符顏色控制
n 的取值及說明:
n | 功能 | 示例 |
---|---|---|
0 | 重置/正常 | x1b[0m 或 x1b[m |
1 | 粗體或增加強度 | x1b[1m |
2 | 弱化(降低強度) | x1b[2m |
3 | 斜體 | x1b[3m |
4 | 下劃線 | x1b[4m |
5 | 緩慢閃爍 | ...... |
6 | 快速閃爍 | ...... |
7 | 反顯 | ...... |
8 | 隱藏 | ...... |
9 | 劃除 | ...... |
10 | 主要(默認)字體 | ...... |
11–19 | 替代字體 | ...... |
20 | 尖角體 | ...... |
21 | 關閉粗體或雙下劃線 | ...... |
22 | 正常顏色或強度 | ...... |
23 | 非斜體、非尖角體 | ...... |
24 | 關閉下劃線 | ...... |
25 | 關閉閃爍 | ...... |
27 | 關閉反顯 | ...... |
28 | 關閉隱藏 | ...... |
29 | 關閉劃除 | ...... |
30–37 | 設置前景色 | ...... |
38 | 設置前景色 | ...... |
39 | 默認前景色 | ...... |
40–47 | 設置背景色 | ...... |
48 | 設置背景色 | ...... |
49 | 默認背景色 | ...... |
51 | Framed | ...... |
52 | Encircled | ...... |
53 | 上劃線 | ...... |
54 | Not framed or encircled | ...... |
55 | 關閉上劃線 | ...... |
60 | 表意文字下劃線或右邊線 | ...... |
61 | 表意文字雙下劃線或雙右邊線 | ...... |
62 | 表意文字上劃線或左邊線 | ...... |
63 | 表意文字雙上劃線或雙左邊線 | ...... |
64 | 表意文字著重標志 | ...... |
65 | 表意文字屬性關閉 | ...... |
90–97 | 設置明亮的前景色 | ...... |
100–107 | 設置明亮的背景色 | ...... |
有了上述這些背景知識,就足夠搞懂串口輸出彩色調(diào)試信息的原理了,關于 ANSI 轉(zhuǎn)義序列的更多內(nèi)容,感興趣的小伙伴可以自行查閱。
串口輸出彩色調(diào)試信息
在 《單片機 printf 重定向串口輸出調(diào)試信息》這篇文章中介紹了如何使用 printf 通過串口輸出調(diào)試信息,那么現(xiàn)在就在此基礎上,再說說如何將輸出的調(diào)試信息變成彩色的。
通過串口輸出彩色調(diào)試信息有兩個必要條件:
- printf 參數(shù)列表中添加字符顏色控制相關的 ANSI轉(zhuǎn)義序列
- 接收串口數(shù)據(jù)的串口調(diào)試工具支持 ANSI 轉(zhuǎn)義序列解析
回顧一下上面講到的字符渲指令(SGR),其基本格式如下:
CSI n m
CSI:控制符起始標志 " 0x1b[ "
n :取值范圍 0 ~ 107
m :轉(zhuǎn)義序列結(jié)束標志,字母 m 作為結(jié)尾,表明是字符渲染序列
當我們想要輸出不同顏色的字符時,將 n 替換成對應的數(shù)字即可,常見的顏色如下:
n | 功能 | 示例 |
---|---|---|
30 | 黑色 | x1b[30m |
31 | 紅色 | x1b[31m |
32 | 綠色 | x1b[32m |
33 | 黃色 | x1b[33m |
34 | 藍色 | x1b[34m |
35 | 品紅 | x1b[35m |
36 | 青色 | x1b[36m |
使用 printf 打印 "Hello World" 代碼如下:
printf("Hello World\\n");
打印不同的 "Hello World" 代碼如下:
printf("\\x1b[31m" "Hello World\\n" "\\x1b[0m");
printf("\\x1b[32m" "Hello World\\n" "\\x1b[0m");
printf("\\x1b[33m" "Hello World\\n" "\\x1b[0m");
printf("\\x1b[34m" "Hello World\\n" "\\x1b[0m");
printf("\\x1b[35m" "Hello World\\n" "\\x1b[0m");
printf("\\x1b[36m" "Hello World\\n" "\\x1b[0m");
注意事項
如果使用的串口調(diào)試工具不支持 ANSI 轉(zhuǎn)義序列解析,那么接收到的串口數(shù)據(jù)會有部分亂碼,而且只會使用工具默認的顏色顯示信息:
支持 ANSI 轉(zhuǎn)義序列解析的串口調(diào)試工具才能正常顯示彩色字符,推薦使用 MobaXterm 。
-
調(diào)試
+關注
關注
7文章
578瀏覽量
33924 -
串口
+關注
關注
14文章
1551瀏覽量
76437 -
函數(shù)
+關注
關注
3文章
4328瀏覽量
62575 -
命令
+關注
關注
5文章
683瀏覽量
22015 -
Printf
+關注
關注
0文章
83瀏覽量
13650
發(fā)布評論請先 登錄
相關推薦
評論