1.环境

  1. 官方给的内核文件(linux3.4)和根文件系统、linux2.6和配套根文件系统
  2. 不同的内核文件编译时用的交叉编译器不同,linux3.4用4.x的编译器,linux2.6用3.x的编译器,否则不能运行
  3. !!注意:在写代码时要用GB2312编码写,否则程序中的"中"是UTF-8,显示出来就是"涓"字

2.架构思路

  • 打开屏所对应的文件,调用fctl函数使可以用地址来操作文件
  • 获得屏的一些信息(如:屏幕一个像素点占用的位数,屏的分辨率等等)
  • 打开汉字库文件,调用fctl函数使可以用地址来操作文件
  • 获得汉字库文件的一些信息(如大小)
  • 清屏
  • 写ascii字符和汉字

3.知识点

  • LCD设备fb0的file_operations是fb_fops(位于fbmem.c)

    fb_fops的write成员是fb_write()函数.

    发现write()函数直接是对显存地址写数据, 所以使用echo “hello”> /dev/fb0时会直接出现乱码(没有点阵信息)

  • ioctl函数

octl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的参数个数如下:int ioctl(int fd, int cmd, …);其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和cmd的意义相关的。

ioctl获取屏幕的信息:ioctl(fd_fb , FBIOGET_FSCREENINFO, &fix)
FBIOGET_VSCREENINFO:获取fb_info-> var成员(可变信息:xy分辨率,像素位数等)
FBIOGET_FSCREENINFO:获取fb_info-> fix成员(固定信息:缓存地址,每行字节数,)
  • mmap函数
    mmap()函数:申请一段用户空间的内存区域,并映射到内核空间某个内存区域.
    申请一块内存映射到某一个文件,然后应用程序直接向内存写数据,即可直接写入这个文件
    即:通过mmap函数可以实现用指针对文件操作
void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);

返回值:失败返回-1,并设置errno值.成功,返回映射的地址指针.若指定start则返回0
start:需要映射的内存起始地址,通常填NULL,表示让系统自动映射,映射成功后返回该地址.

length:映射地址的大小,填LCD显存字节数即可,因为2440一个地址存8位.

prot:对映射地址的保护(protect)方式,常用组合如下:

PROT_EXEC 映射区域可被执行
PROT_READ 映射区域可被读取
PROT_WRITE 映射区域可被写入
PROT_NONE 映射区域不可访问
flag:填MAP_SHARED即可,表示共享此映射,对其它进程可见.

fd:需要将内存映射到哪个文件描述符(以后便可以直接通过内存来直接操作该文件)

offset:映射偏移值,填0即可.

  • ASCII码字库文件使用

在linux工程文件中搜索font,内核有很多font文件,我们使用font_8*16.c,这里面就存着字符对应的点阵信息。

数组的下标就是字符对应的ascii码

  • HZK16汉字库文件使用
    (1)HZK16是按分区表排列的点阵文件,由于每个汉字是2字节,每个字节的点阵是8x16,所以HZK16里的每个汉字点阵大。小:2816=32字节.
    (2)然后还要将编码转为点阵码,我们以"中"为例:
    “中” 的GBK编码为D6 D0.
    转为分区表(每字节减去A1): 35 2F
    所以中的点阵位于:(35*94+2F)32~(3594+2F)*32+31

注意!!

注意编写程序的软件的编码方式是什么,HZK16使用的是GBK的编码,所以如果编辑器的编码方式不是ANSI的,那么就需要在编译的时候加上

 gcc  -finput-charset=UTF-8  -fexec-charset=GBK  -o  ansi ansi.c

