基于stm32f103c8的正点原子ov7670摄像头上位机显示问题

2019-07-25 11:43发布

小弟最近在做小车,需要用摄像头输出黑白的图像,也就是让摄像头输出YUV格式,用的mcu是stm32f103c8t6,摄像头就是正点原子的带fifo的ov7670,已经做一周了!但是用串口通信输出到电脑上,就算把摄像头盖子盖上,Y输出的也不都全是0x00或者0xff,真的是快要疯掉了。这周每晚都熬到三点多,白天要上课没时间做,但是还是没做出来,真的要疯掉了。。。我用的代码就是原子哥http://www.openedv.com/posts/list/23685.htm这个链接里的代码,寄存器配置都和他的一样,可是就是不成功。哪位好心大哥能帮我看一下代码吗?帮帮小弟!搞不出来摄像头心情真的非常差,整个人每天都没什么精神,求哪位大哥帮帮小弟看看代码吧!
代码里我写的是ov7225,大哥们自动忽略,其实用的是7670,摄像头就是在原子哥店铺里买的那个。
//*****************************GPIO口使用
//PA0   VSYNC场中断信号输入,floating输入
//PA1   WE写使能,推挽输出,50MHZ
//PA5  WRST写指针复位,推挽输出,50MHZ
//PA2  RRST读指针复位,推挽输出,50MHZ
//PA3  OE读使能,推挽输出,50MHZ
//PA4  RCLK读指针复位,推挽输出,50MHZ
//PB8~15   D0~7数据输入端,上拉输入
//PC14  SCL
//PC13  SDA
//*******************************以下是主函数
#include "stm32f10x.h"
#include "bsp_ov7725.h"
#include "usart.h"
#include "stdint.h"
#include "delay.h"
extern u8 Ov7725_vsync; 
uint16_t i,j;
u16 Y;
int main(void)
{
  Ov7725_vsync = 0;
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
Ov7725_GPIO_Config();//初始化GPIO口
uart_init(115200);  //上位机显示,与电脑通信时波特率是115200
while(SCCB_SUCCESS());//初始化7670寄存器,配置为yuv输出
VSYNC_Init();//配置场中断

FIFO_CS_L;   //拉低OE,使读使能

while(1)
{
if( Ov7725_vsync == 2 )
{

FIFO_RRST=0;
FIFO_RCLK_L;
FIFO_RCLK_H;
FIFO_RCLK_L;
FIFO_RRST=1;
FIFO_RCLK_H;



for(i=0;i<240;i++)
{
for(j=0;j<320;j++)
{
FIFO_RCLK_L;
Y=((GPIOB->IDR&0xff00)>>8);//因为用的是GPIOB的8~15口,所以要与0XFF00后右移八位
FIFO_RCLK_H;

FIFO_RCLK_L;//不用读UV
FIFO_RCLK_H;

USART_SendData(USART1,Y);//发送给电脑
delay_us(200);

}
}
  Ov7725_vsync = 0;
}
}

}



