韦东山-电子量产工具项目:UI系统

代码结构

所有代码都已通过测试跑通,其中代码结构如下:

 一、include文件夹

1.1 common.h

#ifndef _COMMON_H
#define _COMMON_H

typedef struct Region {
	int iLeftUpX;  //区域左上方的坐标
	int iLeftUpY;  //区域左下方的坐标
	int iWidth;    //区域宽度
	int iHeigh;    //区域高度
}Region, *PRegion;
 


#endif

1.2 disp_manager.h

#ifndef _DISP_MANAGER_H //防止头文件重复包含,只要右边的出现过,就不会再往下编译
#define _DISP_MANAGER_H
#include<common.h>

//区域结构体
typedef struct DispBuff {
	int iXres; 
	int iYres; 
	int iBpp;   
	char *buff;  
}DispBuff, *PDispBuff; 
//区域结构体
/*
typedef struct Region {
	int iLeftUpX;  //区域左上方的坐标
	int iLeftUpY;  //区域左下方的坐标
	int iWidth;    //区域宽度
	int iHeigh;    //区域高度
}Region, *PRegion;
*/ 
//显示设备结构体(LCD设备或者是web设备),通过调用这个结构体中的函数来实现显示功能
typedef struct DispOpr {
	char *name;   //设备名
	int (*DeviceInit)(void);//设备初始化函数
	int (*DeviceExit)(void);//设备清除
	int (*GetBuffer)(PDispBuff ptDispBuff);///用于获取lcd所需的内存空间,return内存空间的首地址
	                                       //argument1-lcd屏长度,argument2-lcd屏宽度,argument3-每一个像素点的位数。
	int (*FlushRegion)(PRegion ptRegion, PDispBuff  ptDispBuff);//刷新出argum1-按钮区域,argum2-区域数据
	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);


void DrawRegion(PRegion ptRegion, unsigned int dwColor);
void DrawTextInRegionCentral(char *name, PRegion ptRegion, unsigned int dwColor);

#endif

1.3 font_manager.h

#ifndef _FONT_MANAGER_H
#define _FONT_MANAGER_H
#include <common.h>
//描述字体位图
typedef struct FontBitMap {
	Region tRegion;
	int iCurOriginX;//当期字符基点x坐标
	int iCurOriginY;//当期字符基点y坐标
	int iNextOriginX;//下一个字符基点x坐标
	int iNextOriginY;//下一个字符基点y坐标
	unsigned char *pucBuffer;
}FontBitMap, *PFontBitMap;
//描述字库操作
typedef struct FontOpr {
	char *name;
	int (*FontInit)(char *aFineName);//字体初始化
	int (*SetFontSize)(int iFontSize);//字体大小
	int (*GetFontBitMap)(unsigned int dwCode, PFontBitMap ptFontBitMap);//获得字符位图,存到ptFontBitMap中
	struct FontOpr *ptNext;//方便支持多种字库
}FontOpr, *PFontOpr;

void RegisterFont(PFontOpr ptFontOpr);
void FontsRegister(void);
int SelectAndInitFont(char *aFontOprName, char *aFontFileName);
int SetFontSize(int iFontSize);
int GetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap);
#endif

1.4 input_manager.h

#ifndef _INPUT_MANAGER_H //防止头文件重复包含,只要右边的出现过,就不会再往下编译
#define _INPUT_MANAGER_H
#include <sys/time.h>

#define INPUT_TYPE_TOUCH 1
#define INPUT_TYPE_NET 2
/* 上报的数据格式 */
typedef struct InputEvent
{
    struct timeval tTime; //加入时间管理
 
    int iType;      //网络事件或者触摸事件类型
    int iX;         //触摸事件x坐标
    int iY;         //触摸事件y坐标
    int iPressure;  //触摸事件压力
    char str[1024]; //网络事件字符串
} InputEvent, *PInputEvent;


