硬汉嵌入式论坛

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

[emWin] WM_MULTIBUF_Enable(1);三缓冲图像不清晰

[复制链接]

16

主题

31

回帖

79

积分

初级会员

积分
79
发表于 2019-10-16 14:54:34 | 显示全部楼层 |阅读模式
本帖最后由 lyw851230 于 2019-10-16 14:56 编辑

main函数里用WM_SetCreateFlags(WM_CF_MEMDEV);图像非常清晰,实际仿真未进入 case LCD_X_SHOWBUFFER:,证明没有用到多级缓冲(尽管有GUI_ALLOC_AssignMemory((void *)GUI_BUF_ADDR, GUI_NUMBYTES);和GUI_MULTIBUF_Config(GUI_BUFFERS);)。

当屏蔽WM_SetCreateFlags(WM_CF_MEMDEV);,加入WM_MULTIBUF_Enable(1);后,图像变得不清晰。
仿真时,进入APP_LCDIF_IRQHandler,且执行GUI_MULTIBUF_Confirm(s_LCDpendingBuffer);函数,后显示出不清晰的图像,程序进入等待状态,无法进入  case LCD_X_SHOWBUFFER:
若是在任意一个控件上点击一下,进入  case LCD_X_SHOWBUFFER:程序,图像变得非常清晰。
感觉是绘图的时候没有调用 LCD_X_DisplayDriver(),请大家给支支招,怎么解决






下面是程序:

#define GUI_NUMBYTES  1000000U//设为1000K
#define GUI_BUFFERS 3
#define LCD_BUFFERS 3
#define GUI_BLOCKSIZE 0X80  //块大小
#define LCD_DIRECTION 1   //横屏
#define LCD_BITS_PER_PIXEL 16
#define LCD_BYTES_PER_PIXEL (LCD_BITS_PER_PIXEL / 8)
#define VRAM_SIZE (LCD_PIXEL_HEIGHT * LCD_PIXEL_WIDTH * LCD_BYTES_PER_PIXEL)
#define COLOR_CONVERSION GUICC_M565
#define DISPLAY_DRIVER   GUIDRV_LIN_16
#define GUI_BUF_ADDR 0x80600000  //emwin动态内存

#define VRAM_ADDR 0x80700000//显存
#define USE_EXRAM  1        //使用外部RAM

static const U32 _aBufferPTR[] =
{
        0x80700000,
        0x80700000+VRAM_SIZE,
        0x80700000+VRAM_SIZE*2
};


//__align(64)        uint32_t gui_buf[2][LCD_PIXEL_HEIGHT][LCD_PIXEL_WIDTH] __attribute__((at(GUI_BUF_ADDR)));

static uint32_t lutData[ELCDIF_LUT_ENTRY_NUM];
static volatile int32_t s_LCDpendingBuffer = -1;

void GUI_X_Config(void) {
        if(USE_EXRAM) //使用外部RAM
        {               
      GUI_ALLOC_AssignMemory((void *)GUI_BUF_ADDR, GUI_NUMBYTES);
      //GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSIZE);

  //
      GUI_SetDefaultFont(GUI_FONT_6X8);
        }else  //使用内部RAM
        {

        }
}



/*******************************************************************************
* Implementation of PortAPI for emWin LCD driver
******************************************************************************/

/* Enable interrupt. */
void BOARD_EnableLcdInterrupt(void)
{
    EnableIRQ(LCDIF_IRQn);
}
//三缓冲时用的中断处理函数
void APP_LCDIF_IRQHandler(void)
{

          uint32_t addr;
    uint32_t intStatus;

    intStatus = ELCDIF_GetInterruptStatus(LCDIF);//获得中断状态,响应中断

    ELCDIF_ClearInterruptStatus(LCDIF,intStatus);//清中断状态

    if (intStatus & kELCDIF_CurFrameDone)
    {
        if (s_LCDpendingBuffer >= 0)
        {
                addr = VRAM_ADDR  + VRAM_SIZE * s_LCDpendingBuffer;//此处的地址应该是显示的地址,显存地址会随着 s_LCDpendingBuffer变化
                 ELCDIF_SetNextBufferAddr(LCDIF, addr);//将显存中的数据显示出来
            /* Send a confirmation that the given buffer is visible */
            GUI_MULTIBUF_Confirm(s_LCDpendingBuffer);//应在挂起的前置缓冲器成为可见之后立即调用
            s_LCDpendingBuffer = -1;
        }
    }
    __DSB();
}

void LCDIF_IRQHandler(void)
{
    APP_LCDIF_IRQHandler();
}