//*******************************以下是各个函数
//*******************************bsp_ov7725.c
#include "bsp_ov7725.h"
#include "sys.h"
#include "delay.h"
#include "usart.h"
const u8 ov7670_init_reg_tbl_YUV[][2]= 
{   


{0x12, 0x10},
{0x3a, 0x14},
{0x3d, 0x80},
//0         0       :      Y U Y V (3a:14 3d:80)
//0         1       :      Y V Y U  (3a:14 3d:81)
//1         0       :      U Y V Y (3a:18 3d:80)
//1         1       :      V Y U Y (3a:18 3d:81)
{0x67, 0x11}, //手工设置 U
{0x68, 0xFF}, //手工设置 V
{0x40, 0xC0}, //YUV输出




{0x32, 0x80}, //HREF
{0x17, 0x16},  //HSTART      
{0x18, 0x04},//HSTOP
{0x19, 0x02},//VSTRT
{0x1a, 0x7a},//0x7a, VSTOP
  {0x03, 0x0a},//0x0a, VREF


{0x0c, 0x0c},
{0x15, 0x00},
{0x3e, 0x00},//10
{0x70, 0x00},
{0x71, 0x01},
{0x72, 0x11},
{0x73, 0x09},//
        
{0xa2, 0x02},//15
{0x11, 0x00},//?±??·????è??,0,??·???.
{0x7a, 0x20},
{0x7b, 0x1c},
{0x7c, 0x28},
        
{0x7d, 0x3c},//20
{0x7e, 0x55},
{0x7f, 0x68},
{0x80, 0x76},
{0x81, 0x80},
        
{0x82, 0x88},
{0x83, 0x8f},
{0x84, 0x96},
{0x85, 0xa3},
{0x86, 0xaf},
        
{0x87, 0xc4},//30
{0x88, 0xd7},
{0x89, 0xe8},
{0x13, 0xe0},
{0x00, 0x00},//AGC
        
{0x10, 0x00},
{0x0d, 0x00}, 
{0x14, 0x20},//0x38, limit the max gain
{0xa5, 0x05},
{0xab, 0x07},
        
{0x24, 0x75},//40
{0x25, 0x63},
{0x26, 0xA5},
{0x9f, 0x78},
{0xa0, 0x68},
        
{0xa1, 0x03},//0x0b,
{0xa6, 0xdf},//0xd8,
{0xa7, 0xdf},//0xd8,
{0xa8, 0xf0},
{0xa9, 0x90},
        
{0xaa, 0x94},//50
{0x13, 0xe5},
{0x0e, 0x61},
{0x0f, 0x4b},
{0x16, 0x02},
        
{0x1e, 0x27},//????????????????.0x07,
{0x21, 0x02},
{0x22, 0x91},
{0x29, 0x07},
{0x33, 0x0b},
        
{0x35, 0x0b},//60
{0x37, 0x1d},
{0x38, 0x71},
{0x39, 0x2a},
{0x3c, 0x78},
        
{0x4d, 0x40},
{0x4e, 0x20},
{0x69, 0x5d},
{0x6b, 0x40},//PLL*4=48Mhz
{0x74, 0x19},
{0x8d, 0x4f},
        
{0x8e, 0x00},//70
{0x8f, 0x00},
{0x90, 0x00},
{0x91, 0x00},
{0x92, 0x00},//0x19,//0x66
        
{0x96, 0x00},
{0x9a, 0x80},
{0xb0, 0x84},
{0xb1, 0x0c},
{0xb2, 0x0e},
        
{0xb3, 0x82},//80
{0xb8, 0x0a},
{0x43, 0x14},
{0x44, 0xf0},
{0x45, 0x34},
        
{0x46, 0x58},
{0x47, 0x28},
{0x48, 0x3a},
{0x59, 0x88},
{0x5a, 0x88},
        
{0x5b, 0x44},//90
{0x5c, 0x67},
{0x5d, 0x49},
{0x5e, 0x0e},
{0x64, 0x04},
{0x65, 0x20},
        
{0x66, 0x05},
{0x94, 0x04},
{0x95, 0x08},
{0x6c, 0x0a},
{0x6d, 0x55},
        
        
{0x4f, 0x80},
{0x50, 0x80},
{0x51, 0x00},
{0x52, 0x22},
{0x53, 0x5e},
{0x54, 0x80},
        
//{0x54, 0x40},//110
        
        
{0x09, 0x03},//????????×??ó

{0x6e, 0x11},//100
{0x6f, 0x9f},//0x9e for advance AWB
    {0x55, 0x00},//????
    {0x56, 0x40},//??±???
    {0x57, 0x80},//0x40,  change according to Jim's request
}; 
u8 Ov7725_vsync=0;
/************************************************
配置FIFO的端口
 ************************************************/
static void FIFO_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC  , ENABLE);

/*PA1(FIFO_WEN--FIFO写使能*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
    GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_1);

/*PA5(FIFO_WRST--FIFO写复位*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_5);

/*PA2(FIFO_RRST--FIFO读复位) PA3(FIFO_OE--FIFO输出使能)*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3); 

/*PA4(FIFO_RCLK-FIFO读时钟*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4);

    /*PB8-PB15(FIFO_DATA--FIFO)数据输出*/
    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

}


