在CodeBlocks搭建SDL2工程构建TFT彩屏模拟器虚拟TFT彩屏幕显示
- 参考文章
- 源码下载地址
- 一、SDL2的创建、初始化、退出
- 二、系统基本Tick、彩屏刷新、按键事件
- 三、彩屏获取与设置颜色
- 四、彩屏填充颜色及清屏
- 五、彩屏显示中文和英文字符串
- 六、彩屏显示数字
- 七、彩屏初始化
- 八、主函数测试
- 九、测试效果
参考文章
源码下载地址
在CodeBlocks搭建SDL2工程构建TFT彩屏模拟器虚拟TFT彩屏幕显示
一、SDL2的创建、初始化、退出
c
typedef struct
{
SDL_Window * MainWindow; /* 窗口 */
SDL_Renderer * MainRender; /* 渲染器 */
SDL_Texture * MainTexture; /* 纹理 */
u8 ExitWindow; /* 退出窗口 */
}AppGlobal_TypeDef, * AppGlobal_TypeDef_t;
static AppGlobal_TypeDef AppSystem = {0};
AppGlobal_TypeDef * pAppSystem = &AppSystem;
/* 初始化SDL */
static u8 ubInit_SDL2(void)
{
/* 初始化SDL */
if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0)
{
SDL_Log("SDL Init Fail......%s\r\n", SDL_GetError());
return 1;
}
/* 创建窗口 */
AppSystem.MainWindow = SDL_CreateWindow("Virtual TFT SDL2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_PHY_WIDTH, WINDOW_PHY_HEIGHT, SDL_WINDOW_SHOWN);
if (AppSystem.MainWindow == NULL)
{
SDL_Log("SDL Create Window Fail......%s\r\n", SDL_GetError());
return 2;
}
/* 创建渲染器 */
AppSystem.MainRender = SDL_CreateRenderer(AppSystem.MainWindow, -1, SDL_RENDERER_ACCELERATED);
if (AppSystem.MainRender == NULL)
{
SDL_Log("SDL Create Renderer Fail......%s", SDL_GetError());
return 3;
}
/* 创建纹理 */
AppSystem.MainTexture = SDL_CreateTexture(AppSystem.MainRender, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, TFT_LCD_PHY_XWIDTH, TFT_LCD_PHY_YHEIGHT);
if (AppSystem.MainTexture == NULL)
{
SDL_Log("SDL Create Texture Fail......%s", SDL_GetError());
return 4;
}
/* 设置纹理模式 */
SDL_SetTextureBlendMode(AppSystem.MainTexture, SDL_BLENDMODE_BLEND);
memset(TFT_LCD_DIS_MEMORY, 0x99, TFT_LCD_PHY_XWIDTH * TFT_LCD_PHY_YHEIGHT * sizeof(u32));
SDL_UpdateTexture(AppSystem.MainTexture, NULL, TFT_LCD_DIS_MEMORY, TFT_LCD_PHY_XWIDTH * sizeof(u32));
SDL_RenderClear(AppSystem.MainRender);
SDL_RenderCopy(AppSystem.MainRender, AppSystem.MainTexture, NULL, NULL);
SDL_RenderPresent(AppSystem.MainRender);
return 0;
}
/* 退出SDL */
static void vQuit_SDL2(void)
{
SDL_Log("Complier Date: %s %s %d\r\n", __DATE__, __TIME__, ulSuperTimer_GetTick());
/* 销毁纹理 */
if (AppSystem.MainTexture != NULL) SDL_DestroyTexture(AppSystem.MainTexture);
/* 销毁渲染器 */
if (AppSystem.MainRender != NULL) SDL_DestroyRenderer(AppSystem.MainRender);
/* 销毁窗口 */
if (AppSystem.MainWindow != NULL) SDL_DestroyWindow(AppSystem.MainWindow);
/* 退出SDL */
SDL_Quit();
}
二、系统基本Tick、彩屏刷新、按键事件
c
/* 系统基本Tick */
static void vSystem_BasicTick(void)
{
static Uint64 oldTick = 0;
Uint64 curTick = SDL_GetTicks64();
if (oldTick == curTick) return;
vSuperTimer_IncTick((u16)(curTick - oldTick));
oldTick = curTick;
}
/* 屏幕刷新+按键事件处理 */
static void vRefresh_KeyEvent_Handler(void)
{
static Uint64 oldTick = 0;
Uint64 curTick = SDL_GetTicks64();
SDL_Event event = {0};
if ((curTick - oldTick) >= 20)
{
SDL_UpdateTexture(AppSystem.MainTexture, NULL, TFT_LCD_DIS_MEMORY, TFT_LCD_PHY_XWIDTH * sizeof(u32));
SDL_RenderClear(AppSystem.MainRender);
SDL_RenderCopy(AppSystem.MainRender, AppSystem.MainTexture, NULL, NULL);
SDL_RenderPresent(AppSystem.MainRender);
oldTick = curTick;
}
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT: AppSystem.ExitWindow = EXIT_WINDOW_TYPE_QUIT; break;
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym)
{
case SDLK_UP: SDL_Log("SDLK_UP......\r\n"); break;
case SDLK_DOWN: SDL_Log("SDLK_DOWN......\r\n"); break;
case SDLK_LEFT: SDL_Log("SDLK_LEFT......\r\n"); break;
case SDLK_RIGHT: SDL_Log("SDLK_RIGHT......\r\n"); break;
default: break;
}
}
break;
default: break;
}
}
}
三、彩屏获取与设置颜色
c
/* 设置颜色 */
void vTFT_LCD_SetColor(u32 x, u32 y, ColorType color)
{
/* 越界 */
if (x > (AppDevTFT.xWidth - 1)) return;
if (y > (AppDevTFT.yHeight - 1)) return;
AppDevTFT.pDisMem[AppDevTFT.xWidth * y + x] = 0xFF000000 | DEV_RGB(color);
}
/* 获取颜色 */
ColorType xTFT_LCD_GetColor(u32 x, u32 y)
{
/* 越界 */
if (x > (AppDevTFT.xWidth - 1)) return 0;
if (y > (AppDevTFT.yHeight - 1)) return 0;
return RGB_DEV(AppDevTFT.pDisMem[AppDevTFT.xWidth * y + x]);
}
四、彩屏填充颜色及清屏
c
/* 填充矩形(单色) */
void vTFT_LCD_FillRect_SinColor(u32 x1, u32 y1, u32 x2, u32 y2, ColorType color)
{
u32 x = 0, y = 0;
/* 越界 */
if (x1 > (AppDevTFT.xWidth - 1)) return;
if (y1 > (AppDevTFT.yHeight - 1)) return;
/* 最大范围 */
if (x2 > (AppDevTFT.xWidth - 1)) x2 = (AppDevTFT.xWidth - 1);
if (y2 > (AppDevTFT.yHeight - 1)) y2 = (AppDevTFT.yHeight - 1);
/* 填充颜色 */
for (x = x1; x <= x2; x++)
{
for (y = y1; y <= y2; ++y)
{
AppDevTFT.pDisMem[AppDevTFT.xWidth * y + x] = 0xFF000000 | DEV_RGB(color);
}
}
}
/* 填充矩形(多色) */
void vTFT_LCD_FillRect_MultColor(u32 x1, u32 y1, u32 x2, u32 y2, ColorType * pColor)
{
u32 x = 0, y = 0, ex = 0, ey = 0;
/* 越界 */
if (x1 > (AppDevTFT.xWidth - 1)) return;
if (y1 > (AppDevTFT.yHeight - 1)) return;
/* 最大范围 */
ex = (x2 > (AppDevTFT.xWidth - 1)) ? (AppDevTFT.xWidth - 1) : x2;
ey = (y2 > (AppDevTFT.yHeight - 1)) ? (AppDevTFT.yHeight - 1) : y2;
for (y = y1; y <= ey; y++)
{
for (x = x1; x <= ex; ++x)
{
AppDevTFT.pDisMem[AppDevTFT.xWidth * y + x] = 0xFF000000 | DEV_RGB(*pColor);
}
pColor += (x2 - ex);
}
}
/* 清屏幕 */
void vTFT_LCD_ClearScreen(ColorType color)
{
u32 x = 0, y = 0;
for (x = 0; x <= (AppDevTFT.xWidth - 1); x++)
{
for (y = 0; y <= (AppDevTFT.yHeight - 1); ++y)
{
AppDevTFT.pDisMem[AppDevTFT.xWidth * y + x] = 0xFF000000 | DEV_RGB(color);
}
}
}
五、彩屏显示中文和英文字符串
c
/* 获取字符数据源地址 */
static void vGet_CharSrc(u8 chr, u8 charSize, u8 ** pSrc)
{
switch (charSize)
{
case ASCII_FONT_TYPE_1206 : *pSrc = (u8 *)(&ASCII_FONT_1206[chr - ' ']); break;
case ASCII_FONT_TYPE_1608 : *pSrc = (u8 *)(&ASCII_FONT_1608[chr - ' ']); break;
case ASCII_FONT_TYPE_2412 : *pSrc = (u8 *)(&ASCII_FONT_2412[chr - ' ']); break;
default: *pSrc = NULL; break;
}
}
/* 显示字符 */
static void vTFT_LCD_DisplayChar(u32 x, u32 y, u8 chr, u8 charSize, ColorType backColor, ColorType foreColor)
{
ColorType color = foreColor;
u8 charByte = 0, k = 0, i = 0;
u8 dat = 0, * pSrcDat = NULL;
u32 y0 = y;
//获取字符数据源地址
vGet_CharSrc(chr, charSize, &pSrcDat);
if (pSrcDat == NULL) return;
// 字符点阵占用字节数
charByte = ((charSize >> 3) + ((charSize & 0x07) ? 1 : 0)) * (charSize >> 1);
// 遍历字符点阵数据
for(k = 0; k < charByte; ++k)
{
dat = pSrcDat[k];
for(i = 0; i < 8; ++i)
{
// 显示有效范围
if ((x < AppDevTFT.xWidth) && (y < AppDevTFT.yHeight))
{
//低位在前
if ((dat >> i) & 0x01) color = foreColor;
else color = backColor;
vTFT_LCD_SetColor(x, y, color);
}
y++;// 纵坐标自加
if (XABS2(y , y0) >= charSize)//纵坐标偏移量等于字符点阵高度
{
y = y0;
x++;
break;
}
}
}
}
/* 显示字符串 */
void vTFT_LCD_DisplayString(u32 x, u32 y, u8 * pStr, u8 strSize, ColorType backColor, ColorType foreColor)
{
//显示ASCII常规字符
while ((*pStr >= ' ') && (*pStr <= '~'))
{
/* 剩余的横纵小于字体宽度 换行显示 */
if ((x + (strSize >> 1)) >= AppDevTFT.xWidth)
{
y += strSize;
x = 0;
}
/* 剩余纵轴小于字体高度 */
// if ((y + strSize) >= AppDevTFT.yHeight)
if (y >= AppDevTFT.yHeight)
{
return;
}
vTFT_LCD_DisplayChar(x, y, *pStr, strSize, backColor, foreColor);
x += (strSize >> 1);
pStr++;
}
}
/* 显示中文字符 */
static void vTFT_LCD_Display_ChineseChar(u32 x, u32 y, u32 xWidth, u32 yHeight, const u8 * pData, ColorType backColor, ColorType foreColor)
{
ColorType color = foreColor;
u16 k = 0, j = 0, n = 0, i = 0;
u32 y0 = y, yMax = 0;
u8 dat = 0;
yMax = (yHeight >> 3) + ((yHeight & 0x07) ? 1 : 0); //高度
y0 = y; //原始纵坐标
for(k = 0; k < xWidth; k++)
{
for(j = 0; j < yMax; j++)
{
dat = pData[n++];
for(i = 0; i < 8; i++)
{
if ((y < AppDevTFT.yHeight) && (x < AppDevTFT.xWidth))
{
//低位在前
if ((dat >> i) & 0x01) color = foreColor;
else color = backColor;
vTFT_LCD_SetColor(x, y, color);
}
y++;//纵坐标处理
if (XABS2(y , y0) >= yHeight)
{
y = y0;
x++;//横坐标处理
break;
}
}
}
}
}
/* 显示中文字符串 */
void vTFT_LCD_Display_ChineseString(u32 x, u32 y, u32 xWidth, u32 yHeight, u8 * pData, u16 num, ColorType backColor, ColorType foreColor)
{
u16 i = 0;
u8 charByte = 0;
u8 * pMem = pData;
/* 异常 */
if ((!num) || (pData == NULL)) return;
// 字符点阵占用字节数
charByte = ((yHeight >> 3) + ((yHeight & 0x07) ? 1 : 0)) * xWidth;
for (i = 0; i < num; ++i)
{
/* 剩余的横纵小于字体宽度 换行显示 */
if ((x + xWidth) > AppDevTFT.xWidth)
{
y += yHeight;
x = 0;
}
/* 剩余纵轴小于字体高度 */
// if ((y + yHeight) >= AppDevTFT.yHeight)
if (y >= AppDevTFT.yHeight)
{
return;
}
pMem = pData + (charByte * i);
vTFT_LCD_Display_ChineseChar(x, y, xWidth, yHeight, pMem, backColor, foreColor);
x += xWidth;
}
}
六、彩屏显示数字
c
static u8 ubGet_EveryBit_Digit(u8 * pDat, u32 num)
{
u8 i = 0;
while (1)
{
pDat[i++] = num % 10;
num = num / 10;
if (!num)
{
break;
}
}
u8 temp = 0;
for (num = 0; num < (i >> 1); ++num)
{
temp = pDat[num];
pDat[num] = pDat[i - num - 1];
pDat[i - num - 1] = temp;
}
return i;
}
/* 显示数字 */
void vTFT_LCD_DisplayNumber(u32 x, u32 y, u32 num, u8 charSize, ColorType backColor, ColorType foreColor)
{
u8 mem[20] = {0};
u8 chr = 0, i = 0, len = ubGet_EveryBit_Digit(mem, num);
for (i = 0; i < len; ++i)
{
/* 剩余的横纵小于字体宽度 换行显示 */
if ((x + (charSize >> 1)) >= AppDevTFT.xWidth)
{
y += charSize;
x = 0;
}
/* 剩余纵轴小于字体高度 */
// if ((y + charSize) >= AppDevTFT.yHeight)
if (y >= AppDevTFT.yHeight)
{
return;
}
chr = mem[i] + 0x30;
vTFT_LCD_DisplayChar(x, y, chr, charSize, backColor, foreColor);
x += (charSize >> 1);
}
}
七、彩屏初始化
c
/* 初始化TFT */
void vTFT_Init(void)
{
AppDevTFT.xWidth = TFT_LCD_PHY_XWIDTH;
AppDevTFT.yHeight = TFT_LCD_PHY_YHEIGHT;
AppDevTFT.pDisMem = TFT_LCD_DIS_MEMORY;
AppDevTFT.BackColor = 0xDCDCDC;
AppDevTFT.ForeColor = 0xFFFFFF;
vTFT_LCD_ClearScreen(AppDevTFT.BackColor);
vTFT_LCD_DisplayString(10, 10, (const u8 *)"Compiler: ", ASCII_FONT_TYPE_1608, 0, 0x00FF00);
vTFT_LCD_DisplayString(90, 10, (const u8 *)__DATE__, ASCII_FONT_TYPE_1608, 0, 0x00FF00);
vTFT_LCD_DisplayString(178, 10, (const u8 *)" ", ASCII_FONT_TYPE_1608, 0, 0x00FF00);
vTFT_LCD_DisplayString(194, 10, (const u8 *)__TIME__, ASCII_FONT_TYPE_1608, 0, 0x00FF00);
vTFT_LCD_DisplayString(10, 50, (const u8 *)"xDemo TFT1...123ABC~!@#$%^&*()-=", ASCII_FONT_TYPE_1206, 0, 0xFFFF00);
vTFT_LCD_DisplayString(10, 70, (const u8 *)"xDemo TFT2...123ABC", ASCII_FONT_TYPE_1608, 0xFFFFFF, 0x0000FF);
vTFT_LCD_DisplayString(10, 100, (const u8 *)"xDemo TFT3...123ABC", ASCII_FONT_TYPE_2412, 0, 0xF59A23);
vTFT_LCD_Display_ChineseString(10, 140, 18, 18, (u8 *)&ChineseDemo[1], 9, 0, 0xFF0000);
vTFT_LCD_DisplayNumber(10, 200, 985, ASCII_FONT_TYPE_2412, 0xDCDCDC, 0xFF0000);
}
八、主函数测试
c
int main( int argc, char * argv[] )
{
if (ubInit_SDL2())
{
SDL_Log("Init SDL Fail......%s\r\n", SDL_GetError());
vQuit_SDL2();
return -1;
}
vTFT_Init();
xSuperTimer_Init();
AppSystem.ExitWindow = EXIT_WINDOW_TYPE_RUN;
ubSuperTimer_Start(xDemo, 1000);
while (AppSystem.ExitWindow)
{
vRefresh_KeyEvent_Handler();
vSystem_BasicTick();
vSuperTimer_RunHandler();
}
vQuit_SDL2();
return 0;
}
九、测试效果