/* 不同的输入设备,应该模块化,使用下面的结构体表示输入设备 */
typedef struct InputDevice
{
    char *name;                                     //设备名称
    int (*GetInputEvent)(PInputEvent ptInputEvent); //获得数据
    int (*DeviceInit)(void);
    int (*DeviceExit)(void);
    struct InputDevice *ptNext; //加入链表,将多个输入设备链接到一起
} InputDevice, *PInputDevice;



#endif

1.5 ui.h

#ifndef _UI_H_
#define _UI_H_
#include<common.h>
#include<disp_manager.h>
#include<input_manager.h>


#define BUTTON_DEFAULT_COLOR 0xff0000
#define BUTTON_PRESSED_COLOR 0x00ff00
#define BUTTON_TEXT_COLOR 0x000000

struct Button;
/* 函数指针(绘制按键) */
typedef int (*ONDRAW_FUNC)(struct Button *ptButton, PDispBuff ptDispBuff);
/* 函数指针(按下按钮) */
typedef int (*ONPRESSED_FUNC)(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent);


typedef struct Button {
	char *name;								// 按键 名字
	int status;								//按键 按下状态
	Region tRegion;							// 按键的区域
	ONDRAW_FUNC OnDraw;						//一个 ONDRAW_FUNC 类型的函数指针,用于指向按钮绘制函数
	ONPRESSED_FUNC OnPressed;				//一个 ONPRESSED_FUNC 类型的函数指针,用于指向按钮按下事件处理函数
}Button, *PButton;


#endif

二、button文件夹

2.1 button.c

#include<ui.h>
#include <string.h>
#include <disp_manager.h>
static int DefaultOnDraw(struct Button *ptButton, PDispBuff ptDispBuff){

	/* 绘制底色   DrawRegion追加在disp_manager.c中 */
	DrawRegion(&ptButton->tRegion, BUTTON_DEFAULT_COLOR);		// 红色 0xff0000

	/* 居中写文字   DrawTextInRegionCentral追加在disp_manager.c中*/
	DrawTextInRegionCentral(ptButton->name, &ptButton->tRegion, BUTTON_TEXT_COLOR);		//黑色 0x000000

	/* flush to lcd/web */
	FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);

	return 0;



}
static int DefaultOnPressed(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent)
{
	unsigned int dwColor = BUTTON_DEFAULT_COLOR;	
	ptButton->status = !ptButton->status;
	if (ptButton->status)
		dwColor = BUTTON_PRESSED_COLOR;
	/* 绘制底色 */
	DrawRegion(&ptButton->tRegion, dwColor);
	/* 居中写文字 */
	DrawTextInRegionCentral(ptButton->name, &ptButton->tRegion, BUTTON_TEXT_COLOR);
	/* flush to lcd/web */
	FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);
	return 0;
}


void InitButton(PButton ptButton, char *name, PRegion ptRegion, ONDRAW_FUNC OnDraw, ONPRESSED_FUNC OnPressed)
{
	ptButton->status = 0;				//初始状态为 0 ,未按下
	ptButton->name = name;
	ptButton->tRegion = *ptRegion;			// 按钮的区域
	ptButton->OnDraw    = OnDraw ? OnDraw : DefaultOnDraw;		//若 OnDraw 为空,则执行默认绘制函数DefaultOnDraw
	ptButton->OnPressed = OnPressed ? OnPressed : DefaultOnPressed;	 //若 OnPressed 为空,则执行默认绘制函数DefaultOnPressed
}

2.2 Makefile

EXTRA_CFLAGS  :=
CFLAGS_file.o :=
obj-y +=button.o

三、display文件夹

3.1 disp_manager.c

#include "disp_manager.h"
#include "font_manager.h"
#include <stdio.h>
#include <string.h>
//管理底层lcd和web
/* display_manager.c */
static PDispOpr g_DispDevs = NULL;//设备链表表头
static PDispOpr g_DispDefault = NULL;
static DispBuff g_tDispBuff;

