ST意法半导体
直播中

钱一辰

8年用户 1037经验值
私信 关注
[问答]

求助,关于正点原子阿波罗H743使用DMA2D后普通刷出现问题求解

正点原子阿波罗H743使用DMA2D后普通刷屏出现问题:
代码:
import utime as timefrom machine import LCD     # Import the LCD class from machinelcd = LCD()                             # Create a LCD objectlcd.light(False)                        # Close the backlighttime.sleep(1)lcd.light(True)                         # Open the backlighttime.sleep(1)lcd.set_color(lcd.WHITE, lcd.BLACK)     # Set background color and foreground colorlcd.fill(lcd.BLACK)                     # Fill the entire LCD with blacktime.sleep(1)lcd.fill(lcd.RED)                       # Fill the entire LCD with redtime.sleep(1)lcd.fill(lcd.GRAY)                      # Fill the entire LCD with graytime.sleep(1)lcd.fill(lcd.WHITE)                     # Fill the entire LCD with whitetime.sleep(1)lcd.pixel(50, 50, lcd.BLUE)             # fills the pixels in the (50,50) position with bluetime.sleep(1)lcd.text("hello RT-Thread", 0, 0, 16)   # prints the string at 16 font size at position (0, 0)time.sleep(1)lcd.text("hello RT-Thread", 0, 16, 24)  # prints the string at 24 font size at position (0, 16)time.sleep(1)lcd.text("hello RT-Thread", 0, 48, 32)  # prints the string at 32 font size at position (0, 48)time.sleep(1)lcd.line(0, 50, 1023, 50)                # Draw a line starting at (0,50) and ending at (239,50)time.sleep(1)lcd.line(0, 50, 1023, 50)                # Draw a line starting at (0,50) and ending at (239,50)time.sleep(1)lcd.rectangle(100, 100, 1000, 500)       # Draw a rectangle with the top left corner (100,100) and the bottom right corner (200,200)time.sleep(1)lcd.circle(150, 150, 100)                # Draw a circle with a radius of 80 at the center (150,150)


回帖(1)

的撒的

2025-5-7 17:58:46

针对正点原子阿波罗H743使用DMA2D后普通刷屏出现的问题,以下是逐步解决方案:




问题原因分析



  1. DMA2D传输未完成时访问显存:普通刷屏操作可能在DMA2D未完成传输时修改了显存,导致数据冲突。

  2. 显存地址或格式配置错误:DMA2D与普通刷屏的显存地址或颜色模式不匹配。

  3. 硬件资源竞争:CPU和DMA2D同时访问同一显存区域,未正确同步。




解决方案


1. 确保DMA2D传输完成后再进行普通刷屏


在启动DMA2D传输后,必须等待传输完成再执行其他显存操作。


// 启动DMA2D传输(以填充内存为例)
HAL_DMA2D_Start(&hdma2d, color, (uint32_t)目标地址, 宽度, 高度);

// 阻塞等待传输完成
while (HAL_DMA2D_PollForTransfer(&hdma2d, 100) != HAL_OK);

// 传输完成后执行普通刷屏操作
LCD_DisplayString(0, 0, "Hello World");

2. 检查显存地址和颜色格式



  • 显存地址:确认DMA2D的目标地址与LCD显存起始地址一致。

  • 颜色格式:DMA2D和普通刷屏的颜色格式需同为RGB565、ARGB8888等。例如,在初始化中配置:


hdma2d.Init.ColorMode = DMA2D_RGB565;  // 与LCD模式匹配
hdma2d.Init.OutputOffset = 0;          // 显存行偏移

3. 使用中断同步(可选)


若需非阻塞操作,可在DMA2D传输完成中断中触发后续操作:


// 启动DMA2D传输并启用中断
HAL_DMA2D_Start_IT(&hdma2d, color, (uint32_t)目标地址, 宽度, 高度);

// 在传输完成回调函数中执行刷屏
void HAL_DMA2D_TransferCpltCallback(DMA2D_HandleTypeDef *hdma2d)
{
    LCD_DisplayString(0, 0, "Transfer Done");
}

4. 验证显存访问权限


确保显存区域配置为可被DMA2D和CPU同时访问(通常需配置为非缓存或使用内存屏障):


// 在STM32H7中,显存通常放置于AXI SRAM(0x24000000),需配置MPU为Write-through
MPU_Config();

5. 排查硬件连接与驱动配置



  • LCD接口:确认FSMC/LTDC配置正确,时序参数与屏幕规格匹配。

  • DMA2D时钟:启用DMA2D时钟(__HAL_RCC_DMA2D_CLK_ENABLE())。




测试步骤



  1. 单独测试普通刷屏:禁用DMA2D相关代码,确认基础显示功能正常。

  2. 单独测试DMA2D:仅使用DMA2D填充颜色块,观察是否正常。

  3. 逐步结合:在DMA2D操作后加入同步等待,再执行普通刷屏,观察问题是否消失。




示例代码片段(HAL库)


// 初始化DMA2D
hdma2d.Instance = DMA2D;
hdma2d.Init.Mode = DMA2D_R2M;          // 寄存器到内存模式
hdma2d.Init.ColorMode = DMA2D_RGB565;  // 与LCD配置一致
hdma2d.Init.OutputOffset = 0;          // 无行偏移
HAL_DMA2D_Init(&hdma2d);

// 使用DMA2D填充绿色矩形
uint32_t destAddr = (uint32_t)(lcd_frame_buffer);  // 显存地址
HAL_DMA2D_Start(&hdma2d, 0x07E0, destAddr, 320, 240);  // RGB565绿色
HAL_DMA2D_PollForTransfer(&hdma2d, 100);  // 等待完成

// 普通刷屏操作(绘制文字)
LCD_SetTextColor(LCD_COLOR_WHITE);
LCD_DisplayString(10, 10, "DMA2D Done");



常见问题排查



  • 花屏/错位:检查显存地址偏移(OutputOffset)是否与屏幕分辨率匹配。

  • 颜色异常:确认DMA2D和LCD的颜色格式一致。

  • 死机/卡顿:检查MPU配置或内存访问权限冲突,确保显存区域可被DMA和CPU访问。


通过以上步骤,应能解决DMA2D与普通刷屏冲突的问题。若仍存在异常,建议使用调试器检查显存内容,或逐步注释代码定位冲突点。

举报

更多回帖

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