小弟最近在做小车,需要用摄像头输出黑白的图像,也就是让摄像头输出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
2、不带fifo的摄像头你抓取IO口占用了大部分资源,你的任何其他操作都会降低的图像的帧数,导致花屏图像错误等
3、波特率太低。。。。传一帧图像你算下要多少时间。。波特率指的是每秒传多少位,这个位指的是二进制形态的,一帧图像很大的
4、不带fifo的情况下,往串口写数据操作是需要的时间的,会导致花屏图像错误等
5、在带fifo的情况下,先保证把图像传到LCD显示出正确图像的前提下,在尝试往串口写数据
6、实现LCD显示成功的前提下,可以把串口写输入的函数替换圈中的那行操作试试
一周热门 更多>