static unsigned int line_width;
static unsigned int pixel_width;
//绘制像素
int PutPixel(int x, int y, unsigned int dwColor)
{
	char *pen_8 = 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);
			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;
			return 0;
		}
		pTmp = pTmp->ptNext;
	}
	return -1;
}

int InitDefaultDisplay(void)
{
	int ret;
	ret = g_DispDefault->DeviceInit(); 
	/*在调用前文SelectDefaultDisplay函数后,g_DispDefault即为g_tFramebufferOpr*/
	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);
}

//文字绘制函数
void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor)
{
    int i, j, p, q;
	int x = ptFontBitMap->tRegion.iLeftUpX;
	int y = ptFontBitMap->tRegion.iLeftUpY;
    int x_max = x + ptFontBitMap->tRegion.iWidth;
    int y_max = y + ptFontBitMap->tRegion.iHeigh;
	int width = ptFontBitMap->tRegion.iWidth;
	unsigned char *buffer = ptFontBitMap->pucBuffer;

    //printf("x = %d, y = %d\n", x, y);

    for ( j = y, q = 0; j < y_max; j++, q++ )
    {
        for ( i = x, p = 0; i < x_max; i++, p++ )
        {
            if ( i < 0      || j < 0       ||
                i >= g_tDispBuff.iXres || j >= g_tDispBuff.iYres )
            continue;

            //image[j][i] |= bitmap->buffer[q * bitmap->width + p];
            if (buffer[q * width + p])
	            PutPixel(i, j, dwColor);
        }
    }
	
}

// 区域绘制函数
void DrawRegion(PRegion ptRegion, unsigned int dwColor)
{
	int x = ptRegion->iLeftUpX;
	int y = ptRegion->iLeftUpY;
	int width = ptRegion->iWidth;
	int heigh = ptRegion->iHeigh;
	int i,j;
	for (j = y; j < y + heigh; j++)
	{
		for (i = x; i < x + width; i++)
			PutPixel(i, j, dwColor);
	}
}

//文本绘制函数
void DrawTextInRegionCentral(char *name, PRegion ptRegion, unsigned int dwColor)
{
	int n = strlen(name);
	int iFontSize = ptRegion->iWidth / n / 2;
	FontBitMap tFontBitMap;
	int iOriginX, iOriginY;
	int i = 0;
	int error;

	if (iFontSize > ptRegion->iHeigh)
		iFontSize =  ptRegion->iHeigh;

	iOriginX = (ptRegion->iWidth - n * iFontSize)/2 + ptRegion->iLeftUpX;
	iOriginY = (ptRegion->iHeigh - iFontSize)/2 + iFontSize + ptRegion->iLeftUpY;

	SetFontSize(iFontSize);

	while (name[i])
	{
		/* get bitmap */
		tFontBitMap.iCurOriginX = iOriginX;
		tFontBitMap.iCurOriginY = iOriginY;
		error = GetFontBitMap(name[i], &tFontBitMap);
		if (error)
		{
			printf("SelectAndInitFont err\n");
			return;
		}
		/* draw on buffer */		
		DrawFontBitMap(&tFontBitMap, dwColor);		

		iOriginX = tFontBitMap.iNextOriginX;
		iOriginY = tFontBitMap.iNextOriginY;	
		i++;
	}
}


/* display_manager.c */
void DisplayInit(void)
{
	extern void FramebufferInit(void); /*对应framebuffer设备lcd输出*/
	FramebufferInit();
	/*WebTnit()-对应web输出未实现*/
}

3.2 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;//LCD的framebuffer地址
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))
	{
		printf("can't get var\n");
		return -1;
	}
   //var.xres x方向的分辨率
	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, char *buffer) //刷新函数
{
	return 0;
}
 


// 构建framebuffer设备结构体
static DispOpr g_tFramebufferOpr = {  
	.name        = "fb",   //设备的名字是fb
	.DeviceInit  = FbDeviceInit, //
	.DeviceExit  = FbDeviceExit, //
	.GetBuffer   = FbGetBuffer,  //获得buf空间中的数据
	.FlushRegion = FbFlushRegion, //刷新
};

