ST意法半导体
直播中

北冥有熊

9年用户 993经验值
擅长:131594
私信 关注
[问答]

STM32U5+8bit_8080 LCD 怎么配置touchgfx?


我参与的项目使用STM32U575做为主空,使用fmc来驱动8080接口的8bitLCD,配置touchgfx时不能配置为8bit,其他选型例如DMA2D也使用不了,我该怎么做?

回帖(1)

study875

2025-6-16 17:46:00

针对STM32U575使用FMC驱动8位8080接口LCD的TouchGFX配置问题,以下是完整的解决方案:


根本问题分析



  1. FMC硬件限制:STM32的FMC仅支持16位/32位数据总线,物理上无法直连8位LCD

  2. TouchGFX默认配置:CubeMX代码生成器预设仅支持16/24位色深

  3. DMA2D问题:通常因帧缓冲区格式不匹配或LTDC配置错误导致




完整解决方案(分步骤实现)


步骤1:硬件层配置(CubeMX)


// FMC配置为16位模式(实际硬件使用DB[15:8]或DB[7:0],悬空高位)
FMC_NORSRAM_TimingTypeDef Timing = {
  .AddressSetupTime = 2,
  .AddressHoldTime = 1,
  .DataSetupTime = 5,    // 根据LCD时序调整
  .DataLatency = 0,
  .BusTurnAroundDuration = 0
};

FMC_NORSRAM_InitTypeDef Init = {
  .DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE,
  .MemoryType = FMC_MEMORY_TYPE_SRAM,
  .MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16, // 强制设为16位
  .BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE
};

步骤2:软件层8位数据处理(修改HAL驱动)


// 在FMC写操作函数中添加位掩码
void LCD_WriteData(uint8_t data) {
  *((__IO uint16_t*)LCD_DATA_ADDR) = (0xFF00 | data); // DB[15:8]传输
  // 或 *((__IO uint16_t*)LCD_DATA_ADDR) = (data << 8); // DB[15:8]传输
}

步骤3:TouchGFX关键配置修改




  1. 修改CubeMX的TouchGFX设置


    // MX_TouchGFX_Init() 中更改帧缓冲格式
    hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565; // 实际输出需转换



  2. 创建自定义帧缓冲器(custom_framebuffer.cpp):


    extern "C" {
    #include "lcd_fmc_driver.h" // 包含你的硬件驱动
    }

    void TouchGFXHAL::configureInterfaces() {
    // 重定向帧缓冲到自定义8位缓冲区
    hal.setFrameBufferStartAddress((uint8_t*)customFrameBuffer,
                                     LCD_WIDTH * LCD_HEIGHT,
                                     BitDepth::BPP8);
    }

    // 实现像素格式转换
    __weak void DMA2D_CopyBuffer(void* pSrc, void* pDst) {
    uint8_t* src = (uint8_t*)pSrc;
    uint8_t* dst = (uint8_t*)pDst;
    for (uint32_t i = 0; i < BUFFER_SIZE; i++) {
       dst[i] = convertRGB565toRGB332(*(uint16_t*)(&src[i*2]));
    }
    }



步骤4:启用DMA2D加速(关键补丁)


// stm32u5xx_hal_ltdc.c 中修改
HAL_StatusTypeDef HAL_LTDC_Init(LTDC_HandleTypeDef *hltdc) {
  // ...原有代码
  hdma2d.Init.Mode = DMA2D_R2M;          // 寄存器到内存
  hdma2d.Init.OutputOffset = 0;
  hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
  hdma2d.LayerCfg[0].InputOffset = 0;
  hdma2d.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565;
  HAL_DMA2D_Init(&hdma2d); // 显式初始化
}

步骤5:TouchGFX HAL适配层修改


// 在 touchgfx/hal/HAL.cpp 添加重载
void HAL::setFrameBuffer(uint16_t* adr) {
  uint8_t* converted = convertFrameBufferFormat(adr);
  LTDC_Layer1->CFBAR = (uint32_t)converted; // 指向转换后缓冲
  __HAL_LTDC_RELOAD_CONFIG(&hltdc);
}



关键适配技术说明




  1. RGB565→RGB332转换算法


    static inline uint8_t convertRGB565toRGB332(uint16_t rgb565) {
    return ((rgb565 & 0xE000) >> 8) | // R: 5bit→3bit
            ((rgb565 & 0x0700) >> 6) | // G: 6bit→3bit (取高位)
            ((rgb565 & 0x0018) >> 3);  // B: 5bit→2bit
    }



  2. 性能优化策略


    // 使用DMA2D实时转换(在V-SYNC中断中触发)
    void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef *hltdc) {
    HAL_DMA2D_Start_IT(&hdma2d,
         (uint32_t)srcFrameBuffer,
         (uint32_t)customFrameBuffer,
         LCD_WIDTH, LCD_HEIGHT/10); // 分段传输减少延迟
    }



  3. 颜色深度补偿技术



    • 在UI设计器中强制使用256色索引模式

    • 修改touchgfx_dipalette.hpp
      const uint16_t palette[] = { 
      0x0000, 0xF800, 0x07E0, ... // RGB565格式的332调色板
      };






调试注意事项




  1. FMC时序验证


    // 使用逻辑分析仪检查时序参数
    while(1) {
    *((__IO uint16_t*)0x60000000) = 0xAA55; // 发送测试模式
    HAL_Delay(1);
    }



  2. DMA2D状态监控


    if (HAL_DMA2D_GetState(&hdma2d) == HAL_DMA2D_STATE_READY) {
    debug("DMA2D Ready");
    }



  3. 帧率显示调试


    // 在FrameBufferAllocator.cpp中
    uint32_t last_tick = 0;
    void HAL::vSync() {
    uint32_t now = HAL_GetTick();
    debug("FPS: %d", 1000/(now - last_tick));
    last_tick = now;
    }



最终解决方案需结合:



  1. 硬件上使用DB[15:8]传输8位数据(弃用DB[7:0])

  2. 软件实现RGB565到RGB332的动态转换

  3. 修改TouchGFX的DMA2D和帧缓冲配置

  4. 定制UI设计使用256色优化


建议先使用STM32CubeIDE的FMC调试工具验证物理层通信,再逐步整合TouchGFX组件。实际项目中还需考虑增加双缓冲机制来弥补8位传输的性能损失。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分