【正点原子I.MX6U-MINI应用篇】6、嵌入式Linux在LCD屏幕上显示字符

news2024/11/20 12:19:23

一、原始方式: 取模显示字符

LCD显示屏是由width * height个像素点构成的,显示字符,一个非常容易想到的方法便是对字符取模,然后在LCD屏上打点显示字符;如果大家以前学习过单片机,想必接触过一些显示屏,譬如 oled、或者其它一些点阵式的显示屏,其实这些显示屏显示字符的原理都是一样的,如下所示:


我们可以通过一些字符取模软件获取到字符的子模;所谓子模,其实就是一个二维数组,用于表示字符点阵中,哪些小方块应该要填充颜色、哪些小方块不填充颜色。譬如上图字符点阵,这是一个宽度为64(64 个小方块)、高度为 86(86 个小方块)的字符点阵,我们会使用一个二维数组来表示这个字符点阵:

unsigned char arr[86][8];

也就是一个86行8列的unsigned char类型数组,数组存储的其实就是字符的位图数据,字符点阵中的每一个小方块对应一个 bit 位,因为一行一共有64个小方块、也就对应8个字节(8 * 8 = 64);将填充颜色的方块使用1表示、不填充颜色的方块使用0来表示,所以一个小方块刚好可以使用一个bit 位来描述。

这里我是使用的的是PCtoLCD2002.exe这个软件。获取几个字符的子模,然后在我们的 LCD 屏上去显示这些字符。按照下图的方式设置,就可以生成字模了。

1.1 源码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#include <linux/fb.h>

#define FB_DEV      "/dev/fb0"      //LCD设备节点

static int width;                       //LCD宽度
static int height;                      //LCD高度
static unsigned short *screen_base = NULL;//LCD显存基地址

static unsigned char ch_char1[86][8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0x00,0x00,0xE0,0xFF,0xFF,0x01,0x00,0x00},
{0x00,0x00,0xF0,0xFF,0xFF,0x07,0x00,0x00},
{0x00,0x00,0xFC,0xFF,0xFF,0x1F,0x00,0x00},
{0x00,0x00,0xFF,0xFF,0xF7,0x7F,0x00,0x00},
{0x00,0xC0,0xFF,0xFB,0xE7,0xFF,0x01,0x00},
{0x00,0xF8,0xFF,0xF9,0xC7,0xFF,0x0F,0x00},
{0x00,0xFF,0x7F,0xF8,0x87,0xFF,0x7F,0x00},
{0xE0,0xFF,0x3F,0xF8,0x07,0xFE,0xFF,0x07},
{0xFC,0xFF,0x1F,0xF8,0x07,0xFC,0xFF,0x1F},
{0xFC,0xFF,0x07,0xF8,0x07,0xF8,0xFF,0x1F},
{0xF8,0xFF,0x03,0xF8,0x07,0xE0,0xFF,0x0F},
{0xF8,0xFF,0x00,0xF8,0x07,0x80,0xFF,0x0F},
{0xF0,0x3F,0x00,0xF8,0x07,0x00,0xFE,0x07},
{0xF0,0x0F,0x00,0xF8,0x07,0x00,0xF8,0x07},
{0xE0,0x01,0x00,0xF8,0x07,0x00,0xC0,0x03},
{0x60,0x00,0x00,0xF8,0x07,0x00,0x00,0x03},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"果",0*/



};

static unsigned char ch_char2[86][8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0x00,0xF8,0x07,0xC0,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F},
{0x00,0x00,0xE0,0xFF,0xFF,0x01,0x00,0x00},
{0x00,0x00,0xF0,0xFF,0xFF,0x07,0x00,0x00},
{0x00,0x00,0xFC,0xFF,0xFF,0x1F,0x00,0x00},
{0x00,0x00,0xFF,0xFF,0xF7,0x7F,0x00,0x00},
{0x00,0xC0,0xFF,0xFB,0xE7,0xFF,0x01,0x00},
{0x00,0xF8,0xFF,0xF9,0xC7,0xFF,0x0F,0x00},
{0x00,0xFF,0x7F,0xF8,0x87,0xFF,0x7F,0x00},
{0xE0,0xFF,0x3F,0xF8,0x07,0xFE,0xFF,0x07},
{0xFC,0xFF,0x1F,0xF8,0x07,0xFC,0xFF,0x1F},
{0xFC,0xFF,0x07,0xF8,0x07,0xF8,0xFF,0x1F},
{0xF8,0xFF,0x03,0xF8,0x07,0xE0,0xFF,0x0F},
{0xF8,0xFF,0x00,0xF8,0x07,0x80,0xFF,0x0F},
{0xF0,0x3F,0x00,0xF8,0x07,0x00,0xFE,0x07},
{0xF0,0x0F,0x00,0xF8,0x07,0x00,0xF8,0x07},
{0xE0,0x01,0x00,0xF8,0x07,0x00,0xC0,0x03},
{0x60,0x00,0x00,0xF8,0x07,0x00,0x00,0x03},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"果",0*/
};