void FramebufferInit(void)
{
	RegisterDisplay(&g_tFramebufferOpr);
}


3.3 Makefile

EXTRA_CFLAGS  :=
CFLAGS_file.o :=
obj-y +=disp_manager.o
obj-y +=framebuffer.o

四、freetype文件夹

4.1 font_manager.c

#include "font_manager.h"
#include <string.h>
static PFontOpr g_ptFonts = NULL;
static PFontOpr g_ptDefaulFontOpr = NULL;


void RegisterFont(PFontOpr ptFontOpr)
{
	ptFontOpr->ptNext = g_ptFonts;
	g_ptFonts = ptFontOpr;
}

void FontsRegister(void)
{
	extern void FreetypeRegister(void);
	FreetypeRegister();
}

int SelectAndInitFont(char *aFontOprName, char *aFontFileName)
{
	PFontOpr ptTmp = g_ptFonts;
	while (ptTmp)
	{
		if (strcmp(ptTmp->name, aFontOprName) == 0)
			break;
		ptTmp = ptTmp->ptNext;
	}

	if (!ptTmp)
		return -1;

	g_ptDefaulFontOpr = ptTmp;
	return ptTmp->FontInit(aFontFileName);
}

int SetFontSize(int iFontSize)
{
	return g_ptDefaulFontOpr->SetFontSize(iFontSize);
}

int GetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap)
{
	return g_ptDefaulFontOpr->GetFontBitMap(dwCode, ptFontBitMap);
}

4.2 freetype.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 <math.h>
#include <wchar.h>
#include <sys/ioctl.h>
#include "font_manager.h"
#include <ft2build.h>//freetype库中的一个头文件
#include FT_FREETYPE_H
#include FT_GLYPH_H
static FT_Face g_tFace;
static int g_iDefaultFontSize = 12;

static int FreeTypeFontInit(char *aFineName)
{
    FT_Library    library;
    int error;

    error = FT_Init_FreeType( &library );                 /* initialize library */    
	if (error)
	{
		printf("FT_Init_FreeType err\n");
		return -1;
	}
	
    error = FT_New_Face(library, aFineName, 0, &g_tFace ); /* create face object */
	if (error)
	{
		printf("FT_New_Face err\n");
		return -1;
	}

    FT_Set_Pixel_Sizes(g_tFace, g_iDefaultFontSize, 0);

	return 0;
}

static int FreeTypeSetFontSize(int iFontSize)
{
    FT_Set_Pixel_Sizes(g_tFace, iFontSize, 0);
	return 0;
}
//给编码值,得到位图
static int FreeTypeGetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap)
{
	int error;
    FT_Vector pen;
    FT_GlyphSlot slot = g_tFace->glyph;
    pen.x = ptFontBitMap->iCurOriginX * 64; /* 单位: 1/64像素 */
    pen.y = ptFontBitMap->iCurOriginY * 64; /* 单位: 1/64像素 */
	/* 转换:transformation */
	FT_Set_Transform(g_tFace, 0, &pen);//FT_Set_Transform是FreeType库中的函数
	/* 加载位图: load glyph image into the slot (erase previous one) */
	error = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER);
	if (error)
	{
		printf("FT_Load_Char error\n");
		return -1;
	}
	ptFontBitMap->pucBuffer = slot->bitmap.buffer;
	ptFontBitMap->tRegion.iLeftUpX = slot->bitmap_left;
	ptFontBitMap->tRegion.iLeftUpY = ptFontBitMap->iCurOriginY*2 - slot->bitmap_top;
	ptFontBitMap->tRegion.iWidth   = slot->bitmap.width;
	ptFontBitMap->tRegion.iHeigh   = slot->bitmap.rows;
	ptFontBitMap->iNextOriginX = ptFontBitMap->iCurOriginX + slot->advance.x / 64;
	ptFontBitMap->iNextOriginY = ptFontBitMap->iCurOriginY;

	return 0;
}
//描述字库操作及对应具体实现
static FontOpr g_tFreetypeOpr = {
	.name          = "freetype",
	.FontInit      = FreeTypeFontInit,
	.SetFontSize   = FreeTypeSetFontSize,
	.GetFontBitMap = FreeTypeGetFontBitMap,
};

