硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1269|回复: 4
收起左侧

[有问必答] STM32F407VET6 + FSMC + DMA LCD图片显示不全

[复制链接]

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2024-9-23 23:49:42 | 显示全部楼层 |阅读模式
本帖最后由 LHYLiuWilliam 于 2024-9-23 23:56 编辑

写GRAM指令后循环写LCD_RAM可以正常显示图片

void LCD_ShowImage(LCD *lcd, uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *image) {
    LCD_SetWindow(lcd, x, y, width, height);
    LCD_WriteGRAM(lcd);

    uint32_t totalPoint = width * height;
    for (uint32_t i = 0; i < totalPoint; i++) {
        LCD_WriteDATA((image[i * 2 + 1] << 8) | image[i * 2]);
    }
}


但是换用DMA从image向LCD_RAM搬运数据就会出问题,图片只能显示上部分 五分之一 左右
void LCD_ShowImage(LCD *lcd, uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *image) {
    LCD_SetWindow(lcd, x, y, width, height);
    LCD_WriteGRAM(lcd);

    HAL_DMA_Start(&dma.Handler, (uint32_t)image, (uint32_t)&LCD1->LCD_RAM,
                  width * height);
    while (HAL_DMA_PollForTransfer(&dma.Handler, HAL_DMA_FULL_TRANSFER,
                                   HAL_MAX_DELAY) != HAL_OK)
        ;
}


使用DMA时图片有部分可以正常显示,DMA的配置应该没问题

目前疑问如下:

1. 使用DMA调用 HAL_DMA_Start 时,如果将 width * height 改为 width * height * 2,图片的显示范围会扩大到上部分  五分之二 左右,
    但改为 width * height * 4,图片显示范围反而缩小回 五分之一 左右。

2. 图片数组为高位在后的模式,所以使用循环写LCD_RAM方法时,需要将高位移至前面: (image[i * 2 + 1] << 8) | image[i * 2]
    但使用DMA时,没有做高位调整的操作,直接将16位数据搬运至LCD_RAM,图片色彩正常,调整后反而色彩不正常

求大佬解答,大学牲要睡不着觉了

回复

使用道具 举报

34

主题

206

回帖

308

积分

高级会员

积分
308
发表于 2024-9-24 10:08:54 | 显示全部楼层
确认下DMA数据内存地址有没有分配到不支持DMA的内存
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2024-9-24 10:11:46 | 显示全部楼层
1、最关键的地方,楼主没说,DMA传输最大65535次
2、一定要开启LCD地址自增模式。并且设置开窗范围。

此贴可以参考

【原创开源应用第4期】给ili9488,RA8875等类显示屏的emWin底层增加DMA加速,提供RTX,uCOS和FreeRTOS版本
https://forum.anfulai.cn/forum.p ... 7501&fromuid=58
(出处: 硬汉嵌入式论坛)


回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
 楼主| 发表于 2024-9-24 17:06:08 | 显示全部楼层
eric2013 发表于 2024-9-24 10:11
1、最关键的地方,楼主没说,DMA传输最大65535次
2、一定要开启LCD地址自增模式。并且设置开窗范围。

多谢硬汉哥,确实是因为DMA传输最大65535次的问题

HAL_DMA_Start 的原型是
HAL_StatusTypeDef HAL_DMA_Start (DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);

uint32_t DataLength 让我想当然以为最大传输次数完全足够了

这是修改后的函数
void LCD_ShowImage(LCD *lcd, uint16_t x, uint16_t y, uint16_t width,
                   uint16_t height, const uint8_t *image) {
    LCD_SetWindow(lcd, x, y, width, height);
    LCD_WriteGRAM(lcd);

    uint32_t restPoint = width * height, alreadyPoint = 0;
    do {
        uint32_t pointToShow = restPoint >= 65535 ? 65535 : restPoint;

        HAL_DMA_Start(&lcd->DMA.Handler, (uint32_t)(image + alreadyPoint * 2),
                      (uint32_t)&LCD1->LCD_RAM, pointToShow);
        while (HAL_DMA_PollForTransfer(&lcd->DMA.Handler, HAL_DMA_FULL_TRANSFER,
                                       HAL_MAX_DELAY) != HAL_OK)
            ;

        restPoint -= pointToShow;
        alreadyPoint += pointToShow;
    } while (restPoint);
}



我还是有一个疑问请大佬帮忙解答

1. 我在图片取模的时候没有选择高位在前

  所以之前在打点显示的时候要手动把高8位移到前面 LCD_WriteDATA((image[i * 2 + 1] << 8) | image[i * 2]) ,这样色彩才是正确的
  但是在使用DMA时,直接把16数据搬过去就可以,把高8位移到前面再搬过去色彩反而是错误的,这是为什么?


回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2024-9-25 09:39:12 | 显示全部楼层
LHYLiuWilliam 发表于 2024-9-24 17:06
多谢硬汉哥,确实是因为DMA传输最大65535次的问题

HAL_DMA_Start 的原型是

如果不是DMA的话,你可以直接定义个uint16_t *p的指针指向这个图片数据,然后p++绘制,一次一个16bit点。

这种应该就对了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 02:51 , Processed in 0.071309 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表