1. 程式人生 > >字元點陣在LCD上顯示

字元點陣在LCD上顯示


這一節,目的:顯示在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