Linux 下 使用点阵在LCD上显示汉字,字符

news/2024/4/26 18:49:58/文章来源:https://blog.csdn.net/wuyiyu_/article/details/128414827

文章目录

  • 前言
  • 一、显示字符
      • 1.获取点阵:
      • 2.描点(显示字符函数):
      • 3. 要打开LCD设备:
      • 4. 通过ioctl 获取Framebuffer参数:
      • 5. 通过mmap映射出Framebuffer的地址:
      • 6.清屏并显示字符:
  • 二、显示汉字
      • 1.区位码:
      • 2. 打开汉字库文件:
      • 3.显示汉字函数:
  • 总结


前言

这篇文章主要讲一下如何在 LCD 上使用点阵显示汉字,字符 ,修改颜色 及效果展示。其中包含了几个核心函数,我们需要了解。

一、显示字符

1.获取点阵:

各个字符对应的点阵都保存在一个数组里,大家可以打开 font_8x16.c 中得到点阵。(不同的点阵对应不同的代码,这里我使用的是 8x16 的点阵 )

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

2.描点(显示字符函数):

找到点阵,将里面需要的点上色就可以在 LCD 上显示出不同的字符
我们使用的是 8x16 的点阵 ,点阵有十六行,每一行里有8位。所以首先要有一个循环16次的大循环代表每一行,在每一个大循环里也需要一个循环8次的小循环,代表每一位。

x ,y : 代表对应点的横纵坐标
c : 表示你要显示的字符
lcd_put_pixel 此函数为描点函数,在 Linux 应用基础 Framebuffer应用编程 中我已详细的写出该函数。(第一二个参数代表x,y 坐标 。第三个参数代表颜色,可任意修改。)

void lcd_put_ascii(int x, int y, unsigned char c)
{unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];int i, b;unsigned char byte;for (i = 0; i < 16; i++){byte = dots[i];for (b = 7; b >= 0; b--){if (byte & (1<<b)){/* show */lcd_put_pixel(x+7-b, y+i, 0x00ff00); /* 绿色 */}else{/* hide */lcd_put_pixel(x+7-b, y+i, 0); /* 黑 */}}}
}

3. 要打开LCD设备:

对于不同的板子,你的 framebuffer 节点可能有所不同,需注意。

	int fd_fb;fd_fb = open("/dev/fb0", O_RDWR);

4. 通过ioctl 获取Framebuffer参数:

将得到的数据保存在 var 结构体中。这个结构体如果不了解的可以参考 Linux 应用基础 Framebuffer应用编程,我都已详细的说明。

	struct fb_var_screeninfo var;if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))

5. 通过mmap映射出Framebuffer的地址:

要映射一块内存,就需要知道它的大小和地址。
screen_size : 为该内存的地址。(整个framebuffer 的大小)

	line_width  = var.xres * var.bits_per_pixel / 8;pixel_width = var.bits_per_pixel / 8;screen_size = var.xres * var.yres * var.bits_per_pixel / 8;fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);

6.清屏并显示字符:

使用 memset 将屏幕变成黑色,再显示字符,便于观察。

	memset(fbmem, 0, screen_size);lcd_put_ascii(var.xres/2, var.yres/2, 'A'); /*在屏幕中间显示8*16的字母A*/

注意: 上面我们映射了一块内存,我们使用完后需要释放 munmap

munmap(fbmem , screen_size);

二、显示汉字

显示汉字,我们可以从网上下载 HZK16 这个文件, 它是常用汉字的 16*16 点阵字库。HZK16里每个汉字使用32字节来描述

1.区位码:

HZK16中是以 GB2312 编码值来查找点阵的,这里就要涉及汉字的区位码。区位码把GB2312字符集分为94个区,每区含有94个位。一个汉字所在的区号和位号简单地组合在一起就构成了该汉字的"区位码"。

例如:
以“中”字为例,它的编码值是“0xd6 0xd0”,其中的0xd6表示“区码”,表示在哪一个区。其中的0xd0表示“位码”,表示它是这个区里的哪一个字符。由于区位码从0xA1开始,所以 “中” 字在 第“0xd6 - 0xa1”区,第“0xd0 - 0xa1”个。

	unsigned int area  = str[0] - 0xA1; //区码unsigned int where = str[1] - 0xA1; //位码unsigned char *dots = hzkmem + (area * 94 + where)*32;//每一个区有94个汉字每个汉字占了32个字节

2. 打开汉字库文件:

struct stat 这个结构体是用来描述一个linux系统文件系统中的文件属性的结构。通过 fstat 函数获得文件状态,保存到 hzk_stat 结构体中。

	int fd_hzk16;struct stat hzk_stat;fd_hzk16 = open("HZK16", O_RDONLY);if (fd_hzk16 < 0){printf("can't open HZK16\n");return -1;}if(fstat(fd_hzk16, &hzk_stat)){printf("can't get fstat\n");return -1;}hzkmem = (unsigned char *)mmap(NULL , hzk_stat.st_size, PROT_READ, MAP_SHARED, fd_hzk16, 0);if (hzkmem == (unsigned char *)-1){printf("can't mmap for hzk16\n");return -1;}

