字元點陣在LCD上顯示
阿新 • • 發佈:2018-12-27
這一節,目的:顯示在LCD顯示字元(英文和中文)
預備知識:
1 知道什麼是編碼庫,核心裡面自帶的Font_8*16.c檔案中,已經包含了ASCII的編碼庫,其中每個字元用16個位元組表示
2 中文編碼:有GB2312,BIG5(繁體字使用),GBK ,UTF-8(一直預設使用的都是這種),,Unicode編碼等等,因此,需要使用這樣的編碼庫,通過編碼查詢的方式,可以找到相應的字元,在這裡使用HZK16
2.1 文字編碼方式
原始檔用不同的編碼方式編寫,會導致執行結果不一樣。
怎麼解決?編譯程式時,要指定字符集
man gcc , /charset
-finput-charset=charset 表示原始檔的編碼方式, 預設以UTF-8來解析
-fexec-charset=charset 表示可執行程式裡的字時候以什麼編碼方式來表示,預設是UTF-8
gcc -o a a.c //
編譯
gcc -finput-charset=GBK -fexec-charset=UTF-8 -o utf-8_2 ansi.c
程式碼如下:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
//#include <sys/types.h>
//#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <linux/fb.h>
#include <string.h>
#define FONTDATAMAX 4096
static const char fontdata_8x16[FONTDATAMAX] = {
.....
};
int fd_fb = 0;
int fd_hzk16 = 0;
struct fb_var_screeninfo fb_var;
struct fb_fix_screeninfo fb_fix;
int screen_size = 0;
unsigned char* fb_mem;
struct stat hzk_stat;
unsigned char *hzk_mem;
int line_width;
int pix_width;
void lcd_put_pixel(int x, int y, unsigned int color)
{
unsigned char *pen_8 = (unsigned char*)(fb_mem+y*line_width+x*pix_width);
unsigned short *pen_16;
unsigned int *pen_32;
pen_16 = (unsigned short*)pen_8;
pen_32 = (unsigned int*)pen_8;
unsigned char red,green,blue;
switch(fb_var.bits_per_pixel)
{
case 8:
*pen_8 = color;
break;
case 16:
red = (color >>16)&0xff;
green = (color>>8)&0xff;
blue = (color>>0)&0xff;
color = ((red>>3)<<11)|((green>>2)<<5)|((blue>>3)<<0);
*pen_16 = color;
break;
case 32:
*pen_32 = color;
break;
default:
printf("Can' support error\n");
break;
}
}
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_put_pixel(x+7-j,y+i,0xffffff);
}
else
{
lcd_put_pixel(x+7-j,y+i,0x0);
}
}
}
}
void lcd_put_chinese(int x, int y ,unsigned char *str)
{
unsigned int area = str[0] - 0xA1;
unsigned int where = str[1] -0xA1;
unsigned char* dots = (unsigned char*)(hzk_mem + (area*94 + where)*32);
int i,j,k;
unsigned char byte;
for(i=0;i<16;i++)
{
for(k=0;k<2;k++)
{
byte = dots[i*2+k];
for(j=7;j>=0;j--)
{
if(byte &(1<<j))
{
lcd_put_pixel(x+k*8+7-j, y+i,0xffffff);
}
else
{
lcd_put_pixel(x+k*8+7-j,y+i,0x0);
}
}
}
}
}
int main()
{
unsigned char * str = "1ú";
fd_fb = open("/dev/fb0",O_RDWR);
if(fd_fb < 0)
{
printf("open /dev/fb0 failed\n");
return -1;
}
if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &fb_var))
{
printf("get var information failed\n");
return -1;
}
if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &fb_fix))
{
printf("get fix information failed\n");
return -1;
}
screen_size = fb_var.xres * fb_var.yres * fb_var.bits_per_pixel /8;
line_width = fb_var.xres * fb_var.bits_per_pixel /8;
pix_width = fb_var.bits_per_pixel /8;
fb_mem =(unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
if(fb_mem == (unsigned char *)-1)
{
printf("fb_mem mmap failed\n ");
return -1;
}
fd_hzk16 = open("HZK16",O_RDONLY);
if(fd_hzk16 < 0)
{
printf("open HZK16 failed\n");
return -1;
}
if(fstat(fd_hzk16, &hzk_stat))
{
printf("get hzk_stat failed\n");
return -1;
}
hzk_mem =(unsigned char *)mmap(NULL , hzk_stat.st_size, PROT_READ, MAP_SHARED, fd_hzk16, 0);
if(hzk_mem == (unsigned char *)-1)
{
printf("hzk_mem mmap failed\n ");
return -1;
}
memset(fb_mem, 0, screen_size);
lcd_put_ascii(fb_var.xres/2, fb_var.yres/2, 'A');
printf("chinese code : %02X %02X \n",str[0],str[1]);
lcd_put_chinese(fb_var.xres/2 + 8, fb_var.yres/2, str);
return 0;
}
編譯測試
首先核心中需要有FrameBuffer的支援
1. 配置、修改核心支援把x35_mini2440_lcd.c編譯進去
(1)把驅動程式lcd.c拷貝到核心的drivers/video/目錄下
(2)修改drivers/video/Makefile
#obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
obj-$(CONFIG _FB_S3C2410) +=x35_mini2440_lcd.o
(3)make menuconfig選擇上對lcd的配置
Device Drivers --->
Graphics support --->
<*> Support for frame buffer devices --->
<*> S3C2410 LCD framebuffer support
(4)make uImage
gcc -finput-charset=GBK -fexec-charset=UTF-8 -o utf-8_2 ansi.c