ov7670 正点原子摄像头 V2.2版 sccb读取是0xff ???

2019-07-24 13:52发布

现在在捣鼓这个ov7670 v2.2 带fifo的摄像头,目前通过sccb进行读写测试时,写摄像头有应答,可以; 但是读出来的数据全部是0xff,

SCCB->SCL   外部已经加了上4.7K拉电阻
SCCB->SDA   外部已经加了上4.7K拉电阻
程序如下:

#define SCCB_ID   0X42   //OV7670的ID
#define SCCB_SEND_ACK (0x10) #define SCCB_SEND_NACK (0x11)  
#define SCCB_STATE_NACK (0x20) #define SCCB_STATE_ACK  (0x21)

#define SCCB_SCL  GPIOEout(2)        // 定义 I2C-SCL 为 GPIOE_Pin_2 #define SCCB_SDA  GPIOEout(3)        // 定义 I2C-SDA 为 GPIOE_Pin_3
#define SCCB_SCL_L   (SCCB_SCL=0)    //#define I2C1_SCL_L         GPIOB->BSRRL = GPIO_Pin_6 #define SCCB_SCL_H   (SCCB_SCL=1)    //#define I2C1_SCL_H         GPIOB->BSRRH = GPIO_Pin_6
#define SCCB_SDA_L   (SCCB_SDA=0)    //#define I2C1_SDA_L         GPIOB->BSRRL = GPIO_Pin_7 #define SCCB_SDA_H   (SCCB_SDA=1)    //#define I2C1_SDA_H         GPIOB->BSRRH = GPIO_Pin_7       #define SCCB_SDA_IN()  GPIOEin(3) #define SCCB_SDA_OUT() GPIOEout(3)       #define SCCB_SDA_READ      ((GPIOE->IDR)  & GPIO_Pin_3)




void SCCB_Delay(u16 i) {            while(i--);  }


#define SCCB_Delay_5us     SCCB_Delay(8) #define SCCB_Delay_3us     SCCB_Delay(6) #define SCCB_Delay_2us     SCCB_Delay(4) #define SCCB_Delay_1us     SCCB_Delay(2)


void SCCB_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; //SCCB  SCL->E2, SDA->E3   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOE, &GPIO_InitStructure);
SCCB_SCL_H; SCCB_Delay_5us; SCCB_Delay_5us; SCCB_SDA_H; SCCB_Delay_5us;          }

