汉字在屏幕上的显示过程以及乱码的原因

本文详细介绍了计算机屏幕上汉字的显示原理,从文字编码、字库、显卡作用等方面进行阐述。乱码问题的根本原因是文件保存和打开时编码不一致。此外,文章还探讨了键盘输入、编码转换及编程过程中可能出现的乱码情况,强调了编码一致性的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、计算机中的显示原理
要想在计算机的显示器上显示文字,首先你得写一个程序,这个程序的任务就是就是把文字的显示信息发给显卡,显示信息包括在这个屏幕上的输出位置、字的大小等等。然后显卡就知道怎么显示这个字符了。

屏幕上是如何显示文字的原理是什么呢?
屏幕上其实有很多个小灯,小到肉眼看不见,当他们不亮时,屏幕就是黑色的,当他们亮了一部分,如果那一部分刚好是个文字的形状,那么屏幕上就显示文字了。这个原理就跟军训时人摆文字显示字符一样。如下图,通过led灯的开和关显示出了123。放到显示器上,小灯会变得特变小,肉眼很难看到,当一部分红色的小灯亮了,那一部分刚好摆成123的形状,那么红色的123这三个字符就在屏幕上显示出来了。
在这里插入图片描述

如何让显示器得知道是那个灯亮那个灯灭,这就是显卡的作用了,操作系统会根据文字的编码,去字库中找到要显示的字符的点阵数据,点阵数据指明了哪个灯应该亮起,亮起的颜色是什么颜色。显卡会结合点阵数据和其他显示信息,进行计算(比如按照一定比例扩大等),然后发给显示器控制显示器的显示!
注意:这一部分的具体细节我不确定,但是大概的思路应该是没错的。

通过以上得知,关键点在于文字的编码,只要知道了文字的编码,就能找到字库的点阵数据。众所周知,文字的编码有很多种,而乱码的根本原因是文件保存时采用的编码和打开文件时用于解码的编码不一致,从而找到了错误的点阵数据,显示了错误的输出!。

二、从键盘输入开始理解编码的存在形式
以window系统为例,假设你刚刚打开了记事本。
1.你在键盘上按下了’a‘。

2.你的按下触发了电路,键盘扫描到你a被按下,于是键盘形成了’a’的扫描码,发送到了存在于键盘上的寄存器,同时给CPU发送了一个中断信号,告诉CPU我这有活动了!

3.CPU根据键盘的中断线路号检测到是键盘发出的中断信号,于是根据中断号计算出键盘的中断处理程序在内存中的地址,转到键盘的中断处理程序去执行。

4.键盘的中断处理程序找到键盘的驱动程序代码,转到键盘的驱动程序执行。

5.键盘的驱动程序去读取键盘上的保存扫描码的寄存器,把‘a’的扫描码读到内存中。

6.驱动程序把扫描码转换成虚拟码。为什么要转换呢,因为不同的键盘由于厂家不同,型号不同、设计不同的原因,‘a’这个按键产生的扫描码在不同的键盘上是不一样的,为了统一管理,驱动程序得把不同键盘按下的‘a’转换成统一的表示。比如把不同键盘按下的‘a’产生的扫描码统一转换成一个字节的0x41。驱动程序要进行转换,那么驱动程序得知道这是哪种类型的键盘,不然没有转换的依据,原理是键盘的相关信息比如生产厂家、键盘型号等会保存在键盘上的一些只读寄存器中,计算机通过这些只读寄存器就知道这是哪种键盘。从而就知道该键盘的扫描码对应的虚拟码。

7.驱动程序把0x41交给操作系统上自带的且在后台默默运行的的IMM进程。

8.IMM进程把0x41交给系统当前使用的的输入法编辑器。比如搜狗输入法或者百度输入法。系统上所有的输入法,都由IMM管理。

9.输入法收到了0x41,对0x41进行处理,霹雳巴拉一顿操作,首先查到0x41这个值对应的可能的文字,比如可能是‘啊’、‘阿’、‘吖‘…等。首先查询系统当前的代码页是哪一个,也就是系统默认编码,若你没有修改系统的默认编码,则查找的结果为GBK(相当于GB2312)编码的。于是通过GBK的代码页这些可能的文字的GBK编码找出来,通过操作系统从字库中寻找这些可能文字的字库数据,交给显卡,显卡把他们显示出来。

10.显卡把他们显示出来后,屏幕上显示了好多个文字让你选择,那么你通过键盘的左移右移回车等操作选中了一个字,这个键盘操作又产生扫描码,最后还是输入法接收到了你的键盘按键输入情况&#x

### Arduino OLED 显示中文乱码解决方案 当在Arduino平台上使用OLED屏幕显示中文时遇到乱码问题,通常是因为字体库未正确加载或编码方式不对。为了确保中文能够被正确解析并显示,在初始化U8g2对象之后,需指定支持汉字的字模文件。 对于ESP32控制板而言,推荐采用GB2312编码格式来处理简体中文字符串,并通过特定的C/C++程序结构定义这些字符集[^1]。此外,考虑到内存占用情况以及性能优化需求,建议预先准备好所需的中文字型位图数据,将其存储于外部Flash芯片内或是直接编译进入固件之中。 针对具体的实施步骤: - **选择合适的字体库**:确认使用的U8g2版本已内置对GBK的支持;如果不是,则应寻找第三方提供的扩展包。 - **设置正确的文本模式**:利用`u8g2Fonts.h`头文件里的API配置好相应的参数,比如字号大小、方向等属性。 - **转换输入串为内部表示法**:由于ASCII之外的语言符号无法简单映射到单字节空间里去,所以要借助专门的方法完成多字节序列至图形坐标系下的变换过程。 下面给出一段简单的代码片段用于展示如何让ESP32配合U8G2库成功渲染出清晰可读的汉语词汇: ```cpp #include <Wire.h> #include <SPI.h> #include <U8g2lib.h> // 如果使用的是软件I2C接口,请替换这里的引脚编号 #define I2C_SDA 21 #define I2C_SCL 22 const uint8_t chineseFont[] PROGMEM = { // 这里放置从其他资源获得的具体字形图案... }; void setup(void) { u8g2.begin(); u8g2.setFont(u8g2_font_wqy16_t_gb2312b); // 设置为WenQuanYi 16pt 字体 } void loop(void){ u8g2.firstPage(); do { // 清除缓冲区内容 u8g2.clearBuffer(); // 输出测试语句 const char *text="你好世界"; int x=0,y=10; for(int i=0;text[i]!='\0';++i){ unsigned short codepoint=utf8_to_unicode(text+i); drawChineseCharacter(codepoint,x,y,&u8g2); x+=16; // 增加下一个字符的位置偏移量 while(utf8_skip_bytes(text+i)>0)i++; } } while ( u8g2.nextPage() ); } ``` 此段代码展示了基本框架,实际应用还需要根据具体情况调整细节部分,例如自定义函数`drawChineseCharacter()`负责绘制单个汉字,而辅助工具函数`utf8_to_unicode()`用来将UTF-8编码形式转化为Unicode数值以便后续操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值