static unsigned char ch_char3[86][8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x06,0x00},
{0x00,0x0C,0x00,0xF8,0x0F,0xC0,0x07,0x00},
{0x00,0xFC,0x00,0xF8,0x0F,0xF8,0x07,0x00},
{0x00,0xFC,0x07,0xF8,0x0F,0xFC,0x0F,0x00},
{0x00,0xFE,0x07,0xF8,0x0F,0xFC,0x0F,0x00},
{0x00,0xFE,0x07,0xF8,0x0F,0xF8,0x1F,0x00},
{0x00,0xFE,0x07,0xF8,0x0F,0xF8,0x1F,0x00},
{0x00,0xFE,0x03,0xF8,0x0F,0xF0,0x1F,0x00},
{0x00,0xFF,0x03,0xF8,0x0F,0xF0,0x3F,0x00},
{0x00,0xFF,0x03,0xF8,0x0F,0xF0,0x3F,0x00},
{0x00,0xFF,0x01,0xF8,0x0F,0xE0,0x7F,0x00},
{0x80,0xFF,0x01,0xF8,0x0F,0xE0,0x7F,0x00},
{0x80,0xFF,0x01,0xF8,0x0F,0xE0,0x7F,0x00},
{0x80,0xFF,0x01,0xF8,0x0F,0xC0,0xFF,0x00},
{0xC0,0xFF,0x00,0xF8,0x0F,0xC0,0xFF,0x00},
{0xC0,0xFF,0x00,0xF8,0x0F,0xC0,0xFF,0x01},
{0xC0,0xFF,0x00,0xF8,0x0F,0x80,0xFF,0x01},
{0xE0,0x7F,0x00,0xF8,0x0F,0x80,0xFF,0x01},
{0xE0,0x7F,0x00,0xF8,0x0F,0x80,0xFF,0x03},
{0xE0,0x7F,0x00,0xF8,0x0F,0x00,0xFF,0x03},
{0xF0,0x3F,0x00,0xF8,0x0F,0x00,0xFF,0x03},
{0xF0,0x3F,0x00,0xF8,0x0F,0x00,0xFF,0x07},
{0xF0,0x3F,0x00,0xF8,0x0F,0x00,0xFE,0x07},
{0xF8,0x1F,0x00,0xF8,0x0F,0x00,0xFE,0x0F},
{0xF8,0x1F,0x00,0xF8,0x0F,0x00,0xFE,0x0F},
{0xF8,0x1F,0x00,0xF8,0x0F,0x00,0xFC,0x0F},
{0xFC,0x0F,0x00,0xF8,0x0F,0x00,0xFC,0x1F},
{0xFC,0x0F,0x00,0xF8,0x0F,0x00,0xFC,0x1F},
{0xFE,0x0F,0x00,0xF8,0x0F,0x00,0xF8,0x1F},
{0xFE,0x07,0x00,0xF8,0x0F,0x00,0xF8,0x1F},
{0xF0,0x07,0x00,0xF8,0x0F,0x00,0xF8,0x03},
{0xC0,0x07,0x00,0xF8,0x0F,0x00,0xF0,0x00},
{0x00,0x02,0x00,0xF8,0x0F,0x00,0x10,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x00},
{0x00,0x00,0x00,0xFC,0x0F,0x00,0x00,0x00},
{0x00,0x40,0x00,0xFE,0x0F,0x00,0x00,0x00},
{0x00,0x80,0xFF,0xFF,0x0F,0x00,0x00,0x00},
{0x00,0x80,0xFF,0xFF,0x0F,0x00,0x00,0x00},
{0x00,0x80,0xFF,0xFF,0x0F,0x00,0x00,0x00},
{0x00,0x80,0xFF,0xFF,0x07,0x00,0x00,0x00},
{0x00,0x00,0xFF,0xFF,0x07,0x00,0x00,0x00},
{0x00,0x00,0xFF,0xFF,0x03,0x00,0x00,0x00},
{0x00,0x00,0xFF,0xFF,0x01,0x00,0x00,0x00},
{0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00},
{0x00,0x00,0xFF,0x3F,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"小",0*/

};

static unsigned char ch_char4[86][8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0xC0,0x1F,0x00,0x00,0x00,0x00,0x00},
{0x00,0xC0,0x1F,0x00,0x00,0x00,0x00,0x00},
{0x00,0xC0,0x1F,0xFF,0xFF,0xFF,0xFF,0x0F},
{0x00,0xC0,0x1F,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xF8,0xC3,0x1F,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xF8,0xC3,0x1F,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xF8,0xC3,0x1F,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xF8,0xC3,0x1F,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xF8,0xC3,0x1F,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xF8,0xC3,0x1F,0xFF,0xFF,0xFF,0xFF,0x0F},
{0xF8,0xC3,0x1F,0x00,0xC0,0x3F,0x00,0x00},
{0xF8,0xC3,0x1F,0x00,0xC0,0x3F,0x00,0x00},
{0xF8,0xC3,0x1F,0x00,0xC0,0x3F,0x00,0x00},
{0xF8,0xC3,0x1F,0x00,0xC0,0x3F,0x00,0x00},
{0xF8,0xC3,0x1F,0x00,0xC0,0x3F,0x00,0x00},
{0xF8,0xC3,0x1F,0x00,0xC0,0x3F,0x00,0x00},
{0xF8,0xC3,0x1F,0xFE,0xFF,0xFF,0xFF,0x07},
{0xF8,0xC3,0x1F,0xFE,0xFF,0xFF,0xFF,0x07},
{0xF8,0xC3,0x1F,0xFE,0xFF,0xFF,0xFF,0x07},
{0xF8,0xC3,0x1F,0xFE,0xFF,0xFF,0xFF,0x07},
{0xF8,0xC3,0x1F,0xFE,0xFF,0xFF,0xFF,0x07},
{0xF8,0xC3,0x1F,0xFE,0xFF,0xFF,0xFF,0x07},
{0xF8,0xC3,0x1F,0xFE,0xFF,0xFF,0xFF,0x07},
{0xF8,0xC3,0x1F,0xFE,0xFF,0xFF,0xFF,0x07},
{0xF8,0xC3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xC3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xC3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xC3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xC3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xC3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xC3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xC3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xC3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xC3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xE3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xE3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xE3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xE3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xE3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xE3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xE3,0x1F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xE3,0x0F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xF3,0x0F,0xFE,0xC1,0x3F,0xF8,0x07},
{0xF8,0xF3,0x0F,0xFE,0xC1,0x3F,0xFC,0x07},
{0xF8,0xF3,0x0F,0xFE,0xC1,0xFF,0xFF,0x07},
{0x00,0xF8,0x0F,0xFE,0xC1,0xFF,0xFF,0x07},
{0x00,0xF8,0x0F,0xFE,0xC1,0xFF,0xFF,0x03},
{0x00,0xF8,0x07,0xFE,0xC1,0xBF,0xFF,0x03},
{0x00,0xFC,0x07,0xFE,0xC1,0xBF,0xFF,0x03},
{0x00,0xFC,0x07,0xFE,0xC1,0xBF,0xFF,0x01},
{0x00,0xFE,0x03,0xFE,0xC1,0xBF,0xFF,0x00},
{0x00,0xFF,0x03,0xFE,0xC1,0x3F,0x3F,0x00},
{0x00,0xFF,0x03,0x00,0xC0,0x3F,0x00,0x00},
{0x80,0xFF,0x01,0x00,0xC0,0x3F,0x00,0x00},
{0xC0,0xFF,0x01,0x00,0xC0,0x3F,0x00,0x00},
{0xE0,0xFF,0x00,0x00,0xC0,0x3F,0x00,0x00},
{0xE0,0xFF,0x00,0x00,0xC0,0x3F,0x00,0x00},
{0xC0,0x7F,0x00,0x00,0xC0,0x3F,0x00,0x00},
{0x00,0x7F,0x00,0x00,0xC0,0x3F,0x00,0x00},
{0x00,0x3E,0x00,0x00,0xC0,0x3F,0x00,0x00},
{0x00,0x18,0x00,0x00,0xC0,0x3F,0x00,0x00},
{0x00,0x10,0x00,0x00,0xC0,0x3F,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"师",0*/
};