void FreetypeRegister(void)
{
	RegisterFont(&g_tFreetypeOpr);
}

4.3 front_manager.c

#include "font_manager.h"
#include <string.h>
static PFontOpr g_ptFonts = NULL;
static PFontOpr g_ptDefaulFontOpr = NULL;


void RegisterFont(PFontOpr ptFontOpr)
{
	ptFontOpr->ptNext = g_ptFonts;
	g_ptFonts = ptFontOpr;
}

void FontsRegister(void)
{
	extern void FreetypeRegister(void);
	FreetypeRegister();
}

int SelectAndInitFont(char *aFontOprName, char *aFontFileName)
{
	PFontOpr ptTmp = g_ptFonts;
	while (ptTmp)
	{
		if (strcmp(ptTmp->name, aFontOprName) == 0)
			break;
		ptTmp = ptTmp->ptNext;
	}

	if (!ptTmp)
		return -1;

	g_ptDefaulFontOpr = ptTmp;
	return ptTmp->FontInit(aFontFileName);
}

int SetFontSize(int iFontSize)
{
	return g_ptDefaulFontOpr->SetFontSize(iFontSize);
}

int GetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap)
{
	return g_ptDefaulFontOpr->GetFontBitMap(dwCode, ptFontBitMap);
}

4.4 Makefile

EXTRA_CFLAGS  :=
CFLAGS_file.o :=
obj-y +=freetype.o
obj-y +=font_manager.o

五、uniotest文件夹

5.1 ui_test.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 <stdlib.h>
#include <disp_manager.h>

#include <font_manager.h>
#include <ui.h> /*包含必要头文件*/

int main(int argc, char **argv)
{
	PDispBuff ptBuffer;
	int error;
	Button tButton;
	Region tRegion;

	if (argc != 2)
	{
		printf("Usage: %s <font_size>\n", argv[0]); //打印用法
		return -1;
	}
		
	DisplayInit();  //显示系统初始化
	SelectDefaultDisplay("fb"); //选择lcd设备显示
	InitDefaultDisplay(); //初始化lcd设备显示
	ptBuffer = GetDisplayBuffer();//获取内存
	FontsRegister(); //字体注册
	error = SelectAndInitFont("freetype", argv[1]);//字体大小设置
	if (error)
	{
		printf("SelectAndInitFont err\n");
		return -1;
	}
    /*指定按键形状、位置信息*/
	tRegion.iLeftUpX = 200; 
	tRegion.iLeftUpY = 200;
	tRegion.iWidth   = 600;
	tRegion.iHeigh   = 200;

	InitButton(&tButton,"Alexius_test", &tRegion, NULL, NULL); //按键初始化
	tButton.OnDraw(&tButton, ptBuffer); //绘制案件即显示红色按钮与对应按键名
	while (1) //按键按下颜色反转
	{
		tButton.OnPressed(&tButton, ptBuffer, NULL); 
		sleep(2);
	}
	
	return 0;	
}

5.2 Makefile

EXTRA_CFLAGS  :=
CFLAGS_file.o :=
obj-y +=ui_test.o

六、顶层Makefile及Makefile.build

6.1 Makefile

