在开发板上显示字符和中文

我们在写lcd驱动程序时,测试时可以在lcd上显示信息,那么他怎么能显示出信息呢,内核里有字符点阵编码,我们在内核里打开字符编码,可以看到很多字符点阵也称为字体。下面我们来自已写一个应用程序在lcd显示屏上显示字母以及显示中文。字符编码 在前面有一个随笔里有写,对于英文字母,用ascii码即可,那么如果我们要显示中文的话应该是要用到汉字库编码即GBK编码表,下面来写一段程序来试验和理解如何在开发板的lcd上显示。

一、首先我们要获得lcd的信息,例:固定信息和可变信息等 这些我们都需要知道可以操作lcd。

二、得到lcd的信息后,把 framebuffer进行内存映射,然后就可以直接操作framebuffer来显示了。

三、然后就可以根据ascii点阵一个一个的把点显示在framebuffer中即可实现了,

四、显示中文不同的是,需要找到一个汉字库文件,然后打开这个文件获得统计信息

五、得到文件统信息后,同样可以把这个字库文件进行内存映射,然后直接操作这个内存进行访问

六、和上面第三步一样,写出显示中文的函数,进行描点即可。

注意:显示的位置坐标要经过计算,要小心算,不然很容易出错和乱码。汉字库的文件解压后要放到根目录下,否则在打开汉字库文件时位置要改为你存放的位置

下面列出列子,实测在板子上可以运行的 ascii 字体头文件在内核里有,复制过来即可 汉字库可以去网上下载

#include <sys/mman.h>
#include "ascii.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <string.h>

static int fd_fb;
static struct fb_var_screeninfo var;    /* 定义一个可变信息结构体 用于保存获得的可变信息 */
static struct fb_fix_screeninfo fix;    /* 定义一个固定信息结构体 用于保存获得的固定信息 */
static int screen_size;                /* 定义一个变量 表示 framebuffer 进行内存映射 */
static unsigned char *fbmem;            /* 定认一个指针变量 用于保存内存映射后的地址 */

static int fd_hzk;
static struct stat hzk_stat;            /* 定义一个结构体用于保存统计信息 */
static unsigned char *hzkmem;            /* 定义一个指针变量 用于保存央存映射的地址 */

static unsigned int line_width;
static unsigned int pixel_whdth;

static unsigned char *str = "谢";

/* 描点函数 根据 x,y,值 确定对应framebuffer的位置
 * 然后依次的在对应的framebuffer上写入颜色值即可
 */
void lcd_put_pixel(int x, int y, unsigned int color)
{
    unsigned char *pen = fbmem + y*line_width + x*pixel_whdth;

    *pen = color;
}

/* 显示ascii字符 那么如何显示呢?
 * 1:根据字符获得字体的点阵
 * 2:根据x,y 的坐标值把点阵的数据放入framebuffer 即可显示出来
 */
void lcd_put_ascii(int x, int y, unsigned char c)
{
    /* 得到字符点阵在数组中的起始位置 */
    unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];
    int i,j;
    unsigned char byte;

    for (i = 0;i < 16;i ++)
    {
        /* 取出一个字节 */
        byte = dots[i];
        for (j = 7;j >= 0;j --)
        {
            if (byte & (1 << j))
            {
                /* 传入参数的值是lcd要显示的起点坐标 这里每个点的坐标每描一个点要移动一次 */
                lcd_put_pixel(x + 7 - j, y + i, 0xffffff);    /* 0xffffff 表示白色 */
            }
            else
            {
                /* 传入参数的值是lcd要显示的起点坐标 这里每个点的坐标每描一个点要移动一次 */
                lcd_put_pixel(x + 7 - j, y + i, 0);        /* 0 表示黑色 */
            }
        }
    }
}

/* 显示中文 如何显示呢?
 * 1: 先得到汉字库的文件 然后可以像打开framebuffe一样打开这个文件
 * 2: 打开后就可以去读了,我们也可以把这个文件当成内存一样用 即映射一下
 * 3: 然后就可以去里面得到字体点阵数据了,接着和显示字符一样描点即可
 * 把文件当成内存去映射先要得到文件大小 可以用 fstat 这个函数来获得大小
 * 如何使用这个函数 可以在服务器上输入 man fstat 得到使用说明
 * 汉字库的使用方法可以去"度娘"去找,基本上就是下面几个注意的地方
 * 1: GBK编码用四个字节表示一个中文 第一个字节表示区码 第二个字节表示位码
 * 2: 为了兼容ascii码 编码从a1 开始 例:"中"字 值是 D6 D0 D6=区码 D0=位码
 * 3: 所以编码的值是 区码+A1 位码+A1
 */