下面是 struct stat 结构体:

struct stat {mode_t     st_mode;       //文件对应的模式,文件,目录等ino_t      st_ino;       //inode节点号dev_t      st_dev;        //设备号码dev_t      st_rdev;       //特殊设备号码nlink_t    st_nlink;      //文件的连接数uid_t      st_uid;        //文件所有者gid_t      st_gid;        //文件所有者对应的组off_t      st_size;       //普通文件,对应的文件字节数time_t     st_atime;      //文件最后被访问的时间time_t     st_mtime;      //文件内容最后被修改的时间time_t     st_ctime;      //文件状态改变时间blksize_t st_blksize;    //文件内容对应的块大小blkcnt_t   st_blocks;     //伟建内容对应的块数量};

3.显示汉字函数:

void lcd_put_chinese(int x, int y, unsigned char *str,unsigned int color)
{unsigned int area  = str[0] - 0xA1; //区码unsigned int where = str[1] - 0xA1; //位码unsigned char *dots = hzkmem + (area * 94 + where)*32;//每一个区有94个汉字每个汉字占了32个字节unsigned char byte;int i, j, b;for (i = 0; i < 16; i++){for (j = 0; j < 2; j++){byte = dots[i*2 + j];for (b = 7; b >=0; b--){if (byte & (1<<b)){/* show */lcd_put_pixel(x+j*8+7-b, y+i, 0x00ff00); /* 绿色 */}else{/* hide */lcd_put_pixel(x+j*8+7-b, y+i, 0); /* 黑 */}	}}}
}

可在主函数里面调用 :

