IMX6ULL —— ASCII 字符和中文字符的点阵显示

news2024/10/5 13:35:31

 前言:

使用的开发板为韦东山老师的 IMX6ULL

目录

ASCII 字符的点阵显示

1.获取点阵

2.描点

3.main 函数

4.编译 c 文件 show_ascii.c

中文字符的点阵显示

1.指定编码格式

2.编码格式实验

默认编码

GB2312 转为 UTF-8

UTF-8 转为 GB2312

汉字区位码

​编辑

3.汉字点阵显示实验

打开汉字库文件

编写显示汉字的函数

使用 lcd_put_chinese 函数

编译程序


ASCII 字符的点阵显示

要在 LCD 中显示一个 ASCII 字符,即英文字母这些字符,首先是要找到字符对应的点阵。

在 Linux 内核源码中有这个文件:lib\fonts\font_8x16.c, 里面以数组形式保存各个字符的点阵,比如:

数组里的数字是如何表示点阵的?以字符 A 为例

上图左侧有 16 行数值,每行 1 个字节。每一个节对应右侧一行中 8 个像素: 像素从右边数起,bit0 对应第 0 个像素,bit1 对应第 1 个像素,……,bit7 对 应第 7 个像素。某位的值为 1 时,表示对应的像素要被点亮;值为 0 时表示对应 的像素要熄灭。

所以要显示某个字符时,根据它的 ASCII 码在 fontdata_8x16 数组中找到它的点阵,然后取出这 16 个字节去描画 16 行像素。

比如字符 A 的 ASCII 值是 0x41,那么从 fontdata_8x16[0x41*16]开始取其点阵数据。

核心函数是

void lcd_put_ascii(int x, int y, unsigned char c)

 它在 LCD 的(x,y)位置处显示字符 c,代码如下图所示:

1.获取点阵

对于字符 c,char c,它的点阵获取方法如下:

4693 unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];

2.描点

因为有十六行,所以首先要有一个循环 16 次的大循环,然后每一行里有 8 位,那么在每一个大循环里也需要一个循环 8 次的小循环。小循环里的判断单行 的描点情况,如果是 1,就填充白色,如果是 0 就填充黑色,如此一来,就可以显示出黑色底,白色轮廓的英文字母。

4697     for (i = 0; i < 16; i++)
4698     {
4699         byte = dots[i];
4700         for (b = 7; b >= 0; b--)
4701         {
4702             if (byte & (1<<b))
4703             {
4704                 /* show */
4705                 lcd_put_pixel(x+7-b, y+i, 0xffffff); /* 白 */
4706             }
4707             else
4708             {
4709                 /* hide */
4710                 lcd_put_pixel(x+7-b, y+i, 0); /* 黑 */
4711             }
4712         }
4713 }

3.main 函数

main 函数中首先要打开 LCD 设备,获取 Framebuffer 参数,实现 lcd_put_pixel 函数;

然后调用 lcd_put_ascii 即可绘制字符

4716 int main(int argc, char **argv)
4717 {
4718     fd_fb = open("/dev/fb0", O_RDWR);
4719     if (fd_fb < 0)
4720     {
4721         printf("can't open /dev/fb0\n");
4722         return -1;
4723     }
4724     if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
4725     {
4726         printf("can't get var\n");
4727         return -1;
4728     }
4729
4730     line_width = var.xres * var.bits_per_pixel / 8;
4731     pixel_width = var.bits_per_pixel / 8;
4732     screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
4733     fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP
                _SHARED, fd_fb, 0);
4734     if (fbmem == (unsigned char *)-1)
4735     {
4736         printf("can't mmap\n");
4737         return -1;
4738     }
4739
4740     /* 清屏: 全部设为黑色 */
4741     memset(fbmem, 0, screen_size);
4742
4743     lcd_put_ascii(var.xres/2, var.yres/2, 'A'); /*在屏幕中间显示 8*16 的字母 A*/
4744
4745     munmap(fbmem , screen_size);
4746     close(fd_fb);
4747
4748     return 0;
4749 }
4750

4.编译 c 文件 show_ascii.c

交叉编译:不同的板子,编译工具的前缀可能不一样,这是使用的是IMX6ULL

arm-buildroot-linux-gnueabihf-gcc -o show_ascii show_ascii.c

