在CodeBlocks搭建SDL2工程构建TFT彩屏模拟器虚拟TFT彩屏幕显示
- 参考文章
- 源码下载地址
- 一、SDL2的创建、初始化、退出
- 二、系统基本Tick、彩屏刷新、按键事件
- 三、彩屏获取与设置颜色
- 四、彩屏填充颜色及清屏
- 五、彩屏显示中文和英文字符串
- 六、彩屏显示数字
- 七、彩屏初始化
- 八、主函数测试
- 九、测试效果
参考文章
- 在CodeBlocks下搭建SDL2开发工程
- 在CodeBlocks搭建SDL2工程OLED液晶模拟器虚拟OLED单色液晶(128x64)
源码下载地址
在CodeBlocks搭建SDL2工程构建TFT彩屏模拟器虚拟TFT彩屏幕显示
一、SDL2的创建、初始化、退出
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、彩屏刷新、按键事件
/* 系统基本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;}}
}
三、彩屏获取与设置颜色
/* 设置颜色 */
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]);
}
四、彩屏填充颜色及清屏
/* 填充矩形(单色) */
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);}}
}
五、彩屏显示中文和英文字符串
/* 获取字符数据源地址 */
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;}
}
六、彩屏显示数字
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);}
}
七、彩屏初始化
/* 初始化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);
}
八、主函数测试
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;
}
九、测试效果