	unsigned char str1[] = "你";unsigned char str2[] = "好";lcd_put_chinese(var.xres/2 + 8,  var.yres/2, str1);lcd_put_chinese(var.xres/2 + 8+16,  var.yres/2, str2);

总结

效果:
在这里插入图片描述

大家可以自行实践一下,有不懂的欢迎留言讨论。

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多线程基础入门

文章目录前言一、认识线程&#xff08;一&#xff09;概念1.线程是什么2.为啥要有线程&#xff08;轻量级进程&#xff09;为什么线程比进程更轻量经典面试题&#xff1a;谈谈进程和线程的区别和联系3.线程的结构&#xff08;二&#xff09;第一个多线程程序&#xff08;三&…

我国用电信息采集系统行业应用需求及市场容量分析 现6省上线运行

用户用电信息采集系统是通过对配电变压器和终端用户的用电数据的采集和分析&#xff0c;实现用电监控、推行阶梯定价、负荷管理、线损分析&#xff0c;最终达到自动抄表、错峰用电、用电检查&#xff08;防窃电&#xff09;、负荷预测和节约用电成本等目的。建立全面的用户用电…

RabbitMQ 第一天 基础 4 RabbitMQ 的工作模式 4.4 Topic 通配符模式 4.5 工作模式总结

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第一天 基础4 RabbitMQ 的工作模式4.4 Topic 通配符模式4.4.1 模式说明4.4.2 代码编写4.4.3 小结4.5 工作模式总结第一天 基础 4 RabbitMQ 的工作模式 4.4 Topic 通配符模式 …

32天高效突击:开源框架+性能优化+微服务架构+分布式,面阿里获P7(脑图、笔记、面试考点全都有)

今年的大环境不佳&#xff0c;所以大部分的人在今年的招聘旺季都没有收获到好的结果。 但不要着急&#xff0c;今天分享的内容则是由 一位阿里P7的面试心得&#xff0c;通过32天的高效突击训练&#xff0c;成功拿下offer的学习方法。 篇章分为三大章节&#xff0c;可以根据自…

day 10 模拟和高精度

P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布 #include<bits/stdc.h> using namespace std; int n, na, nb, fa, fb;//f:得分 int a[205], b[205];void fun(int ta, int tb){if(ta 0 && tb 1) fb;if(ta 1 && tb 0) fa;if(ta 0 && tb …

【nowcoder】笔试强训Day2

目录 一、选择题 二、编程题 2.1排序子序列 2.2倒置字符串 一、选择题 1.A 派生出子类 B &#xff0c; B 派生出子类 C &#xff0c;并且在 java 源代码有如下声明&#xff1a; 1. A a0new A(); 2. A a1new B(); 3. A a2new C(); 问以下哪个说法是正确的&#xff08;&…

机器学习 | 线性回归

一.基本原理 利用回归方程&#xff08;函数&#xff09;对一个或多个自变量&#xff08;特征值&#xff09;和因变量&#xff08;目标值&#xff09;之间关系进行建模的一种分析方式 根据线性代数&#xff0c;我们可以定义方程 xwy&#xff0c;在线性回归问题中&#xff0c;x…

前端小知识:赋予变量默认值(逻辑与运算符、空值合并运算符、逻辑空运算符)

8. 逻辑与运算符、空值合并运算符、逻辑空运算符&#xff08;可用赋予默认值&#xff09; &#xff08;空值合并运算符&#xff09;官方文档&#xff1a; https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing   &#xff08;逻辑…

【推荐收藏】这份图解算法数据结构的材料太良心

5年前发生的一件事&#xff0c;成为了我职业生涯的重要转折点。当时的我在交大读研&#xff0c;对互联网求职一无所知&#xff0c;但仍然硬着头皮申请了 Microsoft 实习生。面试官让我在白板上写出“快速排序”代码&#xff0c;我畏畏缩缩地写了一个“冒泡排序”&#xff0c;并…

1754. 构造字典序最大的合并字符串

摘要 1754. 构造字典序最大的合并字符串 一 贪心算法分析 题目要求合并两个字符串 word1 与 word2&#xff0c;且要求合并后的字符串字典序最大。首先需要观察一下合并的选择规律&#xff0c;假设当前需要从 word1​ 的第 i 个字符和 word2​ 的第 j个字符选择一个字符加入到…

自制macOS安装镜像iso虚拟机用

在网上下载的用于在虚拟机中安装的镜像版本相对比较旧。安装完成后还要进行升级比较麻烦。于是我就想自己制作安装镜像了。 精华 #创建空白磁盘镜像 hdiutil create -o /tmp/ventura -size 13800m -volname ventura -layout SPUD -fs HFSJ #挂载上面创建的镜像 hdiutil attac…

内容资产管理11问

&#x1f447;点击一键关注主笔&#xff1a;邹小困、邝晴岚主持人&#xff1a;增长黑盒分析师Emma出品&#xff1a;增长黑盒研究组前言在这个信息爆炸的数据时代&#xff0c;各个行业正积极推进数字化转型&#xff0c;产业升级与技术赋能成为主题之一。在推进企业线上线下融合的…

最近面试遇到一个算法题,简单写一点。

第⼀题&#xff08;必答&#xff09; 请针对有重复数字的数组设计⼀个快排算法&#xff0c;⽐如&#xff1a;[34, 34, 89, 1, 1, 20, 12]&#xff0c;排序后结果为 [89,34,34,20,12,1,1] 第⼆题&#xff08;必答&#xff09; 请利⽤Redis 实现⼀个通⽤分布式锁&#xff0c;并…

B+树 [数据结构与算法][Java]

B树 B树是B树的一种变形 我们通过一颗四阶B树来理解认识一下B树:(如下:) 我们其实从图上就可以看出B树和B树是有很多不同之处的 比如我们的B树中将叶子结点层的所有结点使用一个链表串联了起来B树中对于非叶子结点都是只是存储的索引(指针), 并没有存储关键字, 所以我们最终查…

Linux系统基础——BIOS和Bootloader

BIOS和Bootloader 特此说明: 刘超的趣谈linux操作系统是比较重要的参考资料&#xff0c;本文大部分内容和所有图片来源于这个专栏。 1 了解背景 1.1 目的 操作系统不是在板子上电就直接运行的&#xff0c;上电到系统启动的中间过程要搞明白&#xff0c;比如了解linux系统启动…

火山引擎 DataTester 上线“流程画布”功能,支持组合型 A/B 实验分析

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 在精细化运营的时代&#xff0c;运营活动同样需要有精细化的策略&#xff0c;例如在年末大促活动中&#xff0c;设计 APP 弹窗提醒、满减、会员领券时&#xff0c;我…

TikTok 加速团结独立站,跨境电商的又一次红利期?

TikTok近年来在国际上非常流行。2021年8月&#xff0c;TikTok的全球下载量首次超过Facebook&#xff0c;成为全球最大的下载量。TikTok的诞生打破了海外社交媒体的垄断&#xff0c;TikTok营销成为许多跨境卖家的重点之一。 封号事件发生后&#xff0c;许多跨境卖家开始向独立站…

Python函数总结

在Python中&#xff0c;函数是一个带有名字的代码块&#xff0c;可以被反复调用。函数可以帮助你组织和重用代码&#xff0c;使你的程序更整洁&#xff0c;更易于维护。本文将会深入探索Python的秘密 目录 定义函数 自定义函数 内置函数 函数式方程 高阶函数 函数标注 …

读研2年,我选择从中科院退学转行做码农

从入学天坑材料专业到退学 先自我介绍一下&#xff1a;我天坑材料专业&#xff0c;本科某211&#xff0c;保研到中科院&#xff0c;但是我真是菜的抠脚&#xff0c;还懒&#xff0c;也不喜欢科研&#xff0c;论文达不到毕业要求&#xff0c;纠结之下研三退学转码农了。 读了2…

JVM【垃圾回收相关概念和垃圾回收器】

垃圾回收相关概念 System.gc()的理解 在默认情况下&#xff0c;通过**system.gc&#xff08;&#xff09;**者Runtime.getRuntime().gc() 的调用&#xff0c;会显式触发FullGC&#xff0c;同时对老年代和新生代进行回收&#xff0c;尝试释放被丢弃对象占用的内存。 然而syste…