void lcd_put_chinses(int x, int y, unsigned char *str)
{
    unsigned int area   = str[0] - 0xa1;
    unsigned int where  = str[1] - 0xa1;
    unsigned char *dots = hzkmem + (area * 94 + where) * 32;
    unsigned char byte;
    int i,j,k;

    for (i = 0;i < 16;i ++)
    {
        for (j = 0;j < 2;j ++)
        {
            byte = dots[i * 2 + j];
            for (k = 7;k >=0;k --)
            {
                if (byte & (1 << k))
                {
                    /* 传入参数的值是lcd要显示的起点坐标 这里每个点的坐标每描一个点要移动一次 */
                    lcd_put_pixel(x + j * 8 + 7 - k, y + i, 0xffffff);    /* 0xffffff 表示白色 */
                }
                else
                {
                    /* 传入参数的值是lcd要显示的起点坐标 这里每个点的坐标每描一个点要移动一次 */
                    lcd_put_pixel(x + j * 8 + 7 - k, y + i, 0);        /* 0 表示黑色 */
                }
            }
        }
    }

}

int main(int argc, char **agrv)
{

    fd_fb = open("/dev/fb0", O_RDWR);    /* 打开lcd设备 可读可写 */
    if (fd_fb < 0)
    {
        printf("cnt‘t open /dev/fb0 !\n");
        return -1;
    }

    if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))        /* 获得可变信息 */
    {
        /* 正常获得信息的话 ioctl 会返回0 如果返回值不为0时表示出错 */
        printf("can‘t get var! \n");
        return -1;
    }
    if (ioctl(fd_fb,FBIOGET_FSCREENINFO, &fix))        /* 获得固定信息 */
    {
        /* 正常获得信息的话 ioctl 会返回0 如果返回值不为0时表示出错 */
        printf("can‘t get fix! \n ");
        return -1;
    }
    /* 计算 framebuffer 的大小 用于内存映射单位字节 用x分辩率*y分辩率*每个像素得到总大小这时的单位是bit 除以8 转换成字节 */
    screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
    /* 内存映射 mmap 怎么用呢,可以在服务器上输入man mmap 得到说明
     * void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
     * 参数说明:void *addr     设置为0 让内核自动给我们分配地址
     *         :size_t length  映射内存大小
     *         :int prot       属性为可读可写
     *         :int flags      共享 其它进程都可见
     *         :int fd           framebuffer
     *         :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");
        return -1;
    }

    line_width  = var.xres * var.bits_per_pixel / 8;
    pixel_whdth = var.bits_per_pixel / 8;

    /* 打开当前目录下的 HZK16 文件 属性设为只读 */
    fd_hzk = open("HZK16", O_RDONLY);
    if (fd_hzk < 0)
    {
        printf("can‘t open HZK16\n");
        return -1;
    }
    /* 得到这个件的统计信息当然也包含了大小 */
    if (fstat(fd_hzk, &hzk_stat))
    {
        printf("can‘t get hzk_stat! \n ");
        return -1;
    }
    /* 内存映射 mmap 怎么用呢,可以在服务器上输入man mmap 得到说明
     * void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
     * 参数说明:void *addr     设置为0 让内核自动给我们分配地址
     *         :size_t length  映射内存大小
     *         :int prot       属性为可读可写
     *         :int flags      共享 其它进程都可见
     *         :int fd           文件
     *         :off_t offset   偏移值
     */
    hzkmem = (unsigned char *)mmap(NULL, hzk_stat.st_size, PROT_READ, MAP_SHARED, fd_hzk, 0);
    if (hzkmem == (unsigned char *)-1)
    {
        printf("can‘t mmap!\n");
        return -1;
    }    

    /* 这里先清屏 全部显黑色 */
    memset(fbmem, 0, screen_size);

    /* 在lcd上显示ascii字符 即然是显示,肯定要有位置 在那显示先定在中间 */
    lcd_put_ascii(var.xres / 2, var.yres / 2, ‘F‘);
    /* 在lcd上显示中文 即然是显示,肯定要有位置 在那显示 */
    lcd_put_chinses(var.xres / 2 + 8, var.yres / 2, str);

    return 0;
}

原文地址:https://www.cnblogs.com/x2i0e19linux/p/11768759.html

时间: 2024-08-29 18:31:16

在开发板上显示字符和中文的相关文章

在开发板上实现矢量字体显示

对于开发板实现显示矢量字体,同样PC机一样,我需要字体文件,这里选择simsun.ttc(新宋体). 1)初始化库  FT_Init_FreeType( &library ); /* initialize library */ 2)create face object  FT_New_Face( library, argv[1], 0, &face ); 3)设置字体大小 FT_Set_Pixel_Sizes(face, 24, 0); 4)设置坐标 pen.x = 0 * 64; pen

