第三阶段应用层——1.7 数码相册—电子书(1)—实现

    技术2022-07-10  103

    数码相册——电子书的实现

    硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3)软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.04_x64 系统参考资料:《嵌入式Linux应用开发手册》、《嵌入式Linux应用开发手册第2版》开发环境:Linux 3.4.2内核、arm-linux-gcc 4.3.2工具链源码仓库:https://gitee.com/d_1254436976/Embedded-Linux-Phase-3

    目录

    数码相册——电子书的实现 一、大致框架1、框架图2、代码间的有效管理 二、`config.h`文件分析三、挑display显示部分来进行分析1、`disp_manager.h`文件分析2、`disp_manager.c`文件分析3、`fb.c`文件分析3.1 分配结构体3.2 设置结构体3.3 注册结构体3.4 完整文件 四、程序的运行1、编译2、执行3、现象


    一、大致框架

    1、框架图

    对于在LCD中显示一个文件,总体上进行下面几件事:

    去文件中获得编码信息,对于每个文件,保存的时候,系统对自动或手动的根据编码规范,对文件的信息进行编码:如保存为ASCII、GBK、UTF-8、UTF16LE、UTF16BE;根据获得的编码信息得到字体数据(LCD上表示为点阵);把字体数据(点阵)显示在LCD上。

    所以根据这个信息,可以总结出上述的框架。

    2、代码间的有效管理

    对于上述完成主要功能的4个部分:encoding编码部分、fonts获取字体点阵部分、display显示部分、draw协调部分,会仿照Linux内核的方式采用模块化进行管理,对于每个部分:

    在代码上实现一个manager,向下支持各种文件的拓展,把所支持的文件放入链表中进行管理;向上提供各种接口,使其可以根据实际情况进行从链表中选择不同的拓展文件来进行功能的实现。每个部分都会定义一个结构体变量,拓展文件可以根据自己的情况:分配结构体、设置结构体、注册结构体。对于每个部分之间进行数据的沟通,可以通过main.c和draw.c的协调,通过获得各个部分的结构体变量,在draw.c文件中进行交互。

    二、config.h文件分析

    对于这个文件,从名字就知道,它是一个配置文件,定义了一些宏定义,供所有文件调用

    源码 对于#define DBG_PRINTF(...) 与 #define DBG_PRINTF printf: 当我们调试的时候,可以//#define DBG_PRINTF(...) #define DBG_PRINTF printf,打印调试信息; 当我们程序发布时,可以#define DBG_PRINTF(...) //#define DBG_PRINTF printf,屏蔽调试信息的打印。 #ifndef _CONFIG_H #define _CONFIG_H #include <stdio.h> #define FB_DEVICE_NAME "/dev/fb0" #define COLOR_BACKGROUND 0xE7DBB5 /* 泛黄的纸 */ #define COLOR_FOREGROUND 0x514438 /* 褐色字体 */ //#define DBG_PRINTF(...) #define DBG_PRINTF printf #endif /* _CONFIG_H */

    三、挑display显示部分来进行分析

    1、disp_manager.h文件分析

    在这个文件中,定义了一个结构体和相关函数,供拓展文件来分配结构体、设置结构体、注册结构体

    #ifndef _DISP_MANAGER_H #define _DISP_MANAGER_H typedef struct DispOpr { char *name; int Xres; int Yres; int Bpp; int (*DeviceInit)(void); int (*ShowPixel)(int PenX, int PenY, unsigned int Color); int (*CleanScreen)(unsigned int BackColor); struct DispOpr *ptNext; }T_DispOpr, *PT_DispOpr; int RegisterDispOpr(PT_DispOpr ptDispOpr); void ShowDispOpr(void); int DisplayInit(void); int FBInit(void); #endif /* _DISP_MANAGER_H */

    2、disp_manager.c文件分析

    这个文件就是负责上述disp_manager.h文件的函数实现:

    #include <config.h> #include <disp_manager.h> #include <string.h> static PT_DispOpr s_ptDispOprHead; /* 函数名: 注册函数 * 函数功能:构建一个链表:把多个拓展文件的结构体“串”起来 * 函数实现:根据传入的结点,首先判断该链表头是否为空 * 空则,头结点指向传入的节点,且把节点的ptNext域指向NULL * 不空则,尾插法插入链表 */ int RegisterDispOpr(PT_DispOpr ptDispOpr) { PT_DispOpr ptTmp; if (!s_ptDispOprHead) { s_ptDispOprHead = ptDispOpr; ptDispOpr->ptNext = NULL; } else { ptTmp = s_ptDispOprHead; while (ptTmp->ptNext) { ptTmp = ptTmp->ptNext; } ptTmp->ptNext = ptDispOpr; ptDispOpr->ptNext = NULL; } return 0; } /* 显示支持拓展文件的名字 */ void ShowDispOpr(void) { int i = 0; PT_DispOpr ptTmp = s_ptDispOprHead; while (ptTmp) { printf("d %s\n", i++, ptTmp->name); ptTmp = ptTmp->ptNext; } } /* 获取指定的名字的拓展文件 */ PT_DispOpr GetDispOpr(char *pName) { PT_DispOpr ptTmp = s_ptDispOprHead; while (ptTmp) { if (strcmp(ptTmp->name, pName) == 0) { return ptTmp; } ptTmp = ptTmp->ptNext; } return NULL; } /* 初始化函数 */ int DisplayInit(void) { int error; error = FBInit(); return error; }

    3、fb.c文件分析

    3.1 分配结构体

    static T_DispOpr s_tFBDispOpr = { .name = "fb", .DeviceInit = FBDeviceInit, .ShowPixel = FBShowPixel, .CleanScreen = FBCleanScreen, };

    3.2 设置结构体

    /* LCD设备初始化函数 */ static int FBDeviceInit(void) { /* 打开设备:支持读写 */ s_FBFD = open(FB_DEVICE_NAME, O_RDWR); if (s_FBFD < 0) { DBG_PRINTF("can not open %s , err code :%d\n", FB_DEVICE_NAME, s_FBFD); return -1; } /* 获得可变信息 */ if (ioctl(s_FBFD, FBIOGET_VSCREENINFO, &s_tVar)) { DBG_PRINTF("can not get s_tVar\n"); return -1; } /* 获得固定信息 */ if (ioctl(s_FBFD, FBIOGET_FSCREENINFO, &s_tFix)) { DBG_PRINTF("can not get s_tVar\n"); return -1; } s_tFBDispOpr.Xres = s_tVar.xres; s_tFBDispOpr.Yres = s_tVar.yres; s_tFBDispOpr.Bpp = s_tVar.bits_per_pixel; s_ScreenSize = s_tVar.xres * s_tVar.yres * s_tVar.bits_per_pixel / 8; // 屏幕总像素所占的字节数 s_LineWidth = s_tVar.xres * s_tVar.bits_per_pixel / 8; // 每行像素所占的字节数 s_PixelWidth = s_tVar.bits_per_pixel / 8; // 每个像素所占字节数 /* 直接映射到内存的Framebuffer */ s_pFbmem = (unsigned char *)mmap(NULL, s_ScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, s_FBFD, 0); if (s_pFbmem == (unsigned char *)-1) { DBG_PRINTF("can not mmap\n"); return -1; } return 0; } /* LCD像素显示函数 */ static int FBShowPixel(int PenX, int PenY, unsigned int Color) { unsigned char *pPen8; unsigned short *pPen16; unsigned int *pPen32; unsigned int red, green, blue; if ((PenX >= s_tVar.xres) || (PenY >= s_tVar.yres)) { DBG_PRINTF("out of region\n"); return -1; } /* 该坐标在内存中对应像素的位置 */ pPen8 = s_pFbmem + PenY * s_LineWidth + PenX * s_PixelWidth; pPen16 = (unsigned short *)pPen8; pPen32 = (unsigned int *)pPen8; switch (s_tFBDispOpr.Bpp) { case 8: *pPen8 = (unsigned char)Color; break; case 16: /* RGB:565 */ red = ((Color >> 16) & 0xffff) >> 3; green = ((Color >> 8 ) & 0xffff) >> 2; blue = ((Color >> 0 ) & 0xffff) >> 3; *pPen16 = (red << 11) | (green << 5) | blue; break; case 32: *pPen32 = Color; break; default: DBG_PRINTF("can not surport %d bpp\n", s_tFBDispOpr.Bpp); return -1; } return 0; } /* 清屏函数 */ static int FBCleanScreen(unsigned int BackColor) { int i; unsigned char *pPen8; unsigned short *pPen16; unsigned int *pPen32; unsigned int red, green, blue; pPen8 = s_pFbmem; pPen16 = (unsigned short *)pPen8; pPen32 = (unsigned int *)pPen8; switch (s_tFBDispOpr.Bpp) { case 8: memset(pPen8, BackColor, s_ScreenSize); break; case 16: /* RGB:565 */ red = ((BackColor >> 16) & 0xffff) >> 3; green = ((BackColor >> 8 ) & 0xffff) >> 2; blue = ((BackColor >> 0 ) & 0xffff) >> 3; BackColor = (red << 11) | (green << 5) | blue; for (i = 0; i < s_ScreenSize;) { *pPen16 = BackColor; pPen16++; i += 2; } break; case 32: for (i = 0; i < s_ScreenSize;) { *pPen32 = BackColor; pPen32++; i += 4; } break; default: DBG_PRINTF("can not surport
    转载请注明原文地址:https://ipadbbs.8miu.com/read-2518.html
    最新回复(0)