static unsigned char ch_char5[86][8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x08,0x00,0x00,0x06,0x00,0x00},
{0x00,0x00,0x1E,0x00,0x00,0x1E,0x00,0x00},
{0x00,0x80,0x3F,0x00,0x00,0xFF,0x00,0x00},
{0x00,0xE0,0x7F,0x00,0x80,0xFF,0x03,0x00},
{0x00,0xE0,0x7F,0x00,0x80,0xFF,0x01,0x00},
{0x00,0xC0,0xFF,0x00,0xC0,0xFF,0x00,0x00},
{0x00,0x80,0xFF,0x01,0xE0,0x7F,0x00,0x00},
{0x00,0x00,0xFF,0x01,0xE0,0x3F,0x00,0x00},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0x00,0x00,0x00,0xF8,0x07,0x00,0xFF,0x01},
{0x00,0x00,0x00,0xF8,0x07,0x00,0xFF,0x01},
{0x00,0x00,0x00,0xF8,0x07,0x00,0xFF,0x01},
{0x00,0x00,0x00,0xF8,0x07,0x00,0xFF,0x01},
{0x00,0x00,0x00,0xF8,0x07,0x00,0xFF,0x01},
{0x00,0x00,0x00,0xF8,0x07,0x00,0xFF,0x01},
{0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01},
{0xE0,0x1F,0x00,0xF8,0x07,0x00,0x00,0x00},
{0xE0,0x1F,0x00,0xF8,0x07,0x00,0x00,0x00},
{0xE0,0x1F,0x00,0xF8,0x07,0x00,0x00,0x00},
{0xE0,0x1F,0x00,0xF8,0x07,0x00,0x00,0x00},
{0xF0,0x1F,0x00,0xF8,0x07,0x00,0x00,0x00},
{0xF0,0x1F,0x00,0xF8,0x07,0x00,0x00,0x00},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07},
{0x00,0x00,0xFC,0xFF,0x07,0x00,0xF8,0x07},
{0x00,0x00,0xFC,0xFF,0x07,0x00,0xF8,0x07},
{0x00,0x00,0xFE,0xFB,0x07,0x00,0xF8,0x07},
{0x00,0x00,0xFF,0xFB,0x07,0x00,0xF8,0x07},
{0x00,0xC0,0xFF,0xF9,0x07,0x00,0xF8,0x07},
{0x00,0xE0,0xFF,0xF8,0x07,0x00,0xFC,0x07},
{0x00,0xF0,0xFF,0xF8,0x07,0x00,0xFC,0x07},
{0x00,0xF8,0x7F,0xF8,0x07,0x00,0xFF,0x07},
{0x00,0xFE,0x3F,0xF8,0xC7,0xFF,0xFF,0x07},
{0x80,0xFF,0x1F,0xF8,0xC7,0xFF,0xFF,0x03},
{0xC0,0xFF,0x0F,0xF8,0xC7,0xFF,0xFF,0x03},
{0xF0,0xFF,0x07,0xF8,0x87,0xFF,0xFF,0x01},
{0xFC,0xFF,0x03,0xF8,0x87,0xFF,0xFF,0x01},
{0xFF,0xFF,0x01,0xF8,0x87,0xFF,0xFF,0x00},
{0xFE,0x7F,0x00,0xF8,0x87,0xFF,0x3F,0x00},
{0xFC,0x3F,0x00,0xF8,0x87,0xFF,0x0F,0x00},
{0xFC,0x1F,0x00,0xF8,0x07,0x00,0x00,0x00},
{0xF8,0x07,0x00,0xF8,0x07,0x00,0x00,0x00},
{0xF0,0x03,0x00,0xF8,0x07,0x00,0x00,0x00},
{0xF0,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x20,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"弟",0*/
};



#define argb8888_to_rgb565(color)   ({ \
            unsigned int temp = (color); \
            ((temp & 0xF80000UL) >> 8) | \
            ((temp & 0xFC00UL) >> 5) | \
            ((temp & 0xF8UL) >> 3); \
            })

/********************************************************************
 * 函数名称: lcd_draw_character
 * 功能描述: 在LCD屏指定位置处(x, y)画字符, 参数color指定字符的颜色
              指针ch指向字符对应的子模数组、参数w、h分别表示字符的宽度和高度
 * 输入参数: color
 * 返 回 值: 无
 ********************************************************************/
