电子产品量产工具(显示系统)

所学来自百问网

目录

1.项目框架

2.显示系统

2.1 数据结构的抽象

2.2 底层的管理

2.3 framebuffer的实现

2.4 显示系统的单元测试


1.项目框架

2.显示系统

架构说明:通过disp_manager.c文件作为中间件,去调用底层文件(Framebuffer或web显示)封装好的函数包括设备初始化、资源释放等,顶层文件通过调用中间件去实现所需功能,这样子设计能达到充分的解耦,也能让代码变得更具有可维护性和健壮性。

2.1 数据结构的抽象

disp_manager.h:该头文件对设备进行各种操作(初始化、数据获取、区域刷新等)进行数据结构的抽象,DispBuff是用于对显示像素的大小的获取,Region是用于对刷新区域的设置

#ifndef _DISP_MANAGER_H
#define _DISP_MANAGER_H
​
#ifndef NULL
#define NULL (void *)0
#endif
​
// 缓冲区地址
typedef struct DispBuff {
    int iXres;
    int iYres;
    int iBpp;
    char *buff;
}DispBuff, *PDispBuff;
​
// 显示区域 包括xy坐标和长 高
typedef struct Region {
    int iLeftUpX;
    int iLeftUpY;
    int iWidth;
    int iHeigh;
}Region, *PRegion;
​
// 对设备进行各种操作
typedef struct DispOpr {
    char *name; //设备名称                  
    int (*DeviceInit)(void); //设备初始化
    int (*DeviceExit)(void); //设备退出,释放
    int (*GetBuffer)(PDispBuff ptDispBuff); //获取数据
    int (*FlushRegion)(PRegion ptRegion, PDispBuff ptDispBuff); //刷新区域
    struct DispOpr *ptNext; //链表
}DispOpr, *PDispOpr;
​
​
// 头文件声明
void RegisterDisplay(PDispOpr ptDispOpr);
void DisplayInit(void);
int SelectDefaultDisplay(char *name);
int InitDefaultDisplay(void);
int PutPixel(int x, int y, unsigned int dwColor);
int FlushDisplayRegion(PRegion ptRegion, PDispBuff ptDispBuff);
PDispBuff GetDisplayBuffer(void);
​
#endif

2.2 底层的管理

disp_manager.c:该文件主要是对底层的管理即中间层,目前web未加入,通过链表对设备进行添加、选择,同时对framebuffer封装函数的调用,进一步的解耦,让代码能更好的维护和拓展

#include <stdio.h>
#include <string.h>
#include <disp_manager.h>
​
/* 管理底层的LCD、WEB */
static PDispOpr g_DispDevs = NULL; //链表
static PDispOpr g_DispDefault = NULL;
static DispBuff g_tDispBuff;
static int line_width; //一行的像素大小
static int pixel_width; // 一个点所占像素大小
​
// 绘制像素
int PutPixel(int x, int y, unsigned int dwColor)
{
    unsigned char *pen_8 = (unsigned char *)(g_tDispBuff.buff+y*line_width+x*pixel_width);
    unsigned short *pen_16; 
    unsigned int *pen_32;   
​
    unsigned int red, green, blue;  
​
    pen_16 = (unsigned short *)pen_8;
    pen_32 = (unsigned int *)pen_8;
​
    switch (g_tDispBuff.iBpp)
    {
        case 8:
        {
            *pen_8 = dwColor;
            break;
        }
        case 16:
        {
            /* 565 */
            red   = (dwColor >> 16) & 0xff;
            green = (dwColor >> 8) & 0xff;
            blue  = (dwColor >> 0) & 0xff;
            dwColor = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
            *pen_16 = dwColor;
            break;
        }
        case 32:
        {
            *pen_32 = dwColor;
            break;
        }
        default:
        {
            printf("can't surport %dbpp\n", g_tDispBuff.iBpp);
            return -1;
            break;
        }
    }
​
    return 0;
}
​
// 注册设备,将设备加入链表
void RegisterDisplay(PDispOpr ptDispOpr)
{
    ptDispOpr->ptNext = g_DispDevs;
    g_DispDevs = ptDispOpr;
}
​
// 选择设备
int SelectDefaultDisplay(char *name)
{
    PDispOpr pTmp = g_DispDevs;
    while (pTmp) 
    {
        // 从链表中找设备
        if (strcmp(name, pTmp->name) == 0)
        {
            g_DispDefault = pTmp; //将被选择的设备赋值给g_DispDefault
            return 0;
        }
        pTmp = pTmp->ptNext;
    }
    // 否则退出
    return -1;
}
​
// 初始化选择的设备
int InitDefaultDisplay(void)
{
    int ret;
    
    ret = g_DispDefault->DeviceInit();
    if (ret)
    {
        printf("DeviceInit err\n");
        return -1;
    }
​
    ret = g_DispDefault->GetBuffer(&g_tDispBuff);
    if (ret)
    {
        printf("GetBuffer err\n");
        return -1;
    }
​
    line_width  = g_tDispBuff.iXres * g_tDispBuff.iBpp/8;
    pixel_width = g_tDispBuff.iBpp/8;
​
    return 0;
}
​
// 获取显示缓存
PDispBuff GetDisplayBuffer(void)
{
    return &g_tDispBuff;
}
​
// 将刷新区域
int FlushDisplayRegion(PRegion ptRegion, PDispBuff ptDispBuff)
{
    return g_DispDefault->FlushRegion(ptRegion, ptDispBuff);
}
​
// 对framebuffer进行初始化 也可扩展对各种显示系统进行初始化(web)
void DisplayInit(void)
{
    extern void FramebufferInit(void);
    FramebufferInit();
}
 

