字符点阵在LCD上显示

来源:互联网 发布:北大网络教育好考吗 编辑:程序博客网 时间:2024/04/30 12:00

这一节,目的:显示在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


0 0