static void lcd_draw_character(unsigned int x, unsigned int y,
            const unsigned char *ch, unsigned int w,
            unsigned int h, unsigned int color)
{
    unsigned short rgb565_color = argb8888_to_rgb565(color);//得到RGB565颜色值
    unsigned long temp;
    unsigned int end_x, end_y;
    int j;
    int columns;

    /**
    计算出二维数组有多少列
    参数w表示的是字符的宽度,1个宽度表示的是1个bit位
    并不是一个字节,这里要注意,如果宽度不是byte单位的整数倍
    通常会补零
    **/
    columns = w / 8;    //1byte=8bit
    if (0 != w % 8) columns++;

    /* 对参数进行限定 */
    if (w < 1 || h < 1) return;
    if (x >= width || y >= height) return;

    /* 计算出结束坐标位置 */
    end_x = x + w - 1;
    end_y = y + h - 1;

    /* 对结束坐标位置进行限定 */
    if (end_x >= width)
        end_x = width - 1;
    if (end_y >= height)
        end_y = height - 1;

    /* 计算有效宽度 */
    h = end_y - y + 1;
    w = end_x - x + 1;

    /* 打点 */
    temp = y * width + x; //定位到起点
    for (y = 0; y < h; y++, temp += width) {

        for (x = 0, j = 0; x < w; ) {

            if (*(ch + y * columns + j) & (0x1 << (x % 8)))
                screen_base[temp + x] = rgb565_color;
            x++;
            if (0 == x % 8) j++;
        }
    }
}

int main(void)
{
    struct fb_var_screeninfo fb_var = {0};
    struct fb_fix_screeninfo fb_fix = {0};
    unsigned long screen_size;
    int fd;

    /* 打开framebuffer设备 */
    fd = open(FB_DEV, O_RDWR);
    if (0 > fd) {
        fprintf(stderr, "open error: %s: %s\n", FB_DEV, strerror(errno));
        exit(EXIT_FAILURE);
    }

    /* 获取framebuffer设备信息 */
    ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
    ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);

    screen_size = fb_fix.line_length * fb_var.yres;
    width = fb_var.xres;
    height = fb_var.yres;

    /* 内存映射 */
    screen_base = mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (MAP_FAILED == (void *)screen_base) {
        perror("mmap error");
        close(fd);
        exit(EXIT_FAILURE);
    }

    /* LCD背景刷白 */
    memset(screen_base, 0xFF, screen_size);

    /* 显示字符 */
    int x = width * 0.5 - 128;
    int y = height * 0.5 - 43;
    lcd_draw_character(x,       y, (unsigned char *)ch_char1, 64, 86, 0xFF00FF);
    lcd_draw_character(x + 64,  y, (unsigned char *)ch_char2, 64, 86, 0xFF00FF);
    lcd_draw_character(x + 128, y, (unsigned char *)ch_char3, 64, 86, 0xFF00FF);
    lcd_draw_character(x + 192, y, (unsigned char *)ch_char4, 64, 86, 0xFF00FF);
    lcd_draw_character(x + 256, y, (unsigned char *)ch_char5, 64, 86, 0xFF00FF);

    /* 退出程序 */
    munmap(screen_base, screen_size);
    close(fd);
    return 0;
}

程序中定义了5个二维数组ch_char1、ch_char2、ch_char3、ch_char4、ch_char5,这5个二维数组便是5个中文字符果果小师弟的子模,字符宽度为64、高度为86。在取模的时候,选择从左到右、从上到下这种方式进行取模,上述示例代码便是按照这种方式进行解析的。

1.2 编译程序

我们要想给ARM板编译出程序,需要使用交叉编译工具链,交叉编译的工具链我们已经安装过了,详细请看【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.x.pdf 的第4.3小节。我是用的是arm-linux-gnueabihf交叉编译工具链。使用arm-linux-gnueabihf-gcc -v可以查看交叉编译工具链的版本号。

然后就可以使用下面命令编译出可以在ARM板子上运行的可执行文件了。

arm-linux-gnueabihf-gcc -o show_char show_char.c
  • 1、arm表示这是编译arm架构代码的编译器。
  • 2、linux表示运行在linux环境下。
  • 3、gnueabihf表示嵌入式二进制接口。
  • 4、gcc表示是gcc工具。

这样编译出来的 led程序才可以在ARM板子上运行。执行file show_char命令就可以看出hello是32位LSB的ELF格式文件,目标机架构为ARM,说明这个交叉编译正常,可执行文件可以在ARM板上执行。

1.3 上传程序到开发板执行

开发板启动后通过nfs挂载Ubuntu目录的方式,将相应的文件拷贝到开发板上。简单来说,就是通过NFS在开发板上通过网络直接访问ubuntu虚拟机上的文件,并且就相当于自己本地的文件一样。

开发板想访问/home/zhiguoxin/myproject/alientek_app_development_source这个目录中的文件,就要把/home/zhiguoxin/myproject/alientek_app_development_source挂载到开发板的mnt目录,这样就可以通过nfs来访问/home/zhiguoxin/myproject/alientek_app_development_source了。

因为我的代码都放在/home/zhiguoxin/myproject/alientek_app_development_source这个目录下,所以我们将这个目录作为NFS共享文件夹。设置方法参考移植SQLite3、OpenCV到RV1126开发板上开发人脸识别项目第一章。

Ubuntu IP为192.168.10.100,然后一般都是挂载在开发板的mnt目录下,这个目录是专门用来给我们作为临时挂载的目录。

文件系统目录简介

然后使用MobaXterm软件通过SSH访问开发板。

ubuntu ip:192.168.10.100
windows ip:192.168.10.200
开发板ip:192.168.10.50

在开发板上执行以下命令:

mount -t nfs -o nolock,vers=3 192.168.10.100:/home/zhiguoxin/myproject/alientek_app_development_source /mnt

就将开饭的mnt目录挂载在ubuntu的/home/zhiguoxin/myproject/alientek_app_development_source目录下了。这样我们就可以在Ubuntu下修改文件,然后可以直接在开发板上执行可执行文件了。当然我这里的/home/zhiguoxin/myproject/windows之间是一个共享目录,我也可以直接在windows上面修改文件,然后ubuntu和开发板直接进行文件同步了。

然后编译,可以编译成功。

./show_char

此时开发板 LCD 屏上会显示果果小师弟五个中文字符,如下图所示


使用这种方式还是非常简单地,自己取模、自己写函数打点显示,但是很 low!好歹咋们玩的也是操作系统,实际的应用项目一般肯定不会这么干,除非你的程序就是显示那么几个固定的字符。那既然如此,为什么还要给大家介绍这种方式呢?一来是让大家理解字符显示的原理;二来,一些实际的应用项目中可能确实就是这么做的,不同的项目它的需求不同,不能一概而论!