驱动控制开发板上的四个LED小灯

在上一章了解了开发linux驱动程序的步骤,在本章会完成一个真正意义上的linux驱动,该驱动用来控制开发板上的四个LED小灯,通过向驱动发送数据可以控制LED小灯的开关. 首先介绍了LED驱动的实现原理,虽然linux驱动直接与硬件打交道,但并不是linux驱动直接向硬件中的内存写数据,而是与本机的I/O内存进行交互.Linux内核的内存管理模块负责同步I/O内存与硬件中的数据.每一个连接linux的硬件在I/O内存中都会有映射首地址. 其次是编写LED驱动.以下创建一个设备文件,第一步:使用

DM365开发板上uboot操作实践

uboot主要命令: nand命令集    nand flash设备的操作命令集合 nand info    显示flash设备信息. nand device [num] 显示具体flash设备的信息. nand erase offset size    擦除Nand Flash的 off 偏移地址处的size 字节的数据.举例: nand erase 200000 300000 nand read loadaddr offset size    从Nand Flash的offset偏移地址处读

在STM32F746G-DISCO开发板上使用Nabto + FreeRTOS的演示热泵应用

当使用STM32 ARM Cortex-M微控制器时,ST的免费嵌入式软件STM32Cube提供了所有必要的驱动程序和中间件组件,以减少初始的开发工作.在上述提到的中间件组件中,其中一个是非常受欢迎的FreeRTOS实时操作系统,Nabto正在努力建立一个强大的FreeRTOS + Nabto组合的解决方案. 我们最新推出AppMyProduct应用平台可帮助您快速开发远程控制设备的高质量应用程序.本文介绍了在STM32F746G-DISCO开发板上使用Nabto + FreeRTOS的演示热泵

jz2440烧写内核和文件系统,将虚拟机上的文件通过nfs挂载到开发板上。

1.内核和文件系统要匹配好. 2.文件系统的格式,yaffs2,jaffs nand write.yaffs2... ...$(filesize) a.安装nfs 下面介绍具体操作:1.执行命令:sudo apt-get install nfs-kernel-server ;2.执行命令:mkdir /home/share/NFS 建立一个nfs服务的专有的文件夹;3.建立好文件夹后,接着执行命令:sudo vi /etc/exports 配置nfs;4.在文章的最后一行添加:/home/sha

8_陀螺仪MPU6050和PWM控制在STM32F4-Discovery开发板上的实现

很早以前就把圆点博士的程序从STM32F103移植到STM32F4-Discovery(STM32F407),battery,陀螺仪和PWM电机控制的程序都已经测试完毕,运行有一段时间,正常.下面展示几张图片,都是用杜邦线连接起来的,陀螺仪,串口等外设,此外还有nRF24L01,不过nRF24L01的程序读写寄存器可以了,没有尝试过与别的nRF24L01通信.下面一张是正面照片: 下面这张是背面的连接线: 下面这张来个更清晰一些的: 下面这张是圆点博士的上位机软件: 同时我也录制了一些视频,上传

[转载]在iTOP-4412开发板上调试helloworld应用

本文转自迅为论坛:http://www.topeetboard.com 1.安装ADB驱动 在开发板上调试 Android 应用,首先要安装 ADB 驱动. 通过“SDK Manager.exe”来安装.如下图所示.另外需要注意的是,如果要使用 SDK Manager 安装软件,需要将 Eclipse 关闭. 安装完成后,打开文件夹中“USB_fastboot_tool\platform-tools”的命令行 cmd.exe, 如下图所示,输入命令“#adb”,然后回车.这里集成了 adb 命令

x210开发板上启动方式的选择

在X210开发板上由于没有接NandFlash芯片,而是外接了一块iNand芯片,占用的是SD/MMC通道0,所以如果开发板上选择的是SD/MMC启动方式,则第一启动是从iNand中启动,第二启动是从SD/MMC通道2,也就是外部的SD卡启动. 当然也可以通过OM pin来选择USB启动来作为优先启动方式,如果usb启动失败了再去通过OMpin来检测第一启动,然后再检测第二启动.注意在usb启动模式下BL1是不需要在前面加头部的校验等信息的.这也就是为什么使用dnw下载时会下载到0xd002_0

【Android 系统开发】 编译 Android 系统 u-boot 内核 源码 并烧写到 OK-6410A 开发板上

博客地址 : http://blog.csdn.net/shulianghan/article/details/40299813  本篇文章中用到的工具源码下载 : -- ok-6410A 附带的 Android 光盘 下载地址 : http://pan.baidu.com/share/link?shareid=3662728609&uk=2754759285 ; -- 光盘所含内容 : Android 引导 u-boot 源码, Android 内核 源码, Android 系统源码, 交叉编