首页 > 系统相关 >Linux 下 使用点阵在LCD上显示汉字,字符

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

时间:2023-11-01 13:03:11浏览次数:46  
标签:int unsigned 汉字 st char LCD Linux var 点阵

@TOC


前言

这篇文章主要讲一下如何在 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);

总结

效果:

Linux 下 使用点阵在LCD上显示汉字,字符_编码值

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

标签:int,unsigned,汉字,st,char,LCD,Linux,var,点阵
From: https://blog.51cto.com/u_16159289/8120830

相关文章

  • Linux 挂载磁盘详解及实操步骤
    转自:https://www.jb51.net/server/288639rwu.htm步骤如下:一、磁盘分区在Linux中,磁盘是通过分区来使用的。分区是将一个硬盘划分成几个逻辑部分来使用,在每个分区中可以存储不同的文件系统。因此,在挂载磁盘之前,我们需要先对磁盘进行分区。磁盘分区的过程可以通过命令行工具或图形......
  • linux 安装 mysql8
    安装查看版本查看状态......
  • 查看linux操作系统版本:Ubuntu?Centos?还是其他?
    查看内核版本和操作系统版本:uname-a查看系统架构:uname-m查看系统主机名:hostname查看当前登录用户:whoami查看系统已安装的软件包列表:dpkg-l查看系统内存使用情况:free-h查看系统磁盘使用情况:df-h查看系统CPU使用情况:top查看系统网络连接状态:ifconfig查看系统已安装的软件包数量:a......
  • Linux时间校准、时间同步(ntpdate及C代码NTP客户端代码校准示例)
    背景机器每次机启后时间就会出现异常,因为机器无法访问外网,只能访问局域网的ntp服务,所以需要保证局域网内部有ntp服务,如何安装ntp服务,参考Ubuntu20.04Ntp服务安装及验证。网络时间协议NetworkTimeProtocol(NTP)是一种确保时钟保持准确的方法。如果可以访问互联网,只需安装ntp......
  • 宝塔linux面板命令大全
    CentOS安装脚本yuminstall-ywget&&wget-Oinstall.shhttp://download.bt.cn/install/install_6.0.sh&&shinstall.shUbuntu/Deepin安装脚本wget-Oinstall.shhttp://download.bt.cn/install/install-ubuntu_6.0.sh&&sudobashinstall.shDeb......
  • Linux配置环境变量
    1.什么是环境变量环境变量(environmentvariables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件夹位置和系统文件夹位置等。环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。例如Windows和DOS操作系统中的path......
  • 如何在linux系统中安装python3.8.1 并卸载 python3.6.2 更新python3引导到3.8.1
    安装python3.8.1步骤1:检查Python版本在终端中输入以下命令来检查当前安装的Python版本:python--version步骤2:安装编译Python所需的依赖项更新系统软件包,并安装构建Python所需的一些工具和库。在终端中运行以下命令:sudoaptupdatesudoapt-getinstall-ybuild-essen......
  • linuxjava安装
    linux安装java1.8一、确认是否安装JDK,通过rpm-qa|grepjava命令查看然后https://www.oracle.com/java/technologies/downloads/#java8下载java二.进入user/local这个目录是管理员安装引用程序的目录三.进行文件上传然后把文件拖进新开的窗口里就ok了三.通过tar-......
  • linux 中paste命令结合管道时调整合并方向
     001、[root@pc1test]#ls##两个测试文件a.txtb.txt[root@pc1test]#cata.txt010203040506070809101112[root@pc1test]#catb.txtabc[root@pc1test]#cut-f2a.txt|paste-b.txt......
  • Linux中中括号{}应用与for循环的可迭代对象
     001、[root@pc1test]#foriinab8ab23ab98;doecho$i;done##直接迭代ab8ab23ab98[root@pc1test]#foriinab{8,23,98};doecho$i;done##可以写成如下形式ab8ab23ab98[root@pc1test]#foriinab{8,23yt,98};doecho$i;done......