操作系统中通常都会有很多的字体文件,譬如 Windows 系统C:\Windows\Fonts目录下就有很多的字体文件,如下所示:


字体文件的格式也有很多种,譬如otf、ttf、ttc等,Linux系统中,字体文件通常会放在/usr/share/fonts目录下,有了字体文件之后,我们就不需要再对字符进行取模了,它们已经编码进了字体文件中,我们只需要解析字体文件、访问字体文件,从字体文件中读取出字符的位图数据即可!

当然,这些复杂的解析过程并不需要我们自己去实现,有很多开源的字体引擎可以帮助我们来处理这些复杂的解析过程,譬如freetype库。

二、FreeType简介

FreeType一个完全免费(开源)的软件字体引擎库,设计小巧、高效、高度可定制且可移植,它提供了统一的接口来访问多种不同格式的字体文件。它提供了一个简单、易于使用且统一的接口来访问字体文件的内容,从而大大简化了这些任务。

请注意,FreeType也称为FreeType 2,以区别于旧的、已弃用的FreeType 1库,Freetype 1库已经不再维护和支持了。

2.1 FreeType移植

开发板出厂系统已经移植好了这些库,但是版本稍微太低了,作为学习者,我们应该要学会自己动手移植,这个是很重要的工作;我们很多的编程工作都是基于别人写好的库、调用库函数来实现应用程序的功能,因为 Linux 软件生态做得非常好,有很多免费、开源的库是可以使用的,不用自己去捣鼓这些东西;所以作为一个嵌入式Linux 软件开发人员,学会移植就显得很重要

2.2 下载FreeType源码

开发板出厂系统中,FreeType 的版本为 2.6,这个版本稍微有点低,我们选择移植 2.8 版本的 FreeType。进入到https://download.savannah.gnu.org/releases/freetype/链接地址,如下所示:

 FreeType 源码下载地址
往下翻找到2.8版本,选择freetype-2.8.tar.gz压缩文件.

2.3 交叉编译FreeType源码

将下载好的freetype-2.8.tar.gz压缩文件拷贝到 Ubuntu共享文件夹目录下,如下所示:


/home/zhiguoxin/linux/tool目录下创建一个名为freetype的目录,把它作为FreeType的安装目录:


回到共享文件夹下,执行命令将freetype-2.8.tar.gz解压开来:

tar -xzf freetype-2.8.tar.gz

将 freetype-2.8.tar.gz 压缩文件解压解压成功之后便会得到FreeType的源码目录freetype-2.8

进入到freetype-2.8目录,老规矩,同样是三部曲:配置、编译、安装。首先对交叉编译工具的环境进行初始化,前面章节内容已经提过很多次了,使用交叉编译器之前,必须要对其环境进行初始化(如果当前终端已经初始化过了,则无需再次进行初始化)。

FreeType库基于模块化设计,意味着我们可以对其进行裁剪,将不需要的功能模块从配置中移除,减小库文件的体积;除此之外,FreeType还支持很多配置选项,如果大家想要对FreeType做一些自定义配置或者对其进行裁剪,可以参考FreeType源码目录下docs/CUSTOMIZE文档,该文件对此有比较详细的说明,建议大家看一看,如果有需求的话。docs目录下还有其它很多的说明文档,也都可以读一读。

这里我们简单地配置一下,打开include/freetype/config/ftoption.h文件,如下所示:

vim include/freetype/config/ftoption.h

该文件定义了很多的配置宏,我们可以选择使能或禁用这些配置选项,具体配置哪些功能,大家自己去研究,每一个配置宏都有详细地解释说明。这里我们打开以下两个配置宏:

#define FT_CONFIG_OPTION_SYSTEM_ZLIB
#define FT_CONFIG_OPTION_USE_PNG

大家找到这两个宏,默认情况下,这两个都被注释掉了,所以是没有使能的;把这两个宏的注释去掉,使能这两个配置宏。

第一个配置宏表示使用系统安装的zlib库,因为 FreeType支持Gzip压缩文件,会使用到zlib库,zlib之前我们移植好了;第二个配置宏表示支持PNG bitmap位图,因为FreeType可以加载PNG格式的彩色位图字形,需要依赖于libpng 库,这个库前面我们也是移植好了

配置好之后,保存、退出ftoption.h文件,接着执行如下命令对FreeType工程源码进行配置:

./configure --prefix=/home/zhiguoxin/linux/tool/freetype/ --host=arm-poky-linux-gnueabi --with-zlib=yes --with-bzip2=no --with-png=yes  --with-harfbuzz=no  ZLIB_CFLAGS="-I/home/zhiguoxin/linux/tool/zlib/include  -L/home/zhiguoxin/linux/tool/zlib/lib" ZLIB_LIBS=-lz LIBPNG_CFLAGS="-I/home/zhiguoxin/linux/tool/png/include -L/home/zhiguoxin/linux/tool/png/lib" LIBPNG_LIBS=-lpng

这个配置命令很长,简单地提一下,具体的细节大家可以执行./configure --help查看配置帮助信息。

  • –prefix 选项指定FreeType库的安装目录;
  • –host 选项设置为交叉编译器名称的前缀;
  • –with-zlib=yes 表示使用 zlib;
  • –with-bzip2=no 表示不使用bzip2库;
  • –with-png=yes 表示使用libpng库;
  • –with-harfbuzz=no 表示不使用harfbuzz库。
  • ZLIB_CFLAGS选项用于指定zlib的头文件路径和库文件路径,根据实际安装路径填写;
  • ZLIB_LIBS 选项指定链接的zlib库的名称;
  • LIBPNG_CFLAGS 选项用于指定libpng的头文件路径和库文件路径,根据实际安装路径填写;
  • LIBPNG_LIBS 选项用于指定链接的libpng库的名称。

配置完成之后接着执行make编译,编译完成之后执行make install安装即可!

make
make install

2.4 安装目录下的文件

进入到 FreeType 安装目录下,如下所示:


如果要使用FreeType库,我们需要在应用程序源码中包含include/freetype2目录下的ft2build.h头文件,除此之外,还需要包含另一个头文件 FT_FREETYPE_H,这是一个用宏定义的头文件,其实就是include/freetype2/freetype/freetype.h 头文件。
所以,在我们的应用程序一般是这样写:

#include <ft2build.h>
#include FT_FREETYPE_H

2.5 移植到开发板

接下来将编译得到的动态链接库文件拷贝到开发板 Linux 系统/usr/lib 目录,在拷贝之前,需将/usr/lib 目录下原有的 FreeType 库文件删除掉,执行下面这条命令:

rm -rf /usr/lib/libfreetype.*

删除之后,再将编译得到的库文件拷贝到开发板/usr/lib目录,拷贝lib目录下的库文件时,需要注意符号链接的问题,不能破坏原有的符号链接;可以将lib目录下的所有文件打包成压缩包的形式,譬如进入到lib目录,执行命令:

tar -czf lib.tar.gz ./ libfreetype*

拷贝过去之后,开发板/usr/lib目录下就应该存在这些库文件,如下所示:

scp lib.tar.gz root@192.168.10.50:/home/root/

这里如果使用scp命令不成功,可以用其他的方法拷贝。

然后lib.tar.gz就拷贝到开发板了,然后使用下面命令将其解压至/usr/lib 目录下

tar -xmzf lib.tar.gz -C /usr/lib

然后使用下面命令查看是是否成功拷贝至/usr/lib目录。

ls -l /usr/lib/libfreetype.*

开发板/usr/lib 目录下的 FreeType库文件

2.6 应用编程


#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <math.h>       //数学库函数头文件

#include <wchar.h>
#include <ft2build.h>
#include FT_FREETYPE_H

#define FB_DEV      "/dev/fb0"      //LCD设备节点

#define argb8888_to_rgb565(color)   ({ \
            unsigned int temp = (color); \
            ((temp & 0xF80000UL) >> 8) | \
            ((temp & 0xFC00UL) >> 5) | \
            ((temp & 0xF8UL) >> 3); \
            })

static unsigned int width;                       //LCD宽度
static unsigned int height;                      //LCD高度
static unsigned short *screen_base = NULL;//LCD显存基地址 RGB565
static unsigned long screen_size;
static int fd = -1;

static FT_Library library;
static FT_Face face;

static int fb_dev_init(void)
{
    struct fb_var_screeninfo fb_var = {0};
    struct fb_fix_screeninfo fb_fix = {0};

    /* 打开framebuffer设备 */
    fd = open(FB_DEV, O_RDWR);
    if (0 > fd) {
        fprintf(stderr, "open error: %s: %s\n", FB_DEV, strerror(errno));
        return -1;
    }

    /* 获取framebuffer设备信息 */
    ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
    ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);

    screen_size = fb_fix.line_length * fb_var.yres;
    width = fb_var.xres;
    height = fb_var.yres;

    /* 内存映射 */
    screen_base = mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (MAP_FAILED == (void *)screen_base) {
        perror("mmap error");
        close(fd);
        return -1;
    }

    /* LCD背景刷成黑色 */
    memset(screen_base, 0xFF, screen_size);
    return 0;
}

static int freetype_init(const char *font, int angle)
{
    FT_Error error;
    FT_Vector pen;
    FT_Matrix matrix;
    float rad;      //旋转角度

    /* FreeType初始化 */
    FT_Init_FreeType(&library);

    /* 加载face对象 */
    error = FT_New_Face(library, font, 0, &face);
    if (error) {
        fprintf(stderr, "FT_New_Face error: %d\n", error);
        exit(EXIT_FAILURE);
    }

    /* 原点坐标 */
    pen.x = 0 * 64;
    pen.y = 0 * 64;     //原点设置为(0, 0)

    /* 2x2矩阵初始化 */
    rad = (1.0 * angle / 180) * M_PI;   //(角度转换为弧度)M_PI是圆周率
#if 0       //非水平方向
    matrix.xx = (FT_Fixed)( cos(rad) * 0x10000L);
    matrix.xy = (FT_Fixed)(-sin(rad) * 0x10000L);
    matrix.yx = (FT_Fixed)( sin(rad) * 0x10000L);
    matrix.yy = (FT_Fixed)( cos(rad) * 0x10000L);
#endif

#if 1       //斜体  水平方向显示的
    matrix.xx = (FT_Fixed)( cos(rad) * 0x10000L);
    matrix.xy = (FT_Fixed)( sin(rad) * 0x10000L);
    matrix.yx = (FT_Fixed)( 0 * 0x10000L);
    matrix.yy = (FT_Fixed)( 1 * 0x10000L);
#endif

    /* 设置 */
    FT_Set_Transform(face, &matrix, &pen);
    FT_Set_Pixel_Sizes(face, 50, 0);    //设置字体大小

    return 0;
}

static void lcd_draw_character(int x, int y,
            const wchar_t *str, unsigned int color)
{
    unsigned short rgb565_color = argb8888_to_rgb565(color);//得到RGB565颜色值
    FT_GlyphSlot slot = face->glyph;
    size_t len = wcslen(str);   //计算字符的个数
    long int temp;
    int n;
    int i, j, p, q;
    int max_x, max_y, start_y, start_x;

    // 循环加载各个字符
    for (n = 0; n < len; n++) {

        // 加载字形、转换得到位图数据
        if (FT_Load_Char(face, str[n], FT_LOAD_RENDER))
            continue;

        start_y = y - slot->bitmap_top; //计算字形轮廓上边y坐标起点位置 注意是减去bitmap_top
        if (0 > start_y) {//如果为负数 如何处理??
            q = -start_y;
            temp = 0;
            j = 0;
        }
        else {      // 正数又该如何处理??
            q = 0;
            temp = width * start_y;
            j = start_y;
        }

        max_y = start_y + slot->bitmap.rows;//计算字形轮廓下边y坐标结束位置
        if (max_y > (int)height)
            max_y = height;

        for (; j < max_y; j++, q++, temp += width) {

            start_x = x + slot->bitmap_left;  //起点位置要加上左边空余部分长度
            if (0 > start_x) {
                p = -start_x;
                i = 0;
            }
            else {
                p = 0;
                i = start_x;
            }

            max_x = start_x + slot->bitmap.width;
            if (max_x > (int)width)
                max_x = width;

            for (; i < max_x; i++, p++) {

                // 如果数据不为0,则表示需要填充颜色
                if (slot->bitmap.buffer[q * slot->bitmap.width + p])
                    screen_base[temp + i] = rgb565_color;
            }
        }

        //调整到下一个字形的原点
        x += slot->advance.x / 64;  //26.6固定浮点格式
        y -= slot->advance.y / 64;
    }
}

