乐趣区

关于c:嵌入式Linux1百问网课后题

第四篇:嵌入式 Linux 利用开发基础知识

第六章:文件显示 – 6.3 中文字符的点阵显示

 批改 lcd_put_chinese 函数,能够指定字符色彩。实现 lcd_put_str 函数,能够输入混合的中英文字符,比方“中国  china”,反对主动换行。

成果:读取指定文件中英文数据到 lcd 显示

文件:show_chinses.c

#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>

extern const unsigned char fontdata_8x16[];  // fontdata_8x16 独自在 fontdata.c

static int fd_fb                    = 0;
static unsigned char *fb_base       = NULL;
static struct fb_var_screeninfo var = {0};
static int screen_size              = 0;
static int line_width               = 0;
static int pixel_width              = 0;

static int fd_hzk16;
static struct stat hzk_stat  = {0};
static unsigned char *hzkmem = {0};

void lcd_put_pixel(int x, int y, unsigned int color)
{
    unsigned char *pen_8   = fb_base + y * line_width + x * pixel_width;
    unsigned short *pen_16 = (unsigned short*)(pen_8);
    unsigned int *pen_32   = (unsigned int*)(pen_8);

    unsigned int red   = 0;
    unsigned int green = 0;
    unsigned int blue  = 0;

    switch (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);
            *pen_16 - color;
            break;

        case 32:
            *pen_32 = color;
            break;

        default:
            printf("can't open %dbpp\n", var.bits_per_pixel);
            break;
    }
}

void lcd_put_ascii(int x, int y, char c, unsigned int color)
{unsigned char *dots = (unsigned char*)(&fontdata_8x16);
    int i = 0;
    int b = 0;

    for (i=0; i<16; ++i)
    {for (b=7; b>=0; --b)
        {if (dots[i] & (1 << b))
                lcd_put_pixel(x+7-b, y+i, color);
            else
                lcd_put_pixel(x+7-b, y+i, 0xffffff);
        }
    }
}

void lcd_put_ascii_str(int x, int y, const unsigned char *str, unsigned int color)
{
    unsigned int index = 0;

    while(*str)
    {if (*str == '\r' || *str == '\n')
        {
            y += 16;
            index = 0;
        }
        else
        {lcd_put_ascii(x + index, y, *str, color);
            index += 8;
        }

        ++str;
    }
}

void lcd_put_chinese(int x, int y, const unsigned char *str, unsigned int color)
{unsigned int area   = str[0] - 0xa1;
    unsigned int where  = str[1] - 0xa1;
    unsigned char *dots = hzkmem + (area * 94 + where) * 32;
    unsigned char byte  = 0;

    int i = 0;
    int j = 0; 
    int b = 0;

    for (i=0; i<16; ++i)
    {for (j=0; j<2; ++j)
        {byte = dots[i*2 + j];
            for (b = 7; b>=0; --b)
            {if (byte & (1 << b))
                    lcd_put_pixel(x+j*8+7-b, y+i, color);
                else
                    lcd_put_pixel(x+j*8+7-b, y+i, 0xffffff);
            }
        }
    }
}

void lcd_put_str(int x, int y, const unsigned char*str, unsigned int color)
{
    unsigned int index = 0;

    while (*str)
    {if (*str <= 0xa1)
        {if (*str == '\r' || *str == '\n')
            {
                y += 16;
                index = 0;
            }
            else
            {lcd_put_ascii(x + index, y, *str, color);
                index += 8;
            }
            str++;
        }
        else
        {lcd_put_chinese(x + index, y, str, color);
            index += 16;
            str+=2;
        }
    }
}

int test_show(const unsigned char *path)
{
    int fd_src = 0;
    unsigned char *srcmem = NULL;
    struct stat src_stat  = {0};

    fd_src = open(path, O_RDONLY);
    if (fd_src < 0)
    {printf("can't open %s\n", path);
        return -1;    
    }

    if(fstat(fd_src, &src_stat))
    {printf("can't get src_stat\n");
        return -1;
    }

    srcmem = (unsigned char*)mmap(NULL, src_stat.st_size, PROT_READ, MAP_SHARED, fd_src, 0);
    if (srcmem == (void*)-1)
    {printf("can't mmap for srcmem\n");
        return -1;
    }

    lcd_put_str(10, 10, srcmem, 0x11ee88);

    munmap(srcmem, src_stat.st_size);
    close(fd_src);
    
}

int main(int argc, char **argv)
{
    int i = 0;

    fd_hzk16 = open("HZK16", O_RDONLY);
    if(fd_hzk16 < 0)
    {printf("can't open HZK16\n");
        return -1;
    }

    if(fstat(fd_hzk16, &hzk_stat))
    {printf("can't get fstat\n");
        return -1;
    }

    hzkmem = (unsigned char*)mmap(NULL, hzk_stat.st_size, PROT_READ, MAP_SHARED, fd_hzk16, 0);
    if (hzkmem == (void*)-1)
    {printf("can't mmap for hzkmem\n");
        return -1;
    }

    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 fd_fb var\n");
        return -1;
    }
    
    screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
    pixel_width = var.bits_per_pixel / 8;
    line_width = var.xres * var.bits_per_pixel / 8;

    fb_base = mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
    if (fb_base == (void*)-1)
    {printf("cant mmap for fb_base\n");
        return -1;
    }

    memset(fb_base, 0xff, screen_size);

    //====================================================

    if (argc == 1)
    {// lcd_put_ascii(100, 100, 'A', 0);
        // lcd_put_ascii_str(100, 100, "Hello word\nHow are you", 0x567894);
        // lcd_put_chinese(200, 200, "中", 0x123456);
        lcd_put_str(100, 100, "A 中 A\nhahah", 0x11ee88);
    }
    else
    {test_show(argv[1]) ;    
    }

    //====================================================

    munmap(fb_base, screen_size);
    munmap(hzkmem, hzk_stat.st_size);

    close(fd_fb);
    close(fd_hzk16);

    return 0;
}

编译运行:

ubutun 编译        -> arm-linux-gnueabihf-gcc -fexec-charset=GB2312 fontdata.c show_chinese.c 
ubutun 拷贝文件    -> cp ./a.out ~/nfs_rootfs/
                  -> cp ./source.txt ~/nfs_rootfs/ 
                  -> cp ./HZK16 ~/nfs_rootfs/
                  
开发板执行         -> ./a.out source.txt

文件:source.txt [请以 GB2312 保留]

If I could,I surely would. 
如果能够,我相对违心!May there be enough clouds in your life to make a beautiful sunset.
愿你的生命中有足够的云翳,来造成一个漂亮的傍晚。The worst way to miss someone is to be sitting right beside them knowing you can’t have them.
失去某人,最蹩脚的莫过于,他近在身旁,却犹如远在天边。You must always have faith in who you are!
置信本人 保持本人!The longest day has an end.
最惆怅的日子也有止境。Dont’t cry because it is over, smile because it happened.
不要因为完结而哭泣. 微笑吧, 为你的已经领有。Happineis good health and a bad memory.
幸福是良好的衰弱加上蹩脚的忘性。
退出移动版