把 show_ascii 程序通过 NFS 挂载放到板子上,执行命令:./show_ascii。如果实验成功,我们将看到屏幕中间会显示出一个白色的字母‘A’。

中文字符的点阵显示

1.指定编码格式

使用点阵字库时,中文字符的显示原理跟 ASCII 字符是一样的。要注意的地 方在于中文的编码:在 C 源文件中它的编码方式是 GB2312 还是 UTF-8?编译出 的可执行程序,其中的汉字编码方式是 GB2312 还是 UTF-8?

注意:一般不会使用 UTF-16 的编码方式,在这种方式下 ASCII 字符也是用 2 字 节来表示,而其中一个字节是 0,但是在 C 语言中 0 表示字符串的结束符,会引起误会。

我们编写 C 程序时,可以使用 ANSI 编码,或是 UTF-8 编码;在编译程序时, 可以使用以下的选项告诉编译器:

-finput-charset=GB2312

-finput-charset=UTF-8

如果不指定“-finput-charset”,GCC 就会默认 C 程序的编码方式为 UTF-8,即使你是以 ANSI 格式保存,也会被当作 UTF-8 来对待。

对于编译出来的可执行程序,可以指定它里面的字符是以什么方式编码,可以使用以下的选项编译器:

-fexec-charset=GB2312

-fexec-charset=UTF-8

如果不指定“-fexec-charset”,GCC 就会默认编译出的可执行程序中字符 的编码方式为 UTF-8。 如果“-finput-charset”与“-fexec-charset”不一样,编译器会进行格式转换

2.编码格式实验

下面做实验。

test_charset_ansi.c、test_charset_utf8.c 的编码格式分别为 ANSI、 UTF-8,它们的程序代码是一样的,如下:

01 #include <stdio.h>
02 #include <string.h>
03
04 int main(int argc, char **argv)
05 {
06     char *str = "A 中";
07     int i;
08
09     printf("str's len = %d\n", (int)strlen(str));
10     printf("Hex code: ");
11     for (i = 0; i < strlen(str); i++)
12     {
13         printf("%02x ", (unsigned char)str[i]);
14     }
15     printf("\n");
16     return 0;
17 }
默认编码

实验如下:

不指定“-finput-charset”与“-fexec-charset”时,input-charset 和 exec-charset 默认都是 UTF-8,不会进行编码转换。即使 C 文件是 ANSI, 也会被认为是 UTF-8,所以不会导致编码转换。

GB2312 转为 UTF-8

实验如下:

从上面的输出信息可以看出来,GB2312 的“0xd6 0xd0”可以转换为 UTF-8 的“0xe4 0xb8 0xad”。而如果把原本就是 UTF-8 格式的 test_charset_utf8.c 当作 GB2312 格式,会引起错误。

UTF-8 转为 GB2312

实验如下:

从 上 面 的 输 出 信 息 可 以 看 出 来 , 如 果 把 原 本 就 是 GB2312 格式的 test_charset_ansi.c 当作 UTF-8 格式,会引起错误。而 UTF-8 格式的“中”编 码值为“0xe4 0xb8 0xad”,可以转换为 GB2312 的“0xd6 0xd0”。

在代码中使用汉字这类非 ASCII 码时,要特别留意编码格式。

汉字区位码

我们从网上搜到 HZK16 这个文件,它是常用汉字的 16*16 点阵字库。HZK16 里每个汉字使用 32 字节来描述,如图所示:

跟 ASCII 字库一样,每个字节中每一位用来表示一个像素,位值等于 1 时表示对 应像素被点亮,位值等于 0 时表示对应像素被熄灭。

HZK16 中是以 GB2312 编码值来查找点阵的,以“中”字为例,它的编码值 是“0xd6 0xd0”,其中的 0xd6 表示“区码”,表示在哪一个区:第“0xd6 - 0xa1” 区;其中的 0xd0 表示“位码”,表示它是这个区里的哪一个字符:第“0xd0 - 0xa1”个。每一个区有 94 个汉字。区位码从 0xa1 而不是从 0 开始,是为了兼 容 ASCII 码。

所以,我们要显示的“中”字,它的 GB2312 编码是 d6d0,它是 HZK16 里 第“(0xd6-0xa1)*94+(0xd0-0xa1)”个字符。

3.汉字点阵显示实验

打开汉字库文件

第 4787 行打开当前目录的字库文件:HZK16。