int main(int argc, char *argv[])
{
    

    /* LCD初始化 */
    if (fb_dev_init())
        exit(EXIT_FAILURE);

    /* freetype初始化 */
    if (freetype_init(argv[1], atoi(argv[2])))
        exit(EXIT_FAILURE);

    /* 在LCD上显示中文 */
    int y = height * 0.25;
    lcd_draw_character(50, 100, L"欢迎各位帅哥美女进小弟的博客", 0x000000);
    lcd_draw_character(50, y+100, L"祝大哥别人不发你还发,永远都是企业家", 0x9900FF);
    lcd_draw_character(50, 2*y+100, L"祝美女人见人爱,花见花开", 0xFF0099);
    lcd_draw_character(50, 3*y+100, L"微信公众号:果果小师弟", 0x9932CC);

    /* 退出程序 */
    FT_Done_Face(face);
    FT_Done_FreeType(library);
    munmap(screen_base, screen_size);
    close(fd);
    exit(EXIT_SUCCESS);
}

编译方法

source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi # 设置环境变量
${CC} -o freetype_test freetype_test.c -I/home/zhiguoxin/linux/tool/freetype/include/freetype2 -L/home/zhiguoxin/linux/tool/freetype/lib -lfreetype -L/home/zhiguoxin/linux/tool/zlib/lib -lz -L/home/zhiguxoin/linux/tool/png/lib -lpng -lm

编译完成就可以在板子上执行可执行文件了。

2.7 上传程序到开发板执行

开发板启动后通过nfs挂载Ubuntu目录的方式,将相应的文件拷贝到开发板上。简单来说,就是通过NFS在开发板上通过网络直接访问ubuntu虚拟机上的文件,并且就相当于自己本地的文件一样。

开发板想访问/home/zhiguoxin/myproject/alientek_app_development_source这个目录中的文件,就要把/home/zhiguoxin/myproject/alientek_app_development_source挂载到开发板的mnt目录,这样就可以通过nfs来访问/home/zhiguoxin/myproject/alientek_app_development_source了。

因为我的代码都放在/home/zhiguoxin/myproject/alientek_app_development_source这个目录下,所以我们将这个目录作为NFS共享文件夹。设置方法参考移植SQLite3、OpenCV到RV1126开发板上开发人脸识别项目第一章。

Ubuntu IP为192.168.10.100,然后一般都是挂载在开发板的mnt目录下,这个目录是专门用来给我们作为临时挂载的目录。

文件系统目录简介

然后使用MobaXterm软件通过SSH访问开发板。

ubuntu ip:192.168.10.100
windows ip:192.168.10.200
开发板ip:192.168.10.50

在开发板上执行以下命令:

mount -t nfs -o nolock,vers=3 192.168.10.100:/home/zhiguoxin/myproject/alientek_app_development_source /mnt

就将开饭的mnt目录挂载在ubuntu的/home/zhiguoxin/myproject/alientek_app_development_source目录下了。这样我们就可以在Ubuntu下修改文件,然后可以直接在开发板上执行可执行文件了。当然我这里的/home/zhiguoxin/myproject/windows之间是一个共享目录,我也可以直接在windows上面修改文件,然后ubuntu和开发板直接进行文件同步了。


然后编译,可以编译成功。

./freetype_test ./simsun.ttc 0


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三次、五次多项式插值(附代码)

文章目录一、三次多项式插值二、五次多项式插值三、matlab代码三次、五次多项式插值在工程实践中很常见。求解多项式的系数最直接的方法是根据端点处的约束条件&#xff0c;列出线性方程组&#xff0c;再写成矩阵方程AXB&#xff0c;然后用通用的方法(如高斯消元法、LU分解等)解…

二叉树广度优先搜索、深度优先搜索(前序、中序、后序)遍历,动图详解-Java/Kotlin双版本代码

自古逢秋悲寂寥&#xff0c;我言秋日胜春朝 二叉树结构说明 本博客使用树节点结构&#xff0c;如下所示&#xff1a; Kotlin 版本 class TreeNode(var value: String, var leftNode: TreeNode? null, var rightNode: TreeNode? null)Java 版本 class TreeNode(){public…

经典排序之插入排序

目录 直接插入排序&#xff1a; 基本思路 图解过程 代码 复杂度分析 希尔排序 基本思想 图解过程 代码 复杂度分析 总结 参赛话题&#xff1a;学习笔记 直接插入排序&#xff1a; 基本思路 直接插入排序的工作方式像许多人排序一手扑克牌。开始时&#xff0c;我们的左手…

【Netty 从成神到升仙系列 大结局】全网一图流死磕解析 Netty 源码

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小黄&#xff0c;独角兽企业的Java开发工程师&#xff0c;Java领域新星创作者。&#x1f4dd;个人公众号&#xff1a;爱敲代码的小黄&#x1f4d5;系列专栏&#xff1a;Java设计模式、数据结构和算法&#x…

第八篇 python 面向对象编程

11 面向对象编程 面向对象编程——Object Oriented Programming&#xff0c;简称OOP&#xff0c;是一种程序设计思想。OOP把对象作为程序的基本单元&#xff0c;一个对象包含了数据和操作数据的函数。 面向过程的程序设计把计算机程序视为一系列的命令集合&#xff0c;即一组…

Python攻防-APK批量化Pull与自动化反编译