#指定交叉编译工具链
COSS_COMPLE ?=arm-linux-gnueabihf-
AS	= $(COSS_COMPLE)as
LD	= $(COSS_COMPLE)ld
CC	= $(COSS_COMPLE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm



STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump

# export导出的变量是给子目录下的Makefile使用的
export AS LD CC CPP AR NM 
export STRIP OBJCOPY OBJDUMP

# 编译器在编译时的参数设置
CFLAGS := -Wall -O2 -g -DDEBUG
# 添加头文件路径,不添加的话include目录下的头文件编译时找不到
CFLAGS += -I $(shell pwd)/include -I/home/alexius/Downloads/freetype-2.10.2/install/include/freetype2

# 链接器的链接参数设置,链接库
LDFLAGS := -L/home/alexius/Downloads/freetype-2.10.2/install/lib -lfreetype
#-L/home/alexius/Downloads/tslib-1.21/install/lib -lts -lpthread	#触摸屏库链接

export CFLAGS LDFLAGS

TOPDIR := $(shell pwd)
export TOPDIR

# 定义将来编译生成的可执行程序的名字
TARGET := ui_test

# 添加项目中所有用到的源文件,有顶层目录下的.c文件,和子文件夹
# 添加顶层目录下的.c文件
#obj-y += main.o

# 添加顶层目录下的子文件夹(注意目录名后面加一个/)
#obj-y += main.o
obj-y += button/
obj-y += uniotest/
obj-y += display/
obj-y += freetype/

# 第一个目标
all : start_recursive_build $(TARGET)
	@echo $(TARGET) has been built!
    
# 处理第一个依赖,**转到 Makefile.build 执行**
start_recursive_build:
	make -C ./ -f $(TOPDIR)/Makefile.build
    
# 处理最终目标,把前期处理得出的 built-in.o 用上
$(TARGET) : built-in.o
	$(CC) -o $(TARGET) built-in.o $(LDFLAGS)
    
# 清理
clean:
	rm -f $(shell find -name "*.o")
	rm -f $(TARGET)
    
# 彻底清理
distclean:
	rm -f $(shell find -name "*.o")
	rm -f $(shell find -name "*.d")
	rm -f $(TARGET)

6.2 Makefile.build


# 将__build定义为伪目标
PHONY := __build
__build:

# 这里初值为空,下面引入Makefile文件后会被覆盖
obj-y :=
subdir-y :=

# 包含同级目录的Makefile
include Makefile

# 从obj-y变量中,将"/"结尾的字符串提取出来,也就是包含的子文件夹目录
__subdir-y	:= $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y	+= $(__subdir-y)

# 将subdir-y变量中的字符串依次赋值给f变量,形成新的$(f)/built-in.o字符串
subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)

# 筛选出obj-y中不以"/"结尾的字符串,也就是普通文件,一般是.o结尾
cur_objs := $(filter-out %/, $(obj-y))

# 为每个.o文件生成.d文件
# 注意.$(f).d是隐藏文件,需要ls -a查看
dep_files := $(foreach f,$(cur_objs),.$(f).d)
dep_files := $(wildcard $(dep_files))

# 如果.d文件不是空,则将.d文件都包含进来
ifneq ($(dep_files),)
  include $(dep_files)
endif


PHONY += $(subdir-y)

# __build是Makefile的目标

__build : $(subdir-y) built-in.o

# 依次跳转到子目录中,执行Makefile.build文件
$(subdir-y):
	make -C $@ -f $(TOPDIR)/Makefile.build

# 生成当前目录的built-in.o,依赖当前目录的.o文件和子目录下的built-in.o文件
built-in.o : $(cur_objs) $(subdir_objs)
	$(LD) -r -o $@ $^

# dep_file变量是用来生成.d文件的
dep_file = .$@.d