第 4793 行获得文件的状态信息,里面含有文件长度,这在后面的 mmap 中 用到。

第 4798 行使用 mmap 映射文件,以后就可以像访问内存一样读取文件内容; mmap 的返回结果保存在 hzkmem 中,它将作为字库的基地址

编写显示汉字的函数

核心函数是 void lcd_put_chinese(int x, int y, unsigned char *str) ,它在 LCD 的(x,y)位置处显示汉字字符 str,str[0]中保存区码、str[1] 中保存位码。

代码如下图所示:

代码分解如下:

第 4734 行确定该汉字属于哪个区;

第 4735 行确实它是该区中哪一个汉字。

第 4736 行确实它的字库地址:每个区中有 94 个汉字,每个汉字在字库中占据 32 字节。

需要根据下图来理解第 4740 行开始的循环:

上图是汉字点阵排布的示意图,总共有十六行,因此需要一个循环 16 次的大循环(第 4740 行)。 考虑到一行有两个字节,在大循环中加入一个 2 次的循环用于区分是哪个字 节(第 4741 行)。

最后使用第 3 个循环来处理一个字节中的 8 位(第 4744 行)。

对于每一位,它等于 1 时对应的像素被设置为白色,它等于 0 时对应的像素被设置为黑色。需要注意的是根据 x、y、i、j、b 来计算像素坐标

使用 lcd_put_chinese 函数

程序文件:show_font.c

编译程序

编译命令:

arm-buildroot-linux-gnueabihf-gcc -o show_chinese show_chinese.c

注意:不同的板子,编译工具的前缀可能不一样。

注意:使用上述命令时 show_chinese.c 的编码格式必须是 ANSI(GB2312),否则编译时需要指定“-fexec-charset=GB2312”。

把 show_chinese 程序放到板子上,执行命令:./show_chinese。如果实验成功,我们将看到屏幕中间会显示出一个白色的字母“A”和“中”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1187507.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

16 _ 二分查找(下):如何快速定位IP对应的省份地址?

通过IP地址来查找IP归属地的功能,不知道你有没有用过?没用过也没关系,你现在可以打开百度,在搜索框里随便输一个IP地址,就会看到它的归属地。 这个功能并不复杂,它是通过维护一个很大的IP地址库来实现的。地址库中包括IP地址范围和归属地的对应关系。 当我们想要查询202…

上海亚商投顾:沪指震荡调整 短剧概念股持续爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数早间低开高走&#xff0c;午后又集体跳水翻绿&#xff0c;临近尾盘有所回升。短剧概念股持续大涨&…

汇编-EQU伪指令(数值替换)

EQU伪指令将一个符号名称与一个整数表达式或一个任意文本相关联&#xff0c; 它有3种格式 在第一种格式中&#xff0c; expression必须是一个有效的整数表达式。在第二种格式中&#xff0c; symbol是一个已存在的符号名称&#xff0c; 已经用或EQU定义过。在第三种格式中&…

Rust语言代码示例

安装Rust语言&#xff0c;然后创建一个新的Rust项目。接下来&#xff0c;你需要安装一个名为"requests"的Rust包&#xff0c;这个包可以帮助你发送请求。然后&#xff0c;你需要安装一个名为"rust-crawler"的Rust包&#xff0c;这个包可以帮助你编写爬虫程…

AI:67-基于深度学习的脱机手写汉字识别

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…

用 Transformer 替换 diffusion 的U-Net:可伸缩的 diffusion 模型

论文标题&#xff1a; Scalable diffusion models with transformers 论文链接&#xff1a;https://openaccess.thecvf.com/content/ICCV2023/html/Peebles_Scalable_Diffusion_Models_with_Transformers_ICCV_2023_paper.html 代码&#xff1a;https://github.com/facebookres…

【EI会议征稿】第四届计算机网络安全与软件工程国际学术会议(CNSSE 2024)

第四届计算机网络安全与软件工程国际学术会议&#xff08;CNSSE 2024&#xff09; 2024 4th International Conference on Computer Network Security and Software Engineering 第四届计算机网络安全与软件工程国际学术会议&#xff08;CNSSE 2024&#xff09;将于2024年2月…

FPBJXDN224、FPBJXDV224插头式电比例节流阀放大器