2.3 framebuffer的实现

framebuffer.c:该类主要对具体进行初始化以便上层对可以直接调用封装好的函数

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <disp_manager.h>
​
static int fd_fb;
static struct fb_var_screeninfo var;    /* Current var */
static int screen_size;
static unsigned char *fb_base;
static unsigned int line_width;
static unsigned int pixel_width;
​
// 设备初始化
static int FbDeviceInit(void)
{
    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)) //对触摸屏参数获取并存入var
    {
        printf("can't get var\n");
        return -1;
    }
​
    line_width  = var.xres * var.bits_per_pixel / 8; //一行所占像素大小
    pixel_width = var.bits_per_pixel / 8; //一个点所占像素大小
    screen_size = var.xres * var.yres * var.bits_per_pixel / 8; //整个屏幕所占像素大小
    // 将整个屏幕进行映射获取缓存区基地址
    fb_base = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
    if (fb_base == (unsigned char *)-1)
    {
        printf("can't mmap\n");
        return -1;
    }
    return 0;
}
​
// 释放资源
static int FbDeviceExit(void)
{
    munmap(fb_base, screen_size);
    close(fd_fb);
    return 0;
}
​
/* 可以返回LCD的framebuffer, 以后上层APP可以直接操作LCD, 可以不用FbFlushRegion
 * 也可以malloc返回一块无关的buffer, 要使用FbFlushRegion
 */
static int FbGetBuffer(PDispBuff ptDispBuff)
{
    ptDispBuff->iXres = var.xres;
    ptDispBuff->iYres = var.yres;
    ptDispBuff->iBpp  = var.bits_per_pixel;
    ptDispBuff->buff  = (char *)fb_base; //基地址
    return 0;
}
// 什么都不做
static int FbFlushRegion(PRegion ptRegion, PDispBuff ptDispBuff)
{
    return 0;
}
// 对设备抽象的实现
static DispOpr g_tFramebufferOpr = {
    .name        = "fb",
    .DeviceInit  = FbDeviceInit,
    .DeviceExit  = FbDeviceExit,
    .GetBuffer   = FbGetBuffer,
    .FlushRegion = FbFlushRegion,
};
// 初始化即加入链表中
void FramebufferInit(void)
{
    RegisterDisplay(&g_tFramebufferOpr);
}

2.4 显示系统的单元测试

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <disp_manager.h>
​
#define FONTDATAMAX 4096
​
static const unsigned char fontdata_8x16[FONTDATAMAX] = {
​
    /* 0 0x00 '^@' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
​
    /* 1 0x01 '^A' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x7e, /* 01111110 */
    0x81, /* 10000001 */
    0xa5, /* 10100101 */
    0x81, /* 10000001 */
    0x81, /* 10000001 */
    0xbd, /* 10111101 */
    0x99, /* 10011001 */
    0x81, /* 10000001 */
    0x81, /* 10000001 */
    0x7e, /* 01111110 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
​
    ... ...
    以下省略
};
​
/**********************************************************************
 * 函数名称: lcd_put_ascii
 * 功能描述: 在LCD指定位置上显示一个8*16的字符
 * 输入参数: x坐标,y坐标,ascii码
 * 输出参数: 无
 * 返 回 值: 无
 * 修改日期        版本号     修改人        修改内容
 * -----------------------------------------------
 * 2020/05/12        V1.0     zh(angenao)         创建
 ***********************************************************************/ 
void lcd_put_ascii(int x, int y, unsigned char c)
{
    unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];
    int i, b;
    unsigned char byte;
​
    for (i = 0; i < 16; i++)
    {
        byte = dots[i];
        for (b = 7; b >= 0; b--)
        {
            if (byte & (1<<b))
            {
                /* show */
                PutPixel(x+7-b, y+i, 0xffffff); /* 白 */
            }
            else
            {
                /* hide */
                PutPixel(x+7-b, y+i, 0); /* 黑 */
            }
        }
    }
}
​
int main(int argc, char **argv)
{
    Region region;
    PDispBuff ptBuffer;
    DisplayInit(); //显示设备初始化
    SelectDefaultDisplay("fb"); //选择设备
    InitDefaultDisplay(); //初始化设备
    
    lcd_put_ascii(101, 100, 'A'); /*在屏幕中间显示8*16的字母A*/
    
    //显示区域
    region.iLeftUpx = 100;
    region.iLeftUpY = 100;
    region.iWidth = 8;
    region.iHeigh = 16;
    // 获取参数的大小
    ptBuffer = GetDisplayBuffer();
    FlushDisplayRegion(&region,ptBuffer);//刷入
    return 0;   
}

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值