OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5866|回复: 3

STM32F4驱动OV5640卡在EV6

[复制链接]

8

主题

67

帖子

0

精华

高级会员

Rank: 4

积分
589
金钱
589
注册时间
2016-3-1
在线时间
81 小时
发表于 2022-10-13 21:52:16 | 显示全部楼层 |阅读模式
1金钱
使用STM32F429驱动OV5640模块,在使用硬件I2C(PB8 PB9)驱动,始终无法正常读写,OV5640地址配置为0x78
现象:总线可以正常启动,但发送完从设备地址后,立马卡住,在EV6中无法跳过
I2C1读取OV5640代码如下:
  1. /**
  2.   * @brief  从 OV5640 寄存器中读取一个字节的数据
  3.   * [url=home.php?mod=space&uid=271674]@param[/url] Addr: 寄存器地址
  4.   * @retval 返回读取得的数据
  5.   */
  6. u8 OV5640_ReadReg(uint16_t Addr)
  7. {
  8.   uint32_t timeout = DCMI_TIMEOUT_MAX;
  9.   uint8_t Data = 0;

  10.         while(I2C_GetFlagStatus(CAMERA_I2C, I2C_FLAG_BUSY))
  11.                 if((timeout--) == 0)        return 0xFF;
  12.                
  13.         //1.开始【发送】--* Generate the Start Condition *
  14.         I2C_GenerateSTART(CAMERA_I2C, ENABLE);                        //启动I2C STM32进入主模式 标志:SR1->SB 0-1
  15.         //----* Test on CAMERA_I2C EV5 and clear it *
  16.         timeout = DCMI_TIMEOUT_MAX; //----* Initialize timeout value *
  17.         while (!I2C_CheckEvent(CAMERA_I2C, I2C_EVENT_MASTER_MODE_SELECT))
  18.         { //----* If the timeout delay is exeeded, exit with error code *
  19.           if ((timeout--) == 0) return 0xFF;               
  20.         }
  21.   
  22.         //2.发送从设备地址 - 主发送--* Send DCMI selcted device slave Address for write *
  23.         I2C_Send7bitAddress(CAMERA_I2C, OV5640_DEVICE_ADDRESS, I2C_Direction_Transmitter);                                        //启动I2C STM32发送从地址 标志:SR1->ADDR 0-1 【一直收不到】//执行完此句后,EV5结束,DR被赋值,SB1被重置
  24.         //20220922 受https://shequ.stmicroelectronics.cn/forum.php?mod=viewthread&tid=602816启发,需排查此步后,EV5对应的A如何检测?标志是啥
  25.         //----* Test on I2C1 EV6 and clear it *
  26.         timeout = DCMI_TIMEOUT_MAX; //----* Initialize timeout value *
  27.         while (!I2C_CheckEvent(CAMERA_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  28.         {//----* If the timeout delay is exeeded, exit with error code *
  29.                 if ((timeout--) == 0) return 0xFF;                //[卡在这行,读取ID时
  30.         }

  31. LED1_GREEN_ON;                                //LED1绿灯亮
  32.   
  33.         //3.1        发送寄存器地址--* Send I2C1 location address MSB *
  34.         I2C_SendData( CAMERA_I2C, (uint8_t)((Addr>>8) & 0xFF) );        //【存疑】是否分2次发???
  35.         //----* Test on I2C1 EV8 and clear it *
  36.         timeout = DCMI_TIMEOUT_MAX; //----* Initialize timeout value *
  37.         while (!I2C_CheckEvent(CAMERA_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  38.         { //----* If the timeout delay is exeeded, exit with error code *
  39.           if ((timeout--) == 0) return 0xFF;
  40.         }
  41.         //----* Clear AF flag if arised *
  42.         CAMERA_I2C->SR1 |= (uint16_t)0x0400;

  43.         //3.2        发送寄存器地址--* Send I2C1 location address LSB *
  44.         I2C_SendData( CAMERA_I2C, (uint8_t)(Addr & 0xFF) );
  45.         //----* Test on I2C1 EV8 and clear it *
  46.         timeout = DCMI_TIMEOUT_MAX; //----* Initialize timeout value *
  47.         while (!I2C_CheckEvent(CAMERA_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  48.         { //----* If the timeout delay is exeeded, exit with error code *
  49.           if ((timeout--) == 0) return 0xFF;
  50.         }
  51.         //----* Clear AF flag if arised *
  52.         CAMERA_I2C->SR1 |= (uint16_t)0x0400;

  53.         //4.开始【接收】--* Generate the Start Condition *
  54.         I2C_GenerateSTART(CAMERA_I2C, ENABLE);
  55.         //----* Test on I2C1 EV6 and clear it *
  56.         timeout = DCMI_TIMEOUT_MAX; //----* Initialize timeout value *
  57.         while (!I2C_CheckEvent(CAMERA_I2C, I2C_EVENT_MASTER_MODE_SELECT))
  58.         {        //----* If the timeout delay is exeeded, exit with error code *  
  59.           if ((timeout--) == 0) return 0xFF;
  60.         }

  61.         //5.发送从设备地址 - 主接收,读取命令--* Send DCMI selcted device slave Address for write *
  62.         I2C_Send7bitAddress(CAMERA_I2C, OV5640_DEVICE_ADDRESS, I2C_Direction_Receiver);
  63.         //----* Test on I2C1 EV6 and clear it *
  64.         timeout = DCMI_TIMEOUT_MAX; //----* Initialize timeout value *
  65.         while (!I2C_CheckEvent(CAMERA_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
  66.         { //----* If the timeout delay is exeeded, exit with error code *
  67.           if ((timeout--) == 0) return 0xFF;
  68.         }
  69.         //----* Prepare an NACK for the next data received *
  70.         I2C_AcknowledgeConfig(CAMERA_I2C, DISABLE);
  71.         //----* Test on I2C1 EV7 and clear it *
  72.         timeout = DCMI_TIMEOUT_MAX; //----* Initialize timeout value *
  73.         while (!I2C_CheckEvent(CAMERA_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED))
  74.         {
  75.           //----* If the timeout delay is exeeded, exit with error code *
  76.           if ((timeout--) == 0) return 0xFF;
  77.         }
  78.         //----* Prepare Stop after receiving data *
  79.         I2C_GenerateSTOP(CAMERA_I2C, ENABLE);
  80.         //----* Receive the Data *
  81.         Data = I2C_ReceiveData(CAMERA_I2C);
  82.         //----* return the read data *
  83.         return Data;
  84. }
复制代码


我被这个问题困扰很久了,我特意还用I2C2驱动MPU6050 QMC5883两个模块都可以正常驱动。
我把I2C1(OV5640)    I2C2(MPU6050 QMC5883)在EV6验证时的截图如下:
这是I2C1的,有问题的

【故障】I2C1

【故障】I2C1

这是I2C2的,正常运行的

【正常】I2C2

【正常】I2C2

最佳答案

查看完整内容[请看2#楼]

PA8是MCO脚 可以不用定时器输出个频率出来的
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

13

主题

250

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2251
金钱
2251
注册时间
2019-8-7
在线时间
364 小时
发表于 2022-10-13 21:52:17 | 显示全部楼层
feiyinglala 发表于 2022-10-16 17:50
经调试,原来是因为OV5640的XCLK未输入时钟,所以摄像头处于停工状态,我把TIM1-CH2的PWM输出到XCLK就好了
...

PA8是MCO脚 可以不用定时器输出个频率出来的
回复

使用道具 举报

8

主题

67

帖子

0

精华

高级会员

Rank: 4

积分
589
金钱
589
注册时间
2016-3-1
在线时间
81 小时
 楼主| 发表于 2022-10-16 17:50:38 | 显示全部楼层
本帖最后由 feiyinglala 于 2022-10-16 17:53 编辑

经调试,原来是因为OV5640的XCLK未输入时钟,所以摄像头处于停工状态,我把TIM1-CH2的PWM输出到XCLK就好了
XCLK对应PA8引脚,配置如下
  1. //-----***使用PA8***       
  2.         GPIO_InitStructure.GPIO_Pin = MCO_XCLK_GPIO_PIN ;       
  3.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  4.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  5.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  6.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  7.         GPIO_Init(MCO_XCLK_GPIO_PORT, &GPIO_InitStructure);
  8.         GPIO_ResetBits(MCO_XCLK_GPIO_PORT,MCO_XCLK_GPIO_PIN);
  9.         GPIO_PinAFConfig(MCO_XCLK_GPIO_PORT, MCO_XCLK_PINSOURCE, GPIO_AF_TIM1);//MCO_XCLK_AF);        //¸′óÃ
  10.         //RCC_MCO1Config(RCC_MCO1Source_PLLCLK, RCC_MCO1Div_1);        //ê1ÄüMCOê±Öó
  11.         TIM1_Config();    //配置为PWM输出
复制代码


回复

使用道具 举报

8

主题

67

帖子

0

精华

高级会员

Rank: 4

积分
589
金钱
589
注册时间
2016-3-1
在线时间
81 小时
 楼主| 发表于 2022-10-24 22:32:28 | 显示全部楼层
远命 发表于 2022-10-17 08:49
PA8是MCO脚 可以不用定时器输出个频率出来的

嗯,我后来改用MCO的专用功能输出了,实用代码如下
        GPIO_InitStructure.GPIO_Pin = MCO_XCLK_GPIO_PIN ;       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_Init(MCO_XCLK_GPIO_PORT, &GPIO_InitStructure);

        GPIO_PinAFConfig(MCO_XCLK_GPIO_PORT, MCO_XCLK_PINSOURCE, MCO_XCLK_AF);        //¸′óÃ
        RCC_MCO1Config(RCC_MCO1Source_HSI, RCC_MCO1Div_5);        //ê1ÄüMCOê±Öó
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-16 20:59

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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