void APP_ELCDIF_Init(void)
{
        const                 elcdif_rgb_mode_config_t lcdConfig = {
                                             .panelWidth = LCD_PIXEL_WIDTH,
                                             .panelHeight = LCD_PIXEL_HEIGHT,
                                                               .hsw = LCD_HSW,
                                             .hfp = LCD_HFP,
                                             .hbp = LCD_HBP,
                                                               .vsw = LCD_VSW,
                                                               .vfp = LCD_VFP,
                                                               .vbp = LCD_VBP,
                                                               .polarityFlags =  LCD_POLARITY_FLAGS,
                                                               //.bufferAddr = (uint32_t)s_psBufferLcd[0],
                                                               .bufferAddr = VRAM_ADDR,
                                                               .pixelFormat = kELCDIF_PixelFormatRGB565,
                                                               .dataBus = kELCDIF_DataBus16Bit
                                                        };
   ELCDIF_RgbModeInit(LCDIF, &lcdConfig);//初始化
                                                                                                                                                                                
    BOARD_EnableLcdInterrupt();
    ELCDIF_EnableInterrupts(LCDIF, kELCDIF_CurFrameDoneInterruptEnable);
    NVIC_EnableIRQ(LCDIF_IRQn);
    ELCDIF_RgbModeStart(LCDIF);
}

static void _CopyBuffer(int LayerIndex, int IndexSrc, int IndexDst)
{
        unsigned long  AddrSrc, AddrDst;
        AddrSrc = VRAM_ADDR + VRAM_SIZE * IndexSrc;  
        AddrDst = VRAM_ADDR + VRAM_SIZE * IndexDst;  //AddrDst地址也会
        memcpy((void *)AddrDst, (void *)AddrSrc, VRAM_SIZE);
}


/*******************************************************************************
* Application implemented functions required by emWin library
******************************************************************************/
void LCD_X_Config(void)
{
           
//.......................配置开始.....................................
        
    GUI_MULTIBUF_Config(GUI_BUFFERS);//设置3缓冲区
        
    GUI_DEVICE_CreateAndLink(DISPLAY_DRIVER, COLOR_CONVERSION, 0, 0);//创建显示驱动器件,并关联将使用的颜色转换程序。
    if(LCD_DIRECTION==0)//竖屏
    {

                          LCD_SetSizeEx(0,LCD_PIXEL_HEIGHT,LCD_PIXEL_WIDTH);    //设置可见区尺寸
                          LCD_SetVSizeEx(0,LCD_PIXEL_HEIGHT,LCD_PIXEL_WIDTH);   //设置虚拟显示区尺寸
        GUI_SetOrientation(GUI_SWAP_XY|GUI_MIRROR_Y);   //设置为竖屏
    }else            //横屏
    {
                        LCD_SetSizeEx(0,LCD_PIXEL_WIDTH,LCD_PIXEL_HEIGHT);
                        LCD_SetVSizeEx(0,LCD_PIXEL_WIDTH,LCD_PIXEL_HEIGHT);
    }
    //LCD_SetVRAMAddrEx(0, (void *)VRAM_ADDR);//0表示图层1,若是图层2则第一个参数为1,设置视频视频RAM的地址。仅当使用配备线性映射视频RAM的显示驱动时才需要 此函数。
                LCD_SetBufferPtr((void *)_aBufferPTR);
                LCD_SetDevFunc(0, LCD_DEVFUNC_COPYBUFFER, (void (*)())_CopyBuffer); //如果使用的显示控制器包括能执行复制 操作的 BitBLT 引擎,则可以利用该引擎来执行复制操作。否则,应当使用基于 DMA 的函数来完成复制 操作。
}


int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void *pData)//显示驱动的回调函数
{
    //uint32_t addr;
#if (LCD_BITS_PER_PIXEL == 16)
    uint16_t colorR, colorG, colorB;
    uint32_t color;
#endif
    int result = 0;

    switch (Cmd)
    {
        case LCD_X_INITCONTROLLER:
        {
            APP_ELCDIF_Init();//使能LCD中断、RGB mode开启
            break;
        }
        case LCD_X_SHOWBUFFER:
        {
                                        LCD_X_SHOWBUFFER_INFO *_pData;


            _pData = (LCD_X_SHOWBUFFER_INFO *)pData;
            s_LCDpendingBuffer = _pData->Index;
            while (s_LCDpendingBuffer >= 0)
                ;
            return 0;
        }
                                case LCD_X_SETLUTENTRY:
        {
            //
            // Required for setting a lookup table entry which is passed in the 'Pos' and 'Color' element of p
            //
            LCD_X_SETLUTENTRY_INFO *_pData;
            _pData = (LCD_X_SETLUTENTRY_INFO *)pData;
            //
            // Call hardware routine to write a LUT entry to the controller
            //
            color = _pData->Color;
            colorB = (color & 0xFF0000) >> 16;
            colorG = (color & 0x00FF00) >> 8;
            colorR = (color & 0x0000FF);
            /* 16-bit bus */
            lutData[_pData->Pos] = (colorR << 11) | (colorG << 5) | (colorB);
            return 0;
        }
        default:
            result = -1;//通过返回不同值区别buffer内是否有图片或数据
            break;
    }

    return result;
}