# Makefile中的规则,把.c文件编译成.o文件
%.o : %.c
	$(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<

# 重新定义 .PHONY的依赖
.PHONY : $(PHONY)

七、编译及结果

7.1 编译

 7.2 测试结果

    将可执行文件ui_test及字库.ttc文件放入开发板下

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/79893.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

安防监控视频云存储EasyCVR平台H.265转码功能更新:新增分辨率配置

安防视频集中存储EasyCVR视频监控综合管理平台可以根据不同的场景需求&#xff0c;让平台在内网、专网、VPN、广域网、互联网等各种环境下进行音视频的采集、接入与多端分发。在视频能力上&#xff0c;视频云存储平台EasyCVR可实现视频实时直播、云端录像、视频云存储、视频存储…

从零做软件开发项目系列之一综论软件项目开发

1 引言 有一个三个泥瓦匠的故事。 三个泥瓦匠在砌墙&#xff0c;一个人走过来&#xff0c;问他们在干什么。   第一个泥瓦匠没好气地说&#xff0c;你没看见吗&#xff1f;我在辛苦地砌墙呢。   第二个回答&#xff0c;我们正在建一座高楼。   第三个则洋溢着喜悦说&…

CSS:filter滤镜 详解(用法 + 代码 + 例子 + 效果)

文章目录 filter 滤镜blur() 模糊度例子 渐变光晕 brightness() 元素亮度contrast() 对比度grayscale() 元素灰度hue-rorate() 色相opacity() 透明度invert() 反转颜色saturate() 饱和度 backdrop-filter 蒙版&#xff0c;滤镜例子 卷轴展开 filter 滤镜 动图为效果添加前后对…

开源了一套基于springboot+vue+uniapp的商城,包含分类、sku、商户管理、分销、会员、适合企业或个人二次开发

RuoYi-Mall-JAVA商城-电商系统简介 开源了一套基于若依框架&#xff0c;SringBoot2MybatisPlusSpringSecurityjwtredisVueUniapp的前后端分离的商城系统&#xff0c; 包含分类、sku、商户管理、分销、会员、适合企业或个人二次开发。 前端采用Vue、Element UI&#xff08;ant…

视频汇聚/视频云存储/视频监控管理平台EasyCVR添加萤石云设备详细操作来啦!

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

贝锐蒲公英助力电子公交站牌联网远程运维,打造智慧出行新趋势

在现代城市公共交通系统中&#xff0c;我们随处可见电子公交站牌的身影。作为公共交通服务的核心之一&#xff0c;电子公交站牌的稳定运行至关重要&#xff0c;公交站台的实时公交状况、公共广告信息&#xff0c;是市民候车时关注的焦点。 某交通科技公司在承接某市智能电子站牌…

MR300C工业无线WiFi图传模块 内窥镜机器人图像传输有线无线的两种方式

MR300C无线WiFi图传模使用方法工业机器人图像高清传输 ⚫ MR300C图传模块基于MIPS处理器实现&#xff0c;电脑/手机连接模块的WIFI热点或网口即可查看视频流 ⚫ 模块的USB 2.0 Host接口&#xff0c;可接入USB uvc摄像头/内窥镜默认输出的视频格式必须是MJPG ⚫ 模块支持接入摄…

Python绘图系统6:自定义坐标列表控件

文章目录 自定义坐标列表控件显示和隐藏加载按钮坐标设置控件的显示和隐藏源代码 Python绘图系统&#xff1a; 基础&#xff1a;将matplotlib嵌入到tkinter &#x1f4c8;简单的绘图系统 &#x1f4c8;数据导入&#x1f4c8;三维绘图系统自定义控件&#xff1a;坐标设置控件&a…

【解决】Kafka Exception thrown when sending a message with key=‘null‘ 异常

问题原因&#xff1a; 如下图&#xff0c;kafka 中配置的是监听域名的方式&#xff0c;但程序里使用的是 ip:port 的连接方式。 解决办法&#xff1a; kafka 中配置的是域名的方式&#xff0c;程序里也相应配置成 域名:port 的方式&#xff08;注意&#xff1a;本地h…

计算机网络的性能指标

计算机网络的性能指标 1. 速率 速率是指数据在网络中传送的速度&#xff0c;通常用比特率或数据率来表示&#xff0c;单位是b/s&#xff0c;或bit/s&#xff0c;即比特每秒&#xff0c;或者bps(bit per second)。 速率单位&#xff1a;1 Ybps 10^24 bps(尧), 1 Zbps 10^21…

【面试八股文】每日一题:谈谈你对IO的理解

谈谈你对IO的理解 每日一题-Java核心-谈谈你对对IO的理解【面试八股文】 1.Java基础知识 Java IO&#xff08;Input/Output&#xff09;是Java编程语言中用于处理输入和输出的一组类和接口。它提供了一种在Java程序中读取和写入数据的方法。 Java IO包括两个主要的部分&#x…

【100天精通python】Day39:GUI界面编程_PyQt 从入门到实战(下)_图形绘制和动画效果,数据可视化,刷新交互

目录 专栏导读 6 图形绘制与动画效果 6.1 绘制基本图形、文本和图片 6.2 实现动画效果和过渡效果 7 数据可视化 7.1 使用 Matplotlib绘制图表 7.2 使用PyQtGraph绘制图表 7.3 数据的实时刷新和交互操作 7.3.1 数据的实时刷新 7.3.2 交互操作 7.4 自定义数据可视化…

LVS-DR模式以及其中ARP问题

目录 LVS_DR LVS_DR数据包流向分析 LVS-DR中ARP问题 问题一 问题二 解决ARP的两个问题的设置方法 LVS-DR特点 LVS-DR优缺点 优点 缺点 LVS-DR集群构建 1.配置负载调度器 2.部署共享存储 3.配置节点服务器 4.测试 LVS 群集 LVS_DR LVS_DR数据包流向分析 客户端…

【报错】git push --set-upstream origin XXXX重名

您在尝试将分支推送到远程仓库时遇到了错误。错误信息表明&#xff0c;由于已经存在名为 refs/heads/xingfan/demo 的文件夹&#xff0c;Git 无法创建分支 refs/heads/xingfan。 要解决此问题&#xff0c;您可以尝试重命名本地分支&#xff0c;然后将其推送到远程仓库。以下是…

C++之std::pair<uint64_t, size_t>应用实例(一百七十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

【电商领域】Axure在线购物商城小程序原型图,品牌自营垂直电商APP原型

作品概况 页面数量&#xff1a;共 60 页 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;网上商城、品牌自营商城、商城模块插件 作品申明&#xff1a;页面内容仅用于功能演示&#xff0c;无实际功能 作品特色 本作品为品牌自营网上商城…

js fetch请求中断的几种方式

1、通过AbortController 这是官方标准手段&#xff0c;真正意义的阻止请求&#xff08;不支持ie&#xff09; 后端接口设置的两秒返回数据 function myFetch() {const controller new AbortController();const signal controller.signal;fetch(http://localhost:3000/aaa/…

京东门详一码多端探索与实践 | 京东云技术团队

本文主要讲述京东门详业务在支撑过程中遇到的困境&#xff0c;面对问题我们在效率提升、质量保障等方向的探索和实践&#xff0c;在此将实践过程中问题解决的思路和方案与大家一起分享&#xff0c;也希望能给大家带来一些新的启发 一、背景 1.1、京东门详介绍 1.1.1、京东门…

【项目实践】基于LSTM的一维数据扩展与预测

基于LSTM的一维数据拟合扩展 一、引(fei)言(hua) 我在做Sri Lanka生态系统服务价值计算时&#xff0c;中间遇到了一点小问题。从世界粮农组织(FAO)上获得Sri Lanka主要农作物产量和价格数据时&#xff0c;其中的主要作物Sorghum仅有2001-2006年的数据&#xff0c;而Millet只有…

《凤凰架构》第二章——访问远程服务

前言 这章挺难的&#xff0c;感觉离我比较远&#xff0c;不太好懂&#xff0c;简单记录吧。 这章主要讲访问远程服务&#xff0c;主要对比了RPC和REST的区别&#xff0c;可以结合知乎上的文章《既然有 HTTP 请求&#xff0c;为什么还要用 RPC 调用&#xff1f;》 这篇文章进行…