void Ov7725_GPIO_Config(void)
{
FIFO_GPIO_Config();
SCCB_Init();
}



/************************************************
场中断配置
 ************************************************/
static void VSYNC_GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  /*PA0---VSYNC*/

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

/************************************************
场中断配置
 ************************************************/
static void VSYNC_NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/************************************************
场中断配置
 ************************************************/

static void VSYNC_EXTI_Configuration(void)
{
    EXTI_InitTypeDef EXTI_InitStructure;

    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);//PA0挂靠到EXTI0线上
    EXTI_InitStructure.EXTI_Line = EXTI_Line0;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ; 
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

}

/************************************************
场中断配置
 ************************************************/
void VSYNC_Init(void)
{

    VSYNC_GPIO_Configuration();
    VSYNC_EXTI_Configuration();
VSYNC_NVIC_Configuration();


    
}

/************************************************
SCCB
 ************************************************/

void SCCB_Init(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //????PB?????±??

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; // PC13
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
  GPIO_Init(GPIOC, &GPIO_InitStructure); //PC13 SDA
  GPIO_SetBits(GPIOC,GPIO_Pin_13); // 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; // SCL
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure); //
  GPIO_SetBits(GPIOC,GPIO_Pin_14); // 
 
SCCB_SDA_OUT();
}



u8 SCCB_SUCCESS(void)
{
    u8 temp;
u16 i=0;
  if(SCCB_WR_Reg(0x12,0x80))return 1; //
delay_ms(50); 
  temp=SCCB_RD_Reg(0x0b);   
if(temp!=0x73)return 2;  
  temp=SCCB_RD_Reg(0x0a);   
if(temp!=0x76)return 2;
for(i=0;i<(sizeof(ov7670_init_reg_tbl_YUV)/sizeof(ov7670_init_reg_tbl_YUV[0])/2);i++)   ///sizeof(ov7670_init_reg_tbl_YUV[0])/2
{
SCCB_WR_Reg(ov7670_init_reg_tbl_YUV[0],ov7670_init_reg_tbl_YUV[1]);
delay_ms(2);
}

}
    return 0; //ok
}


u8 SCCB_WR_Reg(u8 reg,u8 data)
{
u8 res=0;
SCCB_Start(); 
if(SCCB_WR_Byte(SCCB_ID))res=1; 
delay_us(100);
  if(SCCB_WR_Byte(reg))res=1; 
delay_us(100);
  if(SCCB_WR_Byte(data))res=1; 
  SCCB_Stop();  
  return res;
}

void SCCB_Start(void)
{
    SCCB_SDA=1;     
    SCCB_SCL=1;     
    delay_us(50);  
    SCCB_SDA=0;
    delay_us(50);  
    SCCB_SCL=0;     
}

u8 SCCB_WR_Byte(u8 dat)
{
u8 j,res;  
for(j=0;j<8;j++) //循环发送八位
{
if(dat&0x80)SCCB_SDA=1;
else SCCB_SDA=0;
dat<<=1;
delay_us(50);
SCCB_SCL=1;
delay_us(50);
SCCB_SCL=0;   
}  
SCCB_SDA_IN(); // 
delay_us(50);
SCCB_SCL=1; /
delay_us(50);
if(SCCB_READ_SDA)res=1;  //
else res=0;         //
SCCB_SCL=0;  
SCCB_SDA_OUT(); //  
return res;  
}


void SCCB_Stop(void)
{
    SCCB_SDA=0;
    delay_us(50);  
    SCCB_SCL=1;
    delay_us(50); 
    SCCB_SDA=1;
    delay_us(50);
}


u8 SCCB_RD_Reg(u8 reg)
{
u8 val=0;
SCCB_Start(); //
SCCB_WR_Byte(SCCB_ID); //
delay_us(100);  
  SCCB_WR_Byte(reg); //
delay_us(100);  
SCCB_Stop();   
delay_us(100);   

SCCB_Start();
SCCB_WR_Byte(SCCB_ID|0X01); //
delay_us(100);
  val=SCCB_RD_Byte(); //
  SCCB_No_Ack();
  SCCB_Stop();
  return val;
}


