你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32U3评测】4、SPI屏移植TouchGFX

[复制链接]
网络孤客 发布时间:2025-6-13 15:30

此前一直是使用官方的探索板,在TouchGFX有完整驱动,开发起来非常方便。这次我来学习Nucleo板与个人SPI屏组合下如何移植TouchGFX。

一、建立工程

1、设置SPI参数

在移植TouchGFX前要测试自己的屏能支持多高的SPI传输速率,并尽量速度设置高些。我的屏只能到24Mbits/s。当然还可以通过细调时钟,进一步提高传输速度。

屏幕截图2025-06-13125143.png

屏幕截图2025-06-13125117.png

2、配置TouchGFX

在Middleware and Software Packs中选择X-CUBE-TOUCHGFX

屏幕截图2025-06-10065413.png

根据屏和屏驱动数据手册,设置屏参数

屏幕截图2025-06-13140622.png

TouchGFX还需要CRC支持,把它也激活,默认配置就行了。

屏幕截图2025-06-13141020.png

3、心跳时钟设置

每帧至少需要传输位数:320(宽) x 240(高) x 16(bits) = 1228800bits

每帧需要传输时间:1228800 / 24(Mbit/s) = 0.0512秒

这要求心跳时钟不能小于0.0512秒,这屏也太......省略了3w字的粗言秽语。

屏幕截图2025-06-13142246.png

心跳时钟:Prescaler 设 96 - 1,Period 设 60000 -1,在96MHz时钟下,60ms中断一次(>0.0512秒)

设置时钟中断,后可以生成代码了。

屏幕截图2025-06-13143137.png

二、使用TouchGFX Designer

生成代码后,工程目录下出现一个TouchGFX目录,

打开TouchGFX Designer,打开此目录下的.TouchGFX文件,可以使用TouchGFX图像配置界面

屏幕截图2025-06-13143815.png

因为屏幕支持RGB565格式,我载入图片,并把图片设置为RGB565格式

屏幕截图2025-06-13144544.png

屏幕截图2025-06-13144807.png

界面和控件设置后,按F4键或右下角</>图标生成代码。

三、代码配置

1、TouchGFX与屏幕驱动对接

在TouchGFXHAL.hpp引用屏幕驱动头文件(st7789.h)及touchgfx/hal/OSWrappers.hpp

因为TouchGFXHAL.hpp是使用C++,而驱动是使用C语言,为能混合编译,需要使用预处理指令指定st7789.h使用C语言编译。

#ifdef __cplusplus
extern "C" {
#include "st7789.h"
}
#endif
#include <touchgfx/hal/OSWrappers.hpp>

屏幕截图2025-06-13145217.png

在TouchGFXHAL.cpp文件中

void TouchGFXHAL::flushFrameBuffer(const touchgfx::Rect& rect)函数写入

    uint16_t* buffer = getClientFrameBuffer() + (rect.y * DISPLAY_WIDTH) + rect.x;
        LCD7789_DrawImage(rect.x, rect.y, rect.width, rect.height, buffer);

其中:void LCD7789_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t *img);

屏幕截图2025-06-13150220.png

因为16bit数据在SPI传输顺序与图片存储不一致,需要调整LCD7789_DrawImage函数

在st7789.c中

/*******************************************************************************
 * 名    称: LCD7789_DrawImage
 * 功    能: 显示图片
 * 形    参: 起点(x,y),宽w、高y
 * 返    回: 无
 * 说    明: 每像素16bits,RGB565格式
 * 更新日期:2025-6-11
 ******************************************************************************/
void LCD7789_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t *img)
{
    // 参数边界检查
    if((x >= DSP_W) || (y >= DSP_H)) return;
    if((x + w) > DSP_W) w = DSP_W - x;
    if((y + h) > DSP_H) h = DSP_H - y;
    //uint32_t pixel_count = w * h * 2;     // 计算数据量

    LCD7789_SetWindows(x, y, x + w - 1, y + h - 1);     // 设置显示窗口

    LCD_WriteRAM_Prepare();
    //LCD_WR_DATA(img, pixel_count);  // 批量传输数据

    uint8_t data[2];
    for (uint16_t i=0;i<h;i++)
    {
        for (uint16_t j=0;j<w;j++)
        {
            data[0] = img[j]>>8;
            data[1] = img[j];
            LCD_WR_DATA(data, 2);
        }
        img += w;
    }
}

2、心跳实现

在TouchGFXHAL.cpp文件中最后建立心跳函数

extern "C"
void touchgfxSignalVSync(void)
{
    HAL::getInstance()->vSync();
    OSWrappers::signalVSync();
    HAL::getInstance()->swapFrameBuffers();
}

屏幕截图2025-06-13151922.png

在main.c文件主函数main(),中设置阶段加入初始化LCD及启动TIM6中断代码

LCD_Init();
HAL_TIM_Base_Start_IT(&htim6);

屏幕截图2025-06-13152323.png

编写TIM6中断回调函数,每次中断,执行一次TouchGFX心跳,回调函数我习惯放在tim.c中

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* tim_baseHandle)
{
    if(tim_baseHandle->Instance==TIM6)
    {
        touchgfxSignalVSync();
    }
}

屏幕截图2025-06-13152711.png

四、效果

图片.jpg

收藏 评论0 发布时间:2025-6-13 15:30

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版