stmf407 + ov7670

2019-07-21 03:54发布

手里有探索者开发板和ov7670摄像头,目的是制作一个照相机。ov7670是没有fifo和晶振。

在对ov7670初始化时,写寄存器没问题(因为返回值正常),但是在读寄存器时,总是卡在写读取命令(打印printf(" step-02 ");),截图上传。

部分代码:
unsigned char bsp_sccbWrReg(unsigned char reg, unsigned char dat)
{   
    bsp_sccbStart();
    if(bsp_sccbWrByte(SCCB_ID))
    {
        bsp_sccbStop();
        return (1);
    }   
    bsp_delayUs(100);   //100us
    if(bsp_sccbWrByte(reg))
    {
        bsp_sccbStop();
        return (1);
    }
    bsp_delayUs(100);   //100us
    if(bsp_sccbWrByte(dat))
    {
        bsp_sccbStop();               
        return (1);
    }
    bsp_sccbStop();

    return (0);
}


unsigned char bsp_sccbRdReg(unsigned char reg, unsigned char *val)
{   
    bsp_sccbStart();
    if(bsp_sccbWrByte(SCCB_ID))
    {
        bsp_sccbStop();
                printf(" step-00 ");
        return (1);
    }
    bsp_delayUs(100);   //100us
    if(bsp_sccbWrByte(reg))
    {
        bsp_sccbStop();
                printf(" step-01 ");
        return (1);
    }
        bsp_sccbStop();
       
    bsp_delayUs(50);   //100us

    bsp_sccbStart();
    if(bsp_sccbWrByte(SCCB_ID | 0x01))
    {
        bsp_sccbStop();
                printf(" step-02 ");
        return (1);
    }
    bsp_delayUs(100);   //100us
    *val = bsp_sccbRdByte();
    bsp_sccbNoAck();
    bsp_sccbStop();

    return (0);
}


uint8_t bsp_ov7670Init(void)
{
    uint8_t ucDatH = 0, ucDatL = 0;
    uint16_t usManuID = 0, usProdID = 0;
    uint16_t i = 0;

    GPIO_InitTypeDef GPIO_InitStruct;

    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOG_CLK_ENABLE();

    /*Configure GPIO pins  */
    GPIO_InitStruct.Pin = OV7670_PWDN_Pin | OV7670_RST_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

    ov7670_XCLK_ON();  //提供XCLK

    OV7670_PWDN(0);    //正常工作模式
    bsp_delayMs(10);
    OV7670_RST(0);     //硬件复位OV7670
    bsp_delayMs(10);
    OV7670_RST(1);     //结束复位

    bsp_sccbInit();
       
    //bsp_sccbWrReg(OV7670_SENSOR_COM7, 0x80); //软复位
    if(bsp_sccbWrReg(OV7670_SENSOR_COM7, 0x80))
    {
            printf(" Software reset fault. ");
        return(1);
    }
    bsp_delayMs(50);
    if(bsp_sccbRdReg(OV7670_SENSOR_MIDH, &ucDatH))//读取厂家ID 高八位
    {
            printf(" Get MID_H fault. ");
        return(1);
    }
    if(bsp_sccbRdReg(OV7670_SENSOR_MIDL, &ucDatL))//读取厂家ID 低八位
    {
            printf(" Get MID_L fault. ");
        return(1);
    }
    usManuID = ucDatH;
    usManuID = (usManuID << 8) | ucDatL;
    if(usManuID != OV7670_MID)
    {
        printf(" MID: %x ", usManuID);
        return(2);
    }

    if(bsp_sccbRdReg(OV7670_SENSOR_PID, &ucDatH))//读取产品ID 高八位
    {
        return(3);
    }
    if(bsp_sccbRdReg(OV7670_SENSOR_VER, &ucDatL))//读取产品ID 低八位
    {
        return(3);
    }
    usProdID = ucDatH;
    usProdID = (usProdID << 8) | ucDatL;
    if(usProdID != OV7670_HID)
    {
        printf(" HID: %x ", usProdID);
        return(4);
    }

    /* 初始化OV7670各个寄存器 */
    for(i = 0; i < sizeof(ov7670_sxga_init_reg_tbl)/2; i++)
    {
        bsp_sccbWrReg(ov7670_sxga_init_reg_tbl[i][0], ov7670_sxga_init_reg_tbl[i][1]);
    }

    return 0;
}

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
3条回答
hu25886
1楼-- · 2019-07-21 09:04
代码已经能够正确读取ID号,初步怀疑是硬件问题(因为换一个硬件就可以正确读出)。这里面还有几个问题,也给遇到同样问题的小伙伴一个参考吧。
1、某宝购买了2款OV7670模块,一款是背后贴片个些许电容(该款测试不通过);一款是背后光秃秃的,只留下晶振焊接引脚(该款测试通过)。两款有什么实质性的区别我不清楚,因为他们的资料都是一样的(一样的乱),大家注意甄别吧。
2、以测试通过的说明。在进行sccb协议读写OV7670寄存器时,XCLK引脚一定要接。我这里使用了MCO1,HSI源5分频。16M/5,后续遇到时钟问题在进行补充。
3、sccb协议的问题。利用示波器查看SCL、SDA波形,发现写寄存器时,发送的数据第9位并没有拉低。在查看各位大神的代码和sccb协议资料都有说明第9位会被sccb从设备拉低,这个问题待解决。
4、我将进行后续的实验,遇到问题及解决将及时告知大家。
下面的图片是上面文字叙述的证据。
hu25886
2楼-- · 2019-07-21 12:11
提供了16M时钟,HSI作为原时钟提供。现在身边没有示波器,不知道有没有正确提供时钟。
想知道,利用SCCB协议读写寄存器时,需要提供XCLK吗?
peng1554
3楼-- · 2019-07-21 17:04
 精彩回答 2  元偷偷看……

一周热门 更多>