FPBJXDN224、FPBJXDV224此阀是一款先导控制&#xff0c;常开&#xff0c;电比例节流阀&#xff0c;带反向单向阀。比例电磁铁得电可以在先导级产生作用力&#xff0c;从而比例地关闭主级的阀芯。液流方向为2口流向1口。无论电比例开启还是关闭反向单向阀都允许油液从1口自由流向…

影视小程序源码 付费短剧小程序源码 支持会员模式 多平台支付方式

这是一款功能强大的全开源付费短剧小程序源码&#xff0c;支持多种展现形式&#xff0c;包括付费、免费、任务等方式解锁自由配置。此外&#xff0c;还有用户运营、营销推广、付费观看和成熟代理机制等多种功能。 该小程序源码支持无限滑动、高性能滑动、预加载和视频预览等功能…

天猫店铺所有商品数据接口(Tmall.item_search_shop)

天猫平台店铺所有商品数据接口是开放平台提供的一种API接口&#xff0c;通过调用该接口&#xff0c;开发者可以获取天猫整店的商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片、价格信息等详细信息。 要使用天猫店铺所有商品数据接口&#xff0c;您需要先登录天…

I/O软件层次介绍

一、I/O系统 1.设备独立性软件 2.设备驱动程序 3.中断处理程序 总览 二、输入、输出管理 1.应用程序接口 网络通信方式过程 2.设备驱动程序接口

应用在便携式多媒体播放器中的音频Codec芯片

便携式多媒体播放器(PMP&#xff0c;Portable Media Player)&#xff0c;也就是通常人们所说的MP4。PMP的主要优点是&#xff1a;携带方便&#xff0c;能够直接播放高品质音/视频文件&#xff1b;也可以浏览图片&#xff0c;以及作为移动硬盘使用&#xff1b;此外&#xff0c;P…

对Mysql和应用微服务做TPS压力测试

1.对Mysql 使用工具&#xff1a;mysqlslap工具 使用命令&#xff1a; mysqlslap -uroot pGG8697000!#--auto generate sql -auto generate sql-load typemixed-concurrency100,200 - number of queries1000-iterations10 - number-int-cols7 - number-charcols13auto genera…

PBJ | IF=13.8 利用ChIP-seq和ATAC-seq技术揭示MdRAD5B调控苹果耐旱性的双重分子作用机制

2023年10月24日&#xff0c;西北农林科技大学园艺学院管清美教授团队在Plant Biotechnology Journal&#xff08;最新IF&#xff1a;13.8&#xff09;上发表题为“The chromatin remodeller MdRAD5B enhances drought tolerance by coupling MdLHP1-mediated H3K27me3 in apple…

Word文件损坏怎么办?这3个方法教你轻松解决!

使用Word编写文档时&#xff0c;我们可能会遇到各种各样的问题&#xff0c;这会给我们的学习和工作带来不好的影响。Word文件损坏也是比较常见的一种情况。怎么解决这个问题呢&#xff1f; 如果Word文档损坏后想要恢复应该怎么做呢&#xff1f;小编给大家总结了几个小妙招&…

更改 npm的默认缓存地址

npm的默认缓存一般在C:\Users\用户名\AppData\Roaming路径下的npm和npm_cache&#xff0c;而c盘往往空间不大。 1、在其他盘新建两个文件夹&#xff0c;如D盘&#xff0c;node_cache和node_global。如下图所示。 2、在cmd中执行npm config set prefix “node_cache的路径”&a…

基于ssm的网上药房管理系统的设计与实现(源码+LW+调试)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于java的ssm网上药房管…

阿里云服务器系统怎么选?Alibaba Cloud Linux操作系统介绍

Alibaba Cloud Linux是阿里云基于龙蜥社区&#xff08;OpenAnolis&#xff09;的龙蜥操作系统&#xff08;Anolis OS&#xff09;打造的操作系统发行版&#xff0c;在全面兼容RHEL/CentOS生态的同时也为云上应用程序环境提供Linux社区的增强功能&#xff0c;并针对阿里云基础设…

若依vue-初步下载使用

若依框架可以满足大部分的后台管理系统的开发,使用频率也是比较高的,所以这里讲一下如何使用若依框架 若依框架代码克隆 首先去若依官网 http://www.ruoyi.vip/ 这里演示的是若依-vue版本的使用 我们点击下载 会跳转到码云仓库 或者直接点击下面的链接去码云仓库 https://git…