u8 SCCB_RD_Byte(void)
{
u8 temp=0,j;    
SCCB_SDA_IN(); 
for(j=8;j>0;j--) 
{      
delay_us(50);
SCCB_SCL=1;
temp=temp<<1;
if(SCCB_READ_SDA)temp++;   
delay_us(50);
SCCB_SCL=0;
}
SCCB_SDA_OUT();   
return temp;



void SCCB_No_Ack(void)
{
delay_us(50);
SCCB_SDA=1;
SCCB_SCL=1;
delay_us(50);
SCCB_SCL=0;
delay_us(50);
SCCB_SDA=0;
delay_us(50);
}


//***********************stm32f10x_it.c
//******************
#include "stm32f10x_it.h"
#include "bsp_ov7725.h"
#include "usart.h"
#include "delay.h"
extern u8 Ov7725_vsync;
void EXTI0_IRQHandler(void)
{
    if ( EXTI_GetITStatus(EXTI_Line0) != RESET ) /如果发送到nvic
    {
        if( Ov7725_vsync == 0 )
        {
FIFO_WE=1;                        //写使能
FIFO_WRST=0;                      //写指针复位
FIFO_WRST=1;     
Ov7725_vsync = 1;  
        }
        else if( Ov7725_vsync == 1 )
        {
            FIFO_WE=0;                          //写禁止
      FIFO_WRST=0;                      //写复位
      FIFO_WRST=1;
            Ov7725_vsync = 2;
        }        
        EXTI_ClearITPendingBit(EXTI_Line0);    //清除标志位      
    }    
}



//********************宏定义
#ifndef __OV7725_H
#define __OV7725_H 
  
#include "stm32f10x.h"
#include "sys.h"

#define FIFO_CS_H     GPIOA->BSRR =GPIO_Pin_3  
#define FIFO_CS_L     GPIOA->BRR  =GPIO_Pin_3  /*??????FIFO????????*/


#define FIFO_WRST          Aout(5)   

#define FIFO_RRST          Aout(2)   

#define FIFO_RCLK_H   GPIOA->BSRR =GPIO_Pin_4  
#define FIFO_RCLK_L   GPIOA->BRR  =GPIO_Pin_4 

#define FIFO_WE            Aout(1)

#define SCCB_SDA_IN()  {GPIOC->CRH&=0XFF0FFFFF;GPIOC->CRH|=0X00800000;}
#define SCCB_SDA_OUT() {GPIOC->CRH&=0XFF0FFFFF;GPIOC->CRH|=0X00300000;}

#define SCCB_SCL     PCout(14) //SCL
#define SCCB_SDA     PCout(13) //SDA  

#define SCCB_READ_SDA     PCin(13)   //????SDA    
#define SCCB_ID   0X42   //OV7670??ID
void Ov7725_GPIO_Config(void);
void VSYNC_Init(void);
void SCCB_Init(void);
u8 SCCB_SUCCESS(void);
u8 SCCB_WR_Reg(u8,u8);
void SCCB_Start(void);
u8 SCCB_WR_Byte(u8);
void SCCB_Stop(void);
u8 SCCB_RD_Reg(u8);
u8 SCCB_RD_Byte(void);
void SCCB_No_Ack(void);


#endif






























友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
13条回答
q1092840790
2019-07-25 12:39
1、OV7670是否带fifo
2、不带fifo的摄像头你抓取IO口占用了大部分资源,你的任何其他操作都会降低的图像的帧数,导致花屏图像错误等
3、波特率太低。。。。传一帧图像你算下要多少时间。。波特率指的是每秒传多少位,这个位指的是二进制形态的,一帧图像很大的
4、不带fifo的情况下,往串口写数据操作是需要的时间的,会导致花屏图像错误等
5、在带fifo的情况下,先保证把图像传到LCD显示出正确图像的前提下,在尝试往串口写数据
6、实现LCD显示成功的前提下,可以把串口写输入的函数替换圈中的那行操作试试

一周热门 更多>