硬汉嵌入式论坛

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

[emWin] 实时显示摄像头数据时画面抖动

[复制链接]

9

主题

42

回帖

69

积分

初级会员

大牛的形成也是时间与技术的积累

积分
69
QQ
发表于 2017-3-18 14:19:07 | 显示全部楼层 |阅读模式
V70318-114428.rar (7.31 MB, 下载次数: 193) 硬件配制: STM32F429 + 16位SDRAM,4.3寸MCU接口屏,要实现的功能是点击某个界面图标,将摄像头实时图像显示到屏上,显示大小为474X315. 底层窗口是用emwin画的,实时显示的摄像头图像是用的DMA的方式直接显示到屏上的(不知道emwin显示摄像头数据要怎么做?),由于摄像头还要叠加文字等,实现过程是先用DMA将摄像头数据写到buf, 采用的是双缓冲模式,两个BUF循环接收摄像头数据,然后拼到一个大BUF里。一帧数据收完后,将文字,2D线等拼加到大BUF,然后再通过DMA传输到屏上显示。但有一个问题,就是图像尺寸是474X315时,左边侧总是有一条纹在抖动,画面有脱节(见附件视频)。当改成小尺寸240X240时,这种现象要好一些,但有时也会出现这种现象,不过概率要小很多。有人说是帧同步问题,我感觉是不是是显示速度不够快引起,不知道应该改哪些,请各位指教。

QQ图片20170318120015.png


部分初始化代码:
static WM_HWIN CreateCameraWindow( WM_HWIN hParent )
{
   /*
  .........//省略部分OV5640初始化及窗体建立部分
*/


/* 输出格式: RGB565: 2Bytes */
        frame_size = DOUT_WINDOWS_SIZE*2;

       DCMI_Init();            //初始化DCMI,此函数会开启帧中断

        //eric: 重配置外部SRAM,错位问题解决了,速度再提升200KB/S,现在处于800-900KB/S。
        pCmrbuf = mymalloc(SRAMEX, frame_size);
        MultiBuffer[0] = mymalloc(SRAMEX, GRAPH_SINGLE_BUF_SIZE*4);
        MultiBuffer[1] = mymalloc(SRAMEX, GRAPH_SINGLE_BUF_SIZE*4);

        /* 修改指针指向 */
        sdramlcd_change((u16*)(pCmrbuf));

        cor_inx = GUI_Color2Index(DESKTOP_BKC);//EMWIN Color->RGB565
        clr_sramlcdbuf(frame_size/2, cor_inx);   

        /* DMA_MDATAALIGN_WORD is essential!!, correspond to DCMI->DR,
        orelse, cause split screen!! */
        DCMI_DMA_Init((u32)pCmrbuf, 0, 0, DMA_MDATAALIGN_WORD, DMA_MINC_ENABLE);

        jpeg_data_len = jpeg_data_ok = 0;
        dcmi_rx_callback = _cbGraphXferCplt;
        HAL_DMAEx_MultiBufferStart(&DMADMCI_Handler, (u32)&DCMI->DR, (u32)MultiBuffer[0], (u32)MultiBuffer[1], GRAPH_SINGLE_BUF_SIZE);//开启双缓冲
        __HAL_DMA_ENABLE_IT(&DMADMCI_Handler, DMA_IT_TC);    //开启传输完成中断
        HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);        //DMA中断优先级
        HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
        
        BufToLcdDMAInit();
}


static void BufToLcdDMAInit(void)
{   
    __HAL_RCC_DMA2_CLK_ENABLE();//DMA2时钟使能   
   
    //__HAL_LINKDMA(&UART1_Handler,hdmatx,UART1TxDMA_Handler);    //将DMA与USART1联系起来(发送DMA)

    while(DMA2_Stream0->CR & 0X01);//等待DMA2_Stream0可配置
    __HAL_DMA_CLEAR_FLAG(&lcdDMA_Handler, DMA_FLAG_TCIF0_4|DMA_FLAG_FEIF0_4\
            |DMA_FLAG_TEIF0_4|DMA_FLAG_DMEIF0_4);
   
    /* DMA2才支持存储器到存储器模式。存储器到存储器模式,
    只要你设置好了,一启动就立即传输. M2M模式,只能使用FIFO模式 */
    lcdDMA_Handler.Instance = DMA2_Stream0;                          //DMA2数据流0                     
    lcdDMA_Handler.Init.Channel = DMA_CHANNEL_0;                     //通道1
    lcdDMA_Handler.Init.Direction = DMA_MEMORY_TO_MEMORY;            //外设到存储器
    lcdDMA_Handler.Init.PeriphInc = DMA_PINC_ENABLE;                //外设增量模式,增量值为PSIZE:2(HALFWORD)!!
    lcdDMA_Handler.Init.MemInc = DMA_MINC_DISABLE;                       //存储器非增量模式
    lcdDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;   //外设数据长度:16位
    lcdDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;      //存储器数据长度:16位
    lcdDMA_Handler.Init.Mode = DMA_NORMAL;//DMA_CIRCULAR;   //M2M模式不能使用循环模式,所以也不能用双缓冲!!
    lcdDMA_Handler.Init.Priority = DMA_PRIORITY_LOW;                //高优先级
    lcdDMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;              //M2M只能使用FIFO模式!!使能FIFO
    lcdDMA_Handler.Init.FIFOThreshold = 0;//DMA_FIFO_THRESHOLD_HALFFULL; //使用1/2的FIFO
    lcdDMA_Handler.Init.MemBurst = DMA_MBURST_SINGLE;                //存储器突发传输
    lcdDMA_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE;             //外设突发单次传输
   
    HAL_DMA_DeInit(&lcdDMA_Handler);                               //先清除以前的设置
    HAL_DMA_Init(&lcdDMA_Handler);                                    //初始化DMA   
}