文章目录前言Pull APK根据包名列表根据手机路径逆向APK自动化反编译findstr检索…总结前言 日常工作过程中&#xff0c;经常会遇到发现新的攻击模式的情况下&#xff0c;需要全量排查手机上所有 APP 的代码是否存在该类代码缺陷。对于复杂的攻击模式而言&#xff0c;往往需要动…

【MyBatis框架】动态SQL

MyBatis之动态SQL 目录MyBatis之动态SQL1. < if > 元素2. < where >3. < choose >,< when >,< otherwise >元素4. < trim >元素5. < set >元素6. < foreach >元素6.1 添加批量数据6.2 批量删除数据7. < SQL >元素8. 小结…

LVS负载均衡群集

企业群集应用 1. 群集的含义 1.1Cluster&#xff0c;群集&#xff0c;集群 2.1由多台主机构成&#xff0c;但对外&#xff0c;只表现为一个整体&#xff0c;只提供一个访问入口&#xff08;域名或ip地址&#xff09;&#xff0c; 相当于一台大型计算机 2.问题出现 互联网…

Sentinel的学习

1、Sentinel控制台的下载 下载地址&#xff1a;https://github.com/alibaba/Sentinel/releases/tag/1.8.3 2、Sentinel控制台的启动 java -jar sentinel-dashboard-1.8.3.jar3、访问 浏览器输入&#xff1a;localhost:8080 账号密码&#xff1a; sentinel/sentinel 4.sprin…

SARScape中用sentinel-1数据做SBAS-InSAR完整流程(1/2)

SARScape中用sentinel-1数据做SBAS-InSAR完整流程1 SABA-InSAR原理简述2 数据采集和预设2.1 SAR数据采集2.2 DEM数据下载与放置2.3 精密轨道数据下载与放置2.4 制作研究区范围矢量2.5 SARscape Preferences预设3 SAR数据预处理3.1 导入数据3.2 optional files设置3.3 参数设置4…

【Git】Git使用的三个场景总结 | 远程仓库到本地 | 本地获取git仓库 | 远程仓库与本地相连接

&#x1f4ad;&#x1f4ad; ✨&#xff1a; git使用的三个场景总结 | 远程仓库到本地 | 本地获取git仓库 | 远程仓库与本地相连接   &#x1f49f;&#xff1a;东非不开森的主页   &#x1f49c;&#xff1a;学习的过程就是不断接触错误&#xff0c;不断提升自己&#xff0c…

Linux 卸载zabbix图文教程

Linux 卸载zabbix图文教程前言1.停止zabbix服务2.卸载zabbix服务2.1查找zabbix所有被安装的rpm包2.2卸载zabbix服务2.3删除所有与zabbix相关的文件&#xff08;配置项等&#xff09;3.卸载数据库3.1查找mariadb所有被安装的rpm包&#xff0c;并删除3.2删除mysql相关配置文件4.卸…

Source Insight4.0中文注释乱码解决方案

一、Source Insight软件介绍 Source Insight是一个面向项目的编程编辑器、代码浏览器和分析器&#xff0c;可帮助您在工作和计划​​时分析代码&#xff0c;具有针对 C/C、C#、Java、Objective-C 等的内置动态分析&#xff0c;深受众多嵌入式软件开发者的喜爱。 二、中文乱码…

复旦-华盛顿大学EMBA 二十年20人丨徐欣:从外企转战民企的变身

复旦大学-华盛顿大学EMBA20周年校友系列访谈。      2008年堪称转折之年&#xff0c;中国举行北京奥运会向全世界展示“和而不同”的理念&#xff0c;入世7年让中国在贸易、金融领域与全球市场紧密相连&#xff0c;一大批最优秀的中国民营企业也加速踏上全球化之路。    …

Web APIs:PC 端网页特效--动画函数封装

动画原理 核心原理&#xff1a;通过定时器 setInterval() 不断移动盒子位置 实现步骤&#xff1a; 1. 获得盒子当前位置 2. 让盒子在当前位置加上1个移动距离 3. 利用定时器不断重复这个操作 4. 加一个结束定时器的条件 5. 注意此元素需要添加定位&#xff0c;才能使用e…

【C语言】三子棋小游戏

&#x1f680; 作者简介&#xff1a;一名在后端领域学习&#xff0c;并渴望能够学有所成的追梦人。 &#x1f40c; 个人主页&#xff1a;蜗牛牛啊 &#x1f525; 系列专栏&#xff1a;初出茅庐C语言 ☀️ 学习格言&#xff1a;眼泪终究流不成海洋&#xff0c;人总要不断成长&am…

Selenium基础 — iframe表单操作

1、什么是iframe表单 实际上就是HTML页面中使用iframe/frame标签&#xff0c;是在当前页面中引用了其他页面的链接&#xff0c;真正的页面数据并没有出现在当前页面源码中&#xff0c;但是在浏览器中我们时看到的。简单理解可以使页面中开了一个窗口显示另一个页面。 我们在We…

谷粒商城-支付业务

目录 商城业务-支付-支付宝沙箱&代码 商城业务-支付-RSA、加密加签、密钥等 商城业务-支付-内网穿透 商城业务-订单服务-整合支付前需要注意的问题 商城业务-订单服务-整合支付 商城业务-订单服务-支付成功同步回调 商城业务-订单服务-订单列表页渲染完成 商城业务…

网络请求+基于Node.js的WebSocket

目录 前言 网络访问配置 1.配置流程 注意事项 使用限制 网络请求详情API wx.request请求数据API ​编辑 wx.uploadFile文件上传API wx.downloadFile文件下载API WebSocket会话API 基于Node.js的WebSocket 为什么WebSocket连接可以实现全双工通信而HTTP连接不行呢&…

git命令记不住?可视化git操作平台Sourcetree入门教程

1、为什么要用Sourcetree 在应届生在参加实习或者工作的时候&#xff0c;往往需要配置各种各样的环境&#xff0c;git肯定是程序员必不可少的分布式版本控制系统&#xff0c;但刚出来工作时往往对git代码不熟悉&#xff0c;老是会忘掉一些命令&#xff0c;所以笔者在此推荐一个…