硬汉嵌入式论坛

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

[摄像头] 关于ov7670关闭再重新打开的问题

[复制链接]

1

主题

6

回帖

9

积分

新手上路

积分
9
发表于 2022-8-10 16:40:14 | 显示全部楼层 |阅读模式
今天用STM32H7测试ov7670功能的时候,打开显示都没有问题,但是关闭后再重新初始化打开,就会出现显示不全的问题(下半部分会停留在之前的画面),分别尝试了关闭存储设备(程序直接进入死循环)以及用GUI_CLEAR清除(还是出现之前的情况),有没有大神可以帮忙解答一下关于ov7670关闭时候的正确姿势呢
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 2022-8-11 14:24:07 | 显示全部楼层
你调用的是GUI_CLEAR, 那你应该用的是emWin吧,如果是emWin的话,此贴,我有做案例:

STM32H7的emWin6.x教程更新摄像头动态刷新章节(2022-01-10)
https://www.armbbs.cn/forum.php? ... d=110517&fromuid=58
(出处: 硬汉嵌入式论坛)



回复

使用道具 举报

1

主题

6

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2022-8-11 16:06:59 | 显示全部楼层
您写的几个例程我基本都看过了,今天也试了好多还是没有解决问题。
static void _cbDialog(WM_MESSAGE * pMsg)
{
        static  WM_HTIMER hTimerCAMERA,hTimerCAMERA1;
        int timerid;
       
        switch (pMsg->MsgId)
        {
                /* 接收到摄像头数据 */
                case WM_INIT_DIALOG:
                        hTimerCAMERA1 = WM_CreateTimer(pMsg->hWin, 1, 1000, 0);       
                        break;
                case MSG_CAMERA:
                        hTimerCAMERA = WM_CreateTimer(pMsg->hWin, ID_TimerCAMERA, 2, 0);       
                  WM_DeleteTimer(hTimerCAMERA1);       
                        break;
               
                case WM_TIMER:
                        /* 删除定时器 */
                        timerid = WM_GetTimerId(pMsg->Data.v);
                  if(timerid==ID_TimerCAMERA)
                        {

                        WM_DeleteTimer(hTimerCAMERA);               
                        /* 选择操作窗口 */
                        WM_SelectWindow(hWin_ov7670_Task);
                        /* Cache Clean和无效化 */
                        SCB_CleanInvalidateDCache();               
                        /* 绘制到多缓冲里面 */
                        GUI_MULTIBUF_Begin();
                        GUI_MEMDEV_WriteAt(hMem_ov7670, 79, 249);
                        GUI_MULTIBUF_End();               
                        WM_SelectWindow(WM_HBKWIN);
                        hTimerCAMERA1 = WM_CreateTimer(pMsg->hWin, 1, 100, 0);       
                        /* 开始下次绘制 */
                        if(cam_start_bit==1)
                              CAM_Start(uiDispMemAddr);               
                        }
                        else if(timerid==1)
                        {        if(cam_start_bit==1)                       
                                   {
                                                WM_RestartTimer(pMsg->Data.v,100);
                                                if(g_tCam.CaptureOk!=0)
                                                     CAM_Start(uiDispMemAddr);                                                                                       
                                                shuaxin_num=0;
                                         }
                                else
                                   {WM_RestartTimer(pMsg->Data.v,1000);
                                   }
                        }
                        break;
{...
case WM_INIT_DIALOG:
       hWin_ov7670_Task=Create_ov7670_Framewin();        
                   hMem_ov7670 = GUI_MEMDEV_CreateEx(0, 0, 320, 240, GUI_MEMDEV_NOTRANS);
             uiDispMemAddr = (uint32_t)GUI_MEMDEV_GetDataPtr(hMem_ov7670);
                         hWin_ov7670_Task_bit=1;                         
                   open_cam2_pwr();
           break;
  case WM_NOTIFY_PARENT:
    Id    = WM_GetId(pMsg->hWinSrc);
    NCode = pMsg->Data.v;
    switch(Id) {
    case ID_BUTTON_0:
                                        close_cam2_pwr();
                                        hWin_ov7670_Task_bit=0;
                                        GUI_EndDialog(hWin_ov7670_Task, 0);                                                          
                                        GUI_EndDialog(pMsg->hWin, 0);
                                        WM_ShowWindow(hstabarwin);

        break;
这是一部分的代码吧,现在的情况是打开摄像头后,是可以实现正常动态显示的,但是在按下button后,再重新进入页面,就会出现显示界面下半部分显示错误的情况,只有上面很少的一部分还可以显示
尝试过退出时删除存储设备,进来后重新打开,也没有用,监测dma_stream7_irqhandler可以看到还是能触发信号,产生MSG_CAMERA信号,怀疑可能是DMA重新进入数据缓存的问题?
PS:我尝试过先刷一帧CAM_START,然后再触发时用CAM1_START显示,但是那样就显示不出来了,不知道是什么情况


回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 2022-8-12 08:59:46 | 显示全部楼层
crushbaby 发表于 2022-8-11 16:06
您写的几个例程我基本都看过了,今天也试了好多还是没有解决问题。
static void _cbDialog(WM_MESSAGE * p ...

确保按下按钮后,emWin这部分的展示没问题吧,如这部分没问题,应该就是摄像头的复位初始化有问题了。
回复

使用道具 举报

1

主题

6

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2022-8-12 09:04:08 | 显示全部楼层
eric2013 发表于 2022-8-12 08:59
确保按下按钮后,emWin这部分的展示没问题吧,如这部分没问题,应该就是摄像头的复位初始化有问题了。

是的 按键显示等都比较正常,摄像头显示方面 上面几行还能显示,但是比较卡,下面大部分会锁死在之前的画面,曾经怀疑过是存储设备和坐标位移等问题,也考虑过是不是中断响应等问题,都一一排查过没什么问题,目前想看看DMA传的数据流是不是完整的一包,或者摄像头复位初始化方面,您有没有什么经验或者参考
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 2022-8-13 10:37:00 | 显示全部楼层
crushbaby 发表于 2022-8-12 09:04
是的 按键显示等都比较正常,摄像头显示方面 上面几行还能显示,但是比较卡,下面大部分会锁死在之前的画 ...

DMA的话,只要DMA传输完成中断正常执行,说明就没问题。
回复

使用道具 举报

1

主题

6

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2022-8-15 09:07:06 | 显示全部楼层
eric2013 发表于 2022-8-13 10:37
DMA的话,只要DMA传输完成中断正常执行,说明就没问题。

好的 谢谢硬汉哥 我在根据你的例子研究研究 可能是其他程序影响了
回复

使用道具 举报

1

主题

6

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2022-8-15 14:28:14 | 显示全部楼层
eric2013 发表于 2022-8-13 10:37
DMA的话,只要DMA传输完成中断正常执行,说明就没问题。

发现一个小bug吧,今天拿从V7裸机开发板跑了一下出厂程序,想看看摄像头这块,进去之后功能都没什么问题,但是按返回键返回到主界面后,屏幕就没有响应了,用调试程序跑了一下发现TOUCH_GetKey()中x,y地址读取出现了错误,进而导致屏幕无法响应。
又看了下摄像头的程序,发现你设计的关闭摄像头只是暂停了timer并没有对摄像头进行处理,而按下返回键后才调用camstop(),所以有没有可能是这块哪部分出现了问题,希望有时间您能研究解答一下,多谢
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 2022-8-16 00:18:14 | 显示全部楼层
crushbaby 发表于 2022-8-15 14:28
发现一个小bug吧,今天拿从V7裸机开发板跑了一下出厂程序,想看看摄像头这块,进去之后功能都没什么问题 ...

摄像头裸机的话,别用出厂程序,出厂程序好久没有升级过了,使用我发布的这两个裸机程序

image.png
回复

使用道具 举报

1

主题

6

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2022-8-16 09:11:18 | 显示全部楼层
eric2013 发表于 2022-8-16 00:18
摄像头裸机的话,别用出厂程序,出厂程序好久没有升级过了,使用我发布的这两个裸机程序

之前这几个已经参考过了,摄像头部分其实已经能正常使用了,现在比较纠结的是退出的时候应该关闭哪些东西才能保证系统能正常运行,有没有可能是关于dma关闭等方面的问题
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 2022-8-17 09:25:53 | 显示全部楼层
crushbaby 发表于 2022-8-16 09:11
之前这几个已经参考过了,摄像头部分其实已经能正常使用了,现在比较纠结的是退出的时候应该关闭哪些东西 ...

不用单独的关闭啊,我那个贼简单,采集一次,DMA2D刷新一次,采用的DMA的单次模式,不是循环一直刷新,这种的才需要你专门终止关闭。

采集完毕了,我哪里直接调用了HAL_DCMI_Stop,这个函数把DCMI和DMA都禁止了,非常方便。
下次启动,直接调用的CAM_Start和CAM_Start1。

[C] 纯文本查看 复制代码
/**
  * @brief  Disable DCMI DMA request and Disable DCMI capture  
  * @param  hdcmi: pointer to a DCMI_HandleTypeDef structure that contains
  *                the configuration information for DCMI. 
  * @retval HAL status     
  */
HAL_StatusTypeDef HAL_DCMI_Stop(DCMI_HandleTypeDef* hdcmi)
{
  register uint32_t count = HAL_TIMEOUT_DCMI_STOP * (SystemCoreClock /8/1000);
  HAL_StatusTypeDef status = HAL_OK;

  /* Process locked */
  __HAL_LOCK(hdcmi);
  
  /* Lock the DCMI peripheral state */
  hdcmi->State = HAL_DCMI_STATE_BUSY;

  /* Disable Capture */
  hdcmi->Instance->CR &= ~(DCMI_CR_CAPTURE);

  /* Check if the DCMI capture effectively disabled */
  do
  {
    if (count-- == 0)
    {
      /* Update error code */
      hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT;
      
      status = HAL_TIMEOUT;
      break;
    } 
  }
  while((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0);

  /* Disable the DCMI */
  __HAL_DCMI_DISABLE(hdcmi);

  /* Disable the DMA */
  HAL_DMA_Abort(hdcmi->DMA_Handle);

  /* Update error code */
  hdcmi->ErrorCode |= HAL_DCMI_ERROR_NONE;

  /* Change DCMI state */
  hdcmi->State = HAL_DCMI_STATE_READY;

  /* Process Unlocked */
  __HAL_UNLOCK(hdcmi);

  /* Return function status */
  return status;
}





回复

使用道具 举报

1

主题

6

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2022-8-17 09:51:33 | 显示全部楼层
eric2013 发表于 2022-8-17 09:25
不用单独的关闭啊,我那个贼简单,采集一次,DMA2D刷新一次,采用的DMA的单次模式,不是循环一直刷新,这 ...

昨天发现问题了,退出的时候dma没有关闭,一直传数据把缓冲传乱了,改好了,谢谢硬汉哥
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-26 03:44 , Processed in 0.200295 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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