附录:源码

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>#define FONTDATAMAX 4096
static const unsigned char fontdata_8x16[FONTDATAMAX] = {... /*asic编码*/
}
int fd_fb;     //屏的文件描述符
int fd_hzk16;  //汉字库文件的描述符
struct fb_var_screeninfo var;   //用来存屏的可变信息的,对应驱动
struct fb_fix_screeninfo fix;   //用来存屏不可变信息的
int screen_size;  //屏幕大小
unsigned char *fbmem;  //屏的framebufferstruct stat hzk_stat;  //汉字文件的属性
unsigned char *hzkmem; //汉字文件的指针,可以直接用这个指针去操作那个文件unsigned int line_width; //一行有多少个字节
unsigned int pixel_width; //一行有多少个字节//color : 0x00RRGGBB
//板子驱动上是每个像素16位
void lcd_put_pixel(int x,int y, unsigned int color)
{unsigned char *pen_8 = fbmem + y*line_width + x*pixel_width; unsigned short *pen_16;unsigned int *pen_32;unsigned int red,green,blue; //这里用int不用char,是因为在给color赋值时需要左移11位,如果是char可能会出错pen_16 = (unsigned short *)pen_8;pen_32 = (unsigned int *)pen_8;switch(var.bits_per_pixel)   //根据每个像素多少位选择用哪个地址{case 8 : *pen_8  = color;break;case 16: {/*565*/red   = (color >> 16) & 0xff;green = (color >> 8) & 0xff;blue  = color &0xff;color = ((red >> 3)<<11) | ((green >> 2)<<5) | (blue >> 3);*pen_16 = color;break;}case 32: *pen_32 = color;break;default:printf("can't support %d bpp\n",var.bits_per_pixel);break; //不能支持这种像素}
}void lcd_put_ascii(int x, int y, unsigned char c)
{//存放字符c的点阵的首地址//每个字符需要16个字节存放,所以第c个字符就是c*16unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];int i,b;unsigned char byte;for(i = 0; i < 16; i++){byte = *(dots+i); // <==> byte=dots[i]for(b = 7; b >= 0; b--){if(byte & (1<<b)){/*show*/lcd_put_pixel(x+7-b , y+i ,0xffffff); //白色}else{/*hide*/lcd_put_pixel(x+7-b , y+i ,0); //黑色}}}}void lcd_put_chinese(int x,int y, unsigned char *str)
{unsigned int area   = str[0] - 0xA1; //这个汉字所在的区,汉字的第一个字符-0xa1unsigned int where  = str[1] - 0xA1; //这个汉字在这个区的什么地方,汉字的第二个字符-0xa1unsigned char *dots =(unsigned char *)(hzkmem + (area*94 + where)*32) ; //一个区有94个字符,一个字符占用32字节(16*16/8) unsigned char byte;int i,j,b;for(i = 0; i < 16; i++){for(j = 0; j < 2; j++){byte = dots[i*2 + j];                //一个汉字占用两个8*16的地方,地址是横着算的,不是先竖着弄完一个8*16,然后再接着另外一个8*16for(b =7; b >=0; b--){if(byte & (1<<b)){/*show*/lcd_put_pixel(x + j*8 + 7-b , y + i , 0xffffff);}else{lcd_put_pixel(x + j*8 + 7-b , y + i , 0);}}}}
}int main(int argc,char **argv)
{unsigned char str[]="中";//屏的初始化fd_fb = open("/dev/fb0",O_RDWR);if(fd_fb <0)            //没打开{printf("can't open /dev/fb0\n");}//首先获得LCD的一些参数,如每个点用多少位来显示,XY的分辨率是多少//这些信息在写LCD驱动的时候,都放在了一个fb_info的结构体中//可以返回去驱看当时的驱动,在lcd_init函数里if(ioctl(fd_fb , FBIOGET_VSCREENINFO, &var))  //可变信息:分辨率、RBG谁在高位、每一个点需要几位数据{printf("can't get var\n");return -1;}if(ioctl(fd_fb , FBIOGET_FSCREENINFO, &fix))  //不可变数据:显存长度、设备名、一行的长度等{printf("can't get fix\n");return -1;}screen_size = var.xres * var.yres *var.bits_per_pixel /8;  //算出一屏有多大,x*y*每个像素的位数/8 (Bytes)pixel_width = var.bits_per_pixel / 8;   //每个像素占多少字节:每个像素占多少位/8line_width = var.xres * pixel_width;    //一行多少个像素乘以每个像素多少字节//这个是把文件当作指针来操作,就不用对文件描述符来操作了//对那个文件描述符操作,就是对framebuffer操作//void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);//            指定地址,不指定系统分配                 属性fbmem =(unsigned char *) mmap(NULL ,screen_size ,PROT_READ|PROT_WRITE , MAP_SHARED , fd_fb , 0);if(fbmem == (unsigned char *)-1){printf("can't mmap\n");}//汉字库初始化fd_hzk16 = open("HZK16",O_RDONLY);if(fd_hzk16 < 0){printf("can't open HZK16\n");return -1;}//int fstat(int fd, struct stat *buf); 获得这个文件的一些信息if(fstat(fd_hzk16 , &hzk_stat)){printf("can't get HZK16\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\n");}/*清屏:全部设为黑色*/memset(fbmem, 0 ,screen_size);lcd_put_ascii(var.xres/2 , var.yres/2 ,'A');printf("chines code: %02x %02x \n",str[0] , str[1]);lcd_put_chinese(var.xres/2+8,var.yres/2,str);}

02.点阵显示中文汉字相关推荐

  1. OpenCV显示中文汉字,未使用CvxText和FreeType库

    OpenCV显示中文汉字,未使用CvxText和FreeType库 采用windows的GDI显示系统的TrueType字体,没有封装,就两个函数,分成了h和cpp文件,可以自己编辑文件名和函数名,亦 ...

  2. 总结一下嵌入式OLED显示屏显示中文汉字的办法

    为什么80%的码农都做不了架构师?>>>    这个问题以为很简单,但最后花很多功夫才能完成,所以总结一下分享给大家. 解决思路 UTF-8->Unicode->GB23 ...

  3. android 只能输入汉字,EditText限制输入的几种方式及只显示中文汉字的做法

    前段时间项目中有个需求是要求只能输入汉字,并且不能输入偏旁部首,于是总结了下EditText限制输入的几种方式,但是对于语音输入的还没找到好的解决方案: 通过设置EditText的inputType来 ...

  4. jetson nano 在opencv拉流的视频上显示中文汉字(含c++完整源码)

    目录 问题 解决方案 步骤一:生成中文图片 步骤二:中文图片蒙皮到视频帧,形成中文显示效果 问题 在jetson nano这样的嵌入式设备上,用opencv拉流,并在实时视频上面,显示汉字. 关于使用 ...

  5. 51单片机教程:51单片机驱动四个8*8点阵,拼凑16*16点阵显示标准汉字。

    看此篇博文之前建议先看博主的上一篇博文: 51单片机教程:8*8 点阵显示字符.数字.简单汉字 取走点赞哦~ 教你如何用4个8乘8点阵拼成一个16乘16点阵 资料链接:点阵16乘16.rar 一.点阵 ...

  6. 单片机8×8点阵显示简单汉字的程序_LED显示屏的显示原理原来是这样,科技实现梦想...

    从图上看,8X8 点阵共需要64 个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一行置高电平,某一列置低电平时,则相应的二极管就亮. 将许多这样的模块组合在一起,就是我们通 ...

  7. STM32F29显示中文汉字

    以下资料为网络搜集,发现很多都为"原创",无法判断作者了. 自己理解后整理,看官自己另行查找详源 . 也可以参考一下这文章 : STM32F429 之 LTDC汉字显示_ 开发效果 ...

  8. 单片机8×8点阵显示简单汉字的程序_干货 | 浅析单片机制作贪吃蛇游戏

    为了让大家更深入地了解底层的原理,在讲解时特意选择了51单片机(而非STM系列),另外16*16点阵由译码器和移位缓存器直接驱动(而非MAX系列芯片),摇杆也利用ADC功能判断方向. 那如何让单片机驱 ...

  9. opencv学习笔记六十八:显示中文汉字

    opencv中putText只能显示英文,如果在某个程序中你想显示汉字,可在该项目上新建一个头文件项putText.h和一个putText.cpp即可. putText.h #ifndef PUTTE ...

最新文章

  1. 自己动手安装ARM交叉编译工具链
  2. 众人评说《我们在微软怎样开发(英文版)》
  3. Android 图片的帧动画
  4. 如何在Django中以GROUP BY查询?
  5. 交换与路由技术课程期末上机测试题目一
  6. Nginx设置本地浏览器缓存
  7. linux ssh应用
  8. mysql 实现表值函数,SQL SERVER 的 CLR表值函数
  9. 《编码规范和测试方法——C/C++版》学习笔记 ·001
  10. Jenkins+Github(Robotframework代码)
  11. BGP路径属性分类与实验(华为设备)
  12. atitit.提高开发效率---mda 革命性的软件开发方法
  13. Android Button设置
  14. 抽象代数 01.06 变换群与置换群
  15. SNOWNLP情感分析报错解决
  16. Android dropbox介绍
  17. Android有效解决加载大图片内存溢出问题及优化虚拟机内存
  18. 高通MTK麒麟 手机平台USB3.0方案对比
  19. fttp项目下载和上传
  20. 升腾c10,华为ct3100安装nextcloud,KodExplorer网盘

热门文章

  1. 对接支付宝支付通道接口
  2. 大华与巴斯勒相机实现单拍的不同
  3. C语言程序设计实训教程-张玉生 张书月 朱苗苗/主编—实验14.4
  4. springboot网上图书商城
  5. 巨杉2017行业认可盘点
  6. OpenLDAP中如何禁用账户,启用账户
  7. 【C#】最全单据打印(打印模板、条形码二维码、字体样式、项目源码)
  8. SWAN之ikev2协议farp配置测试
  9. 递归实现斐波那契数列 一个人赶着鸭子去每个村庄卖,每经过一个 村子卖去所赶鸭子的一半又一只。 这样他经过了 七个村子后还剩 两只鸭子,问问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子?
  10. 中法计算机专业,中法计算机大一新生的专业课课程表