一、实验目的
1.编写能够在嵌入式开发板LCD上显示汉字的程序;
2.在Ubuntu系统中编译上述程序生成可执行文件;
3.到开发板中验证。
二、实验步骤
1. Ubuntu系统上编写验证程序
Ubuntu系统上编写的验证程序如下,为了验证是否能够正确从HZK16字库中读取出某个字。
HZK16汉字16*16点阵字库的使用及实例程序
2. Ubuntu系统上编写能够在板子上执行的程序
要在LCD上显示“福州大学”,首先打开FrameBuffer驱动:fd_fb = open(“/dev/fb0”, O_RDWR),之后使用函数mmap映射显示存储器,最后调用函数PrintLCD显示字体,代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#define FONT_COLOR 0xf100 // 红色
#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 1600
#define PIXEL_BYTES 2
#define ZOOM_FACTOR 20 // 放大倍数
#define CHAR_SPACING 10 // 字符间距
unsigned short *fb = 0;
void getHZCode(unsigned char incode[], unsigned char hzCode[]) {
long offset; // 相对于字库起始位置的偏移字节数
int quCode = incode[0] - 0xa0; // 区码: 该汉字的区号
int weiCode = incode[1] - 0xa0; // 位码: 该汉字的位号
offset = (94 * (quCode - 1) + (weiCode - 1)) * 32; // 32为一个汉字需要32字节(16*16=256个点,256/8=32)
FILE *HZK = fopen("HZK16S", "rb");
if (HZK == NULL) { // rb: 打开二进制文件
printf("Can't Open HZK16S\n");
exit(1);
}
fseek(HZK, offset, SEEK_SET);
fread(hzCode, 1, 32, HZK); // 读取表示此汉字的32字节数到hzCode中
fclose(HZK);
}
void printLCD(int top, int left, unsigned char hzCode[]) {
int i, j, k, m, n;
for (j = 0; j < 16; j++) {
for (i = 0; i < 2; i++) {
for (k = 0; k < 8; k++) {
if (hzCode[j * 2 + i] & (0x80 >> k)) {
for (m = 0; m < ZOOM_FACTOR; m++) {
for (n = 0; n < ZOOM_FACTOR; n++) {
*(fb + (j * ZOOM_FACTOR + m + top) * SCREEN_WIDTH + left + (i * 8 + k) * ZOOM_FACTOR + n) = FONT_COLOR;
}
}
}
}
}
}
}
int main() {
int i;
int fd_fb = 0;
unsigned char incode[2]; // 存储区码和位码
unsigned char hzCode[32]; // 存储汉字点阵数据
char testStr[] = {
0xB8, 0xA3, // 福
0xD6, 0xDD, // 州
0xB4, 0xF3, // 大
0xD1, 0xA7 // 学
};
int strLength = sizeof(testStr);
fd_fb = open("/dev/fb0", O_RDWR); // 打开FrameBuffer驱动
if (fd_fb == -1) {
perror("open fb0");
return 1;
}
fb = (unsigned short *)mmap(0, SCREEN_WIDTH * SCREEN_HEIGHT * PIXEL_BYTES, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0); // 映射显示存储器,2: 2Bytes
if (fb == MAP_FAILED) {
perror("mmap");
close(fd_fb);
return 1;
}
memset(fb, 0, SCREEN_WIDTH * SCREEN_HEIGHT * PIXEL_BYTES); // 清屏
for (i = 0; i < strLength; i += 2) {
incode[0] = testStr[i]; // 区码
incode[1] = testStr[i + 1]; // 位码
getHZCode(incode, hzCode);
printLCD(100, i / 2 * (16 * ZOOM_FACTOR + CHAR_SPACING), hzCode); // 显示放大的点阵
}
munmap(fb, SCREEN_WIDTH * SCREEN_HEIGHT * PIXEL_BYTES);
close(fd_fb);
return 0;
}