回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107415
QQ
发表于 2019-10-16 15:21:19 | 显示全部楼层
多缓冲没有正常开启
回复

使用道具 举报

16

主题

31

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2019-10-16 15:33:13 | 显示全部楼层
eric2013 发表于 2019-10-16 15:21
多缓冲没有正常开启

硬汉兄,_pData->Index指数从0,1,2这样循环变化,这样还没开启?怎么才算开启?

我点击不清楚图像上的button控件图像就变清晰,同时停留在 s_LCDpendingBuffer = _pData->Index;处

我想问的是如何打开每一个页面时都发送命令LCD_X_SHOWBUFFER,能够把LCD_X_DisplayDriver调用上
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107415
QQ
发表于 2019-10-17 07:11:41 | 显示全部楼层
lyw851230 发表于 2019-10-16 15:33
硬汉兄,_pData->Index指数从0,1,2这样循环变化,这样还没开启?怎么才算开启?

我点击不清楚图像上的 ...

试试这个,KEIL提供的用于RT105X的emWin底层驱动文件
http://www.armbbs.cn/forum.php?mod=viewthread&tid=95140&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

16

主题

31

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2019-10-17 09:16:18 | 显示全部楼层
本帖最后由 lyw851230 于 2019-10-17 09:57 编辑

妥了,用我最上面的文件没有问题,问题出在调用上。

需要在while循环里加上
#ifdef GUI_BUFFERS
            GUI_MULTIBUF_Begin();
#endif
                      //GUI_Delay(20);
            GUI_Exec();
#ifdef GUI_BUFFERS
            GUI_MULTIBUF_End();

LCDConf_Lin_Template.c

6.25 KB, 下载次数: 28

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107415
QQ
发表于 2019-10-17 11:10:33 | 显示全部楼层
lyw851230 发表于 2019-10-17 09:16
妥了,用我最上面的文件没有问题,问题出在调用上。

需要在while循环里加上

这两个函数一般用于重绘前后。图形绘制前后等场合
回复

使用道具 举报

6

主题

54

回帖

72

积分

初级会员

积分
72
发表于 2021-12-6 15:18:36 | 显示全部楼层
为啥我一调用WM_MULTIBUF_Enable(1);程序就跑飞了呢!~
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107415
QQ
发表于 2021-12-7 08:59:59 | 显示全部楼层
fengxiaoyu 发表于 2021-12-6 15:18
为啥我一调用WM_MULTIBUF_Enable(1);程序就跑飞了呢!~

你的底层驱动应该没有正常实现。
回复

使用道具 举报

2

主题

26

回帖

32

积分

新手上路

积分
32
发表于 2022-2-22 11:13:22 | 显示全部楼层
我一调用WM_MULTIBUF_Enable(1)触摸就失效,不调用就正常。不知什么原因?触摸是GT911。
回复

使用道具 举报

2

主题

26

回帖

32

积分

新手上路

积分
32
发表于 2022-2-22 11:15:45 | 显示全部楼层
用:WM_SetCreateFlags(WM_CF_MEMDEV);触摸也正常
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107415
QQ
发表于 2022-2-22 11:33:26 | 显示全部楼层
focus012 发表于 2022-2-22 11:13
我一调用WM_MULTIBUF_Enable(1)触摸就失效,不调用就正常。不知什么原因?触摸是GT911。

这个没遇到过,我们用的是GT911和三缓冲,触摸都正常,有需要可以参考。
回复

使用道具 举报

2

主题

26

回帖

32

积分

新手上路

积分
32
发表于 2022-2-22 15:45:24 | 显示全部楼层
eric2013 发表于 2022-2-22 11:33
这个没遇到过,我们用的是GT911和三缓冲,触摸都正常,有需要可以参考。

谢谢,我就是参照V7的例子改的,我再看看。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-30 12:52 , Processed in 0.192040 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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