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

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

前言


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

1

二、显示汉字


显示汉字,我们可以从网上下载 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);


总结

效果:



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


相关文章
|
7月前
|
数据采集 Shell Linux
【Shell 命令集合 文档编辑】Linux 字符转换或删除 tr 命令使用指南
【Shell 命令集合 文档编辑】Linux 字符转换或删除 tr 命令使用指南
118 0
|
7月前
|
Linux 编译器 C语言
Linux应用开发基础知识——字符文字编码(五)
Linux应用开发基础知识——字符文字编码(五)
173 0
Linux应用开发基础知识——字符文字编码(五)
|
7月前
|
Linux
如何在 Linux 中创建带有特殊字符的文件?
如何在 Linux 中创建带有特殊字符的文件?
121 0
|
7月前
|
Unix Java Linux
Linux脚本中的字符处理与awk编程|WC统计
Linux脚本中的字符处理与awk编程|WC统计
101 0
|
Linux
linux系统中字符设备驱动开发方法
linux系统中字符设备驱动开发方法
94 0
|
1月前
|
Linux 开发工具 Perl
在Linux中,有一个文件,如何删除包含“www“字样的字符?
在Linux中,如果你想删除一个文件中包含特定字样(如“www”)的所有字符或行,你可以使用多种文本处理工具来实现。以下是一些常见的方法:
41 5
|
2月前
|
Linux 开发工具 Perl
Linux命令替换目录下所有文件里有"\n"的字符为""如何操作?
【10月更文挑战第20天】Linux命令替换目录下所有文件里有"\n"的字符为""如何操作?
48 4
|
6月前
|
Linux
Linux交叉编译+粤嵌LCD实现三色图
Linux交叉编译+粤嵌LCD实现三色图
|
4月前
|
Linux 开发工具 Perl
在Linux中,有一个文件,如何删除包含“www“字样的字符?
在Linux中,有一个文件,如何删除包含“www“字样的字符?
|
4月前
|
存储 Linux 数据库
Linux源码阅读笔记16-文件系统关联及字符设备操作
Linux源码阅读笔记16-文件系统关联及字符设备操作