【嵌入式Linux】1_百问网课后题

码农天地 -
【嵌入式Linux】1_百问网课后题
第四篇:嵌入式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[c * 16]);
    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.
幸福是良好的健康加上糟糕的记性。
特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。

Tags 标签

加个好友,技术交流

1628738909466805.jpg