【嵌入式Linux】1_百问网课后题_第四篇嵌入式Linux应用开发基础知识

云上漂泊者
• 阅读 1816

第六章:文件显示

6.3 中文字符的点阵显示

修改 lcd_put_chinese 函数,可以指定字符颜色。
实现 lcd_put_str 函数, 可以输出混合的中英文字符,比如“中国  china”,支持自动换行。
效果:读取指定文件中英文数据到lcd显示

【嵌入式Linux】1_百问网课后题_第四篇嵌入式Linux应用开发基础知识

文件: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.
幸福是良好的健康加上糟糕的记性。

第七章:输入系统应用编程

7.3 不使用库的应用程序实例

使用 select 函数实现LCD输入信息获取
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>

int main(int argc, char **argv)
{
    int fd = 0;
    int len = 0;
    int i = 0;
    int ret = 0;
    struct input_id id = {0};
    struct input_event event = {0};    
    unsigned char byte = 0;
    unsigned char bit = 0;
    unsigned int evbit[2] = {0};
    int nfds;
    fd_set readfds;
    struct timeval tv;
    
    const char *ev_names[] = {
        "EV_SYN ",
        "EV_KEY ",
        "EV_REL ",
        "EV_ABS ",
        "EV_MSC ",
        "EV_SW    ",
        "NULL ",
        "NULL ",
        "NULL ",
        "NULL ",
        "NULL ",
        "NULL ",
        "NULL ",
        "NULL ",
        "NULL ",
        "NULL ",
        "NULL ",
        "EV_LED ",
        "EV_SND ",
        "NULL ",
        "EV_REP ",
        "EV_FF    ",
        "EV_PWR ",
    };

    if (argc <2)
    {
        printf("Usage: %s <dev>\n", argv[0]);
        return -1;
    }

    fd = open(argv[1], O_RDWR | O_NONBLOCK);
    if (fd < 0)
    {
        printf("can not open %s\n", argv[1]);
        return -1;
    }
    
    if (!ioctl(fd, EVIOCGID, &id))    
    {
        printf("bustype = 0x%x\n", id.bustype);
        printf("vendor  = 0x%x\n", id.vendor);
        printf("product = 0x%x\n", id.product);
        printf("version = 0x%x\n", id.version);
    }

    len = ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);    
    if (len > 0 && len <= sizeof(evbit))
    {
        printf("support ev type: ");
        for (i=0; i<len; ++i)
        {
            byte = ((unsigned char*)evbit)[i];
            for (bit=0; bit<8; ++bit)
            {
                if (byte & (1 << bit))
                    printf("%s ", ev_names[i * 8 + bit]);    // 这里的下标和 ev_names 填充 "NULL" 一起理解
            }
        }
        printf("\n");
    }

    while (1)
    {
        FD_ZERO(&readfds);
        FD_SET(fd, &readfds);
        tv.tv_sec  = 5;
         tv.tv_usec = 0;
        nfds = fd + 1;
        ret = select(nfds, &readfds, NULL, NULL, &tv);
        if (ret > 0)
        {
            if (FD_ISSET(fd, &readfds))
                while (read(fd, &event, sizeof(event)) == sizeof(event))
                    printf("get event: type = 0x%x, code = 0x%x, value = 0x%x\n", event.type, event.code, event.value);
        }
        else if (ret == 0)
        {
            printf("time out\n");
        }
        else
        {
            printf("select err\n");
        }
        
    }

    close(fd);

    return 0;
}
点赞
收藏
评论区
推荐文章
Karen110 Karen110
3年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Peter20 Peter20
4年前
mysql中like用法
like的通配符有两种%(百分号):代表零个、一个或者多个字符。\(下划线):代表一个数字或者字符。1\.name以"李"开头wherenamelike'李%'2\.name中包含"云",“云”可以在任何位置wherenamelike'%云%'3\.第二个和第三个字符是0的值wheresalarylike'\00%'4\
Stella981 Stella981
3年前
JS 苹果手机日期显示NaN问题
问题描述newDate("2019122910:30:00")在IOS下显示为NaN原因分析带的日期IOS下存在兼容问题解决方法字符串替换letdateStr"2019122910:30:00";datedateStr.repl
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql中时间比较的实现
MySql中时间比较的实现unix\_timestamp()unix\_timestamp函数可以接受一个参数,也可以不使用参数。它的返回值是一个无符号的整数。不使用参数,它返回自1970年1月1日0时0分0秒到现在所经过的秒数,如果使用参数,参数的类型为时间类型或者时间类型的字符串表示,则是从1970010100:00:0
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Stella981 Stella981
3年前
JavaScript常用函数
1\.字符串长度截取functioncutstr(str,len){vartemp,icount0,patrn/^\x00\xff/,strre"";for(vari
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
云上漂泊者
云上漂泊者
Lv1
共看明月应垂泪,一夜乡心五处同。
文章
7
粉丝
0
获赞
0