void BufToLcdDMAShow(int x, int y, int xsize, int ysize)
{  
    u32 lcdsize = xsize*ysize;
    u32 dmatransfered = 0;
    u32 tx_len;   

    /* Is an important sentence, decide the display area!! */
    LCD_Set_Window(x, y, xsize, ysize);
    LCD_SetCursor(x, y);//设置光标位置
    LCD_WriteRAM_Prepare();     //开始写入GRAM   
            
    while(lcdsize)
    {           
        __HAL_DMA_DISABLE(&lcdDMA_Handler);
        while(lcdDMA_Handler.Instance->CR & 0X01);        //等待DMA2_Stream0可配置

        //清除上次的传输完成标记
        __HAL_DMA_CLEAR_FLAG(&lcdDMA_Handler, DMA_FLAG_TCIF0_4|DMA_FLAG_FEIF0_4\
        |DMA_FLAG_TEIF0_4|DMA_FLAG_DMEIF0_4);        
        
        if(lcdsize > SLCD_DMA_MAX_TRANS)
        {
            tx_len = SLCD_DMA_MAX_TRANS;
            lcdsize -= SLCD_DMA_MAX_TRANS;               
        }
        else
        {            
            tx_len = lcdsize;
            lcdsize = 0;
        }   

        __HAL_UNLOCK(&lcdDMA_Handler);
        HAL_DMA_Start(&lcdDMA_Handler, (u32)(sramlcdbuf + dmatransfered), (u32)&LCD->LCD_RAM, tx_len);
        while(__HAL_DMA_GET_FLAG(&lcdDMA_Handler, DMA_FLAG_TCIF0_4) == RESET)
        {
            ;//pro = __HAL_DMA_GET_COUNTER(&lcdDMA_Handler);
        }
        dmatransfered += tx_len;   
    }

    __HAL_DMA_DISABLE(&lcdDMA_Handler);
}


static void DispCmrImage(void)
{
    u16 cor_inx = POINT_COLOR;
    int cursor_x=100,cursor_y = 100;
        
    if(jpeg_data_ok)
    {                        
        DCMI_Stop();    //停止DCMI

        if(cfr > 0)
        {
            /* 放大倍数图标 */
            usrGUI_ShowIcon(rZoom.x1+5, rZoom.y0-10, &icoZOOM, cor_inx);//zoom
            usrGUI_FillRect(&rZoom, cor_inx);
            usrGUI_FillRect(&rZmbar, cor_inx);
                           
            LCD_ShowString(150, 105, 190, 145, 24, zmbuf[Zm]);

            /* 亮度调节图标 */
            usrGUI_FillRect(&rBrt, cor_inx);
            usrGUI_ShowIcon(rBrt.x0-10, rBrt.y0 + brt*20, &icoBRT, cor_inx);

            /* 激光点 */
            usrGUI_ShowIcon(cursor_x, cursor_y, &icoCURSOR, cor_inx);                                
        }
  
        //BufToLcdDMAShow(DOUT_WINDOWS_XST, 432, DOUT_WINDOWS_XSIZE, DOUT_WINDOWS_YSIZE);
        BufToLcdDMAShow(DOUT_WINDOWS_XST, DOUT_WINDOWS_YST, DOUT_WINDOWS_XSIZE, DOUT_WINDOWS_YSIZE);
                    
        jpeg_data_ok = 0;
        jpeg_data_len = 0;
        
        DCMI_Start();
    }
}
回复

使用道具 举报

4

主题

21

回帖

33

积分

新手上路

积分
33
发表于 2017-3-18 19:31:26 | 显示全部楼层
应该是摄像头数据锁存问题,楼主好厉害!视频流畅度怎样?我们现在也在帮客户做视频画中画和叠加

内容来自[手机版]
回复

使用道具 举报

9

主题

42

回帖

69

积分

初级会员

大牛的形成也是时间与技术的积累

积分
69
QQ
 楼主| 发表于 2017-3-20 08:36:03 | 显示全部楼层

回 g_lcd 的帖子

g_lcd:应该是摄像头数据锁存问题,楼主好厉害!视频流畅度怎样?我们现在也在帮客户做视频画中画和叠加

内容来自[手机版]  (2017-03-18 19:31) 
效果你可以看下我传的视频,除了抖动引起左侧有一错位条纹外,其它还好。文字和图标叠加已实现。就是画图尺寸大会引起抖动这问题不知道怎么解决
回复

使用道具 举报

0

主题

4

回帖

10

积分

新手上路

积分
10
发表于 2017-11-4 13:37:27 | 显示全部楼层
楼主可以分享一下代码吗,参考一下,谢谢啦
回复

使用道具 举报

0

主题

4

回帖

10

积分

新手上路

积分
10
发表于 2017-11-15 21:26:20 | 显示全部楼层
楼主可以分享一下吗,谢谢??
回复

使用道具 举报

0

主题

4

回帖

10

积分

新手上路

积分
10
发表于 2017-11-15 21:30:21 | 显示全部楼层
能发一份源码吗?645875247@qq.com,不是免费的
回复

使用道具 举报

9

主题

42

回帖

69

积分

初级会员

大牛的形成也是时间与技术的积累

积分
69
QQ
 楼主| 发表于 2017-11-17 15:12:59 | 显示全部楼层
最近没搞这个了,好久没上论坛了,参考代码已发邮箱
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-19 20:32 , Processed in 0.051179 second(s), 33 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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