/********************************************************** 启动子程序 在 SCL 高电平期间 SDA 发生负跳变【从高到低】 scl为高电平期间,sda产生一个下降沿  **********************************************************/ u8 SCCB_Start(void) {   u8 i; SCCB_SDA_H;   SCCB_SCL_H; SCCB_Delay_5us;    i=0; while((SCCB_SDA_READ == 1) && (i<250)) //如果SCCB_SDA=1,表示被控器无应答或损坏 { i++; //计时开始, if(i==249) //如果计时到了249,器件还没有应答则自动退出 return (SCCB_STATE_NACK); }           SCCB_SDA_L;   SCCB_Delay_5us; i=0; while((SCCB_SDA_READ == 1) && (i<250)) //如果SCCB_SDA=1,表示被控器无应答或损坏 { i++; //计时开始, if(i==249) //如果计时到了249,器件还没有应答则自动退出 return (SCCB_STATE_NACK); }        SCCB_SCL_L;   SCCB_Delay_2us;      return SCCB_STATE_ACK; //SUCCESS; }

/********************************************************** 停止子函数 在 SCL 高电平期间 SDA 发生正跳变 【从低到高】 scl高电平期间,sda产生一上升沿  **********************************************************/ void SCCB_Stop(void) {   SCCB_SDA_L;   SCCB_Delay_1us; SCCB_SCL_H; SCCB_Delay_5us; SCCB_SDA_H;   SCCB_Delay_3us; }

/********************************************************** //读一字节 ack: SCCB_SEND_ACK 时应答,SCCB_SEND_NACK 时不应答  **********************************************************/ u8 SCCB_ReadByte(unsigned char ack) //【非常好】 { u8 i = 0,Read_Data=0;   SCCB_SDA_H;   SCCB_SDA_IN(); //设置SDA为输入   for(i=0;i<8;i++)          // 循环移入8个位 {      SCCB_Delay_1us;          //5us     SCCB_SCL_L;     SCCB_Delay_5us;     SCCB_SCL_H; SCCB_Delay_5us;     Read_Data <<= 1;      if(SCCB_SDA_READ)        //读SDA {       Read_Data++; } }   SCCB_SCL_L;   SCCB_Delay_3us;      //5us   SCCB_SDA_OUT(); //设置SDA为输出     SCCB_Delay_3us;      //5us   if(ack == SCCB_SEND_ACK)  SCCB_SDA_L;       //发送应答   else     SCCB_SDA_H;       //发送非应答      SCCB_Delay_2us;      //5us SCCB_SCL_H;   SCCB_Delay_5us;   SCCB_SCL_L;   SCCB_Delay_1us;      //5us return (Read_Data); }

/********************************************************** //向总线写一字节,并返回有无应答  **********************************************************/ unsigned char SCCB_WriteByte(unsigned char write_data) {   unsigned char i;   for(i=0;i<8;i++)   {     if(write_data & 0x80)      SCCB_SDA_H;     else      SCCB_SDA_L;           SCCB_Delay_1us;     SCCB_SCL_H;     //置时钟线为高,通知被控器开始接收数据位      SCCB_Delay_5us;     SCCB_SCL_L;     write_data <<= 1;         } SCCB_SDA_IN(); //设置SDA为输入   SCCB_Delay_2us;   SCCB_SDA_H;   SCCB_Delay_2us;   SCCB_SCL_H;   SCCB_Delay_3us;    i=0; while((SCCB_SDA_READ == 1) && (i<250)) //如果SCCB_SDA=1,表示被控器无应答或损坏 { i++; //计时开始, if(i==249) //如果计时到了249,器件还没有应答则自动退出 return (SCCB_STATE_NACK); }
SCCB_SCL_L; SCCB_Delay_2us; SCCB_SDA_OUT(); //设置SDA为输出   return (SCCB_STATE_ACK);   }

//写寄存器 //返回值:SCCB_STATE_ACK->成功; SCCB_STATE_NACK->失败. u8 SCCB_WR_Reg(u8 reg,u8 data) { u8 res = SCCB_STATE_NACK; SCCB_Start(); //启动SCCB传输 res=SCCB_WriteByte(SCCB_ID); //写器件ID if(SCCB_STATE_NACK == res) res=1;   if(SCCB_STATE_NACK == SCCB_WriteByte(reg)) res=1;    if(SCCB_STATE_NACK == SCCB_WriteByte(data)) res=1;   SCCB_Stop();     return res; }

//读寄存器 //返回值:读到的寄存器值 u8 SCCB_RD_Reg(u8 reg) { u8 val=0; SCCB_Start(); //启动SCCB传输 printexp(USART1, "DCMI_id",SCCB_WriteByte(SCCB_ID),16) ; //写器件ID  
  //SCCB_WriteByte(reg); //写寄存器地址    printexp(USART1, "DCMI_reg",SCCB_WriteByte(reg),16) ; SCCB_Stop();    SCCB_Delay_5us;
 
//设置寄存器地址后,才是读 SCCB_Start(); //SCCB_WriteByte(SCCB_ID|0X01); //发送读命令   printexp(USART1, "SCCB_ID|0X01",SCCB_WriteByte(SCCB_ID|0X01),16) ;   val=SCCB_ReadByte(SCCB_SEND_NACK); //读取数据   SCCB_Stop(); printexp(USART1, "SCCB_val",val,16) ;   return val; }


//初始化成功返回0,否则返回1 u8 Cam_Init(void) { u8 temp; u16 i=0; GPIO_InitTypeDef GPIO_InitStructure; DCMI_InitTypeDef DCMI_InitStructure; //DMA_InitTypeDef  DMA_InitStructure;
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE); //DCMI  //RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); //DMA2 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |  RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE, ENABLE);//使能DCMI的GPIO时钟
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI); //DCMI D0 GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI); //DCMI D1 GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_DCMI); //DCMI D2 GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_DCMI); //DCMI D3 GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_DCMI); //DCMI D4 GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI); //DCMI D5 GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_DCMI); //DCMI D6 GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_DCMI); //DCMI D7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6; GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_Init(GPIOB, &GPIO_InitStructure); //---------------------------------------控制信号引脚定义--------------------------------------- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4| GPIO_Pin_6| GPIO_Pin_8; //DCMI 2->WRST, 3->RRST, 4->WEN, 6->RCLK, 8->OE(CS) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //SYSCFG->CMPCR = 0x00000001; //使用IO 补偿单元, //当GPIO 速度超过50M 的时候要考虑使用此设置 GPIO_Init(GPIOA, &GPIO_InitStructure); //--------------VSYNC IN --------------------------------- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //DCMI VSYNC GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //同步信号检测IO GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //SYSCFG->CMPCR = 0x00000001; GPIO_Init(GPIOB, &GPIO_InitStructure); DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous; DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware; DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Falling; DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High; DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_High; DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame; DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b; DCMI_Init(&DCMI_InitStructure);

/*   DMA_DeInit(DMA2_Stream1);   DMA_InitStructure.DMA_Channel = DMA_Channel_1;   DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;   DMA_InitStructure.DMA_Memory0BaseAddr = FSMC_LCD_ADDRESS;   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;   DMA_InitStructure.DMA_BufferSize = 1;   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;   DMA_InitStructure.DMA_Priority = DMA_Priority_High;   DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;   DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;   DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;   DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;     DMA_Init(DMA2_Stream1, &DMA_InitStructure); */   SCCB_Init();         //初始化SCCB 的IO口    temp = SCCB_WR_Reg(0x12,0x80);   if(SCCB_STATE_NACK == temp)  return 1; //复位SCCB   delay_ms(50);  //读取产品型号   temp=SCCB_RD_Reg(0x0b);                               //就是这里,通过SCcB读取时,数据总是0xff,不知道河谷???? printexp(USART1, "DCMI_0X0B",temp,16) ;    //读取的数据发回给电脑查看 if(temp!=0x73)  return 2;     temp=SCCB_RD_Reg(0x0a);    if(temp!=0x76)  return 2; //初始化序列   for(i=0;i<sizeof(ov7670_init_reg_tbl)/sizeof(ov7670_init_reg_tbl[0])/2;i++) { SCCB_WR_Reg(ov7670_init_reg_tbl[0],ov7670_init_reg_tbl[1]); delay_ms(2);   } return 0x00; //OK }









友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。