ASCII 字符的点阵显示
要在 LCD 中显示一个 ASCII 字符,即英文字母这些字符,首先是要找到字符对应的点阵。在 Linux 内核源码中有这个文件:lib\fonts\font_8x16.c,里面以数组形式保存各个字符的点阵,比如:
数组里的数字是如何表示点阵的?以字符 A 为例
上图左侧有 16 行数值,每行 1 个字节。每一个节对应右侧一行中 8 个像素:像素从右边数起,bit0 对应第 0 个像素,bit1 对应第 1 个像素,……,bit7 对应第 7 个像素。某位的值为 1 时,表示对应的像素要被点亮;值为 0 时表示对应的像素要熄灭。所以要显示某个字符时,根据它的 ASCII 码在 fontdata_8x16 数组中找到它的点阵,然后取出这 16 个字节去描画 16 行像素。比如字符 A 的 ASCII 值是 0x41,那么从 fontdata_8x16[0x41*16]开始取其点阵数据。
核心函数是 void lcd_put_ascii(int x, int y, unsigned char c),它在 LCD 的(x,y)位置处显示字符 c
获取点阵
对于字符 c,char c,它的点阵获取方法如下:
unsigned char *dots = (unsigned char )&fontdata_8x16[c16];
描点
现在要实现显示字符 “A” , 因为有十六行,所以首先要有一个循环 16 次的大循环,然后每一行里有 8位,那么在每一个大循环里也需要一个循环 8 次的小循环。小循环里的判断单行的描点情况,如果是 1,就填充白色,如果是 0 就填充黑色,如此一来,就可以显示出黑色底,白色轮廓的英文字母。
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, 0xFF0000); /* 白 */
}
else
{
/* hide */
lcd_put_pixel(x+7-b, y+i, 0); /* 黑 */
}
}
}
main 函数
main 函数中首先要打开 LCD 设备,获取 Framebuffer 参数,实现lcd_put_pixel 函数;然后调用 lcd_put_ascii 即可绘制字符。
int main(int argc, char **argv)
{
fd_fb = open("/dev/fb0", O_RDWR);
if (fd_fb < 0)
{
printf("can't open /dev/fb0\n");
return -1;
}
if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
{
printf("can't get var\n");
return -1;
}
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);
if (fbmem == (unsigned char *)-1)
{
printf("can't mmap\n");
return -1;
}
/* 清屏: 全部设为黑色 */
memset(fbmem, 0, screen_size);
lcd_put_ascii(var.xres/2, var.yres/2, 'B'); /*在屏幕中间显示8*16的字母A*/
// lcd_put_ascii(var.xres/2 + 8, var.yres/2, 'O');
munmap(fbmem , screen_size);
close(fd_fb);
return 0;
}
结果如下: