在CodeBlocks搭建SDL2工程构建TFT彩屏模拟器虚拟TFT彩屏幕显示

在CodeBlocks搭建SDL2工程构建TFT彩屏模拟器虚拟TFT彩屏幕显示

参考文章


源码下载地址

在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;
}

九、测试效果


相关推荐
AL流云。5 分钟前
【CPP_STL篇】总结可遍历STL所有容器的迭代器(反向迭代器的模拟+实现)
windows·迭代器·stl
蓝裕安16 分钟前
适配器模式(类适配器,对象适配器)
开发语言·c#
玉面小君23 分钟前
C# 设计模式(结构型模式):适配器模式
设计模式·c#·适配器模式
蓑衣客VS索尼克1 小时前
嵌入式硬件设计的基本流程
嵌入式硬件
晨之清风1 小时前
Windows通过X11转发显示远程Linux上的图形界面
linux·运维·windows·x11转发
wit_yuan1 小时前
openbmc sdk09.03 适配(一)
linux·服务器·嵌入式硬件
GCSXP3 小时前
PT8026 六触控六输出IC
单片机·嵌入式硬件
aloneboyooo7 小时前
SPI通信-(STM32)
stm32·单片机·嵌入式硬件
秋风&萧瑟8 小时前
【数据结构】双向循环链表的使用
数据结构·windows·链表
爱学电子的刻刻帝9 小时前
STM32传感器系列:GPS定位模块
stm32·单片机·嵌入式硬件·gps