STM32
直播中

kmno4

12年用户 944经验值
私信 关注
[问答]

STM32F4外设配置速查的方法是什么?

OV2640的是什么?
STM32F4外设配置速查的方法是什么?

回帖(1)

李乔

2021-9-30 16:35:19
OV2640

OV2640是OmniVision公司生产的1/4英寸CMOS UXGA(1632_1232分辨率)图像传感器
特点:



  • 体积小、工作电压低、灵敏度高
  • 具有单片UXGA摄像头和影像处理器的所有功能
  • 通过SCCB总线控制
  • 可输出整帧、子采样、缩放、取窗口等方式各种分辨率的8/10位影像数据
  • 最高帧数15帧/秒(SVGA可达30帧,CIF可达60帧)
  • 用户定义图像质量、数据格式、传输方式等
  • 所有图像处理功能都可以通过SCCB接口(行摄像机控制总线协议,相当于一个简易的I2C协议)编程
  • 兼容I2C接口
  • 支持RawRGB、RGB、GRB422、YUV和YCbCr输出格式
  • 内置DSP,支持UXGA、SXGA、SVGA以及按比例缩小到从SXGA到40*30的任何尺寸,支持图像缩放
  • 支持自动曝光控制、自动增益控制、自动白平衡、自动消除灯光条纹、自动黑电平校准等自动控制功能和色饱和度、色相、伽马、锐度等设置,支持闪光灯
  • 支持图像压缩,可输出JPEG图像数据

SCCB时序

SCCB(Serial Camera Control Bus串行摄像头控制总线)总线是由OV(OmniVision)公司定义和发展的三线式串行总线。现在SCCB总线大多采用两线式接口总线,接口总线包括SIOC串行时钟输入线和SIOD串行双向数据线,分别相当于IIC协议的SCL信号线和SDA信号线。SCCB就是个简化版的IIC,可以直接使用IIC的软件驱动代码改编成SCCB的驱动
基本概念简介

[tr]UXGA1600*1200[/tr]
SXGA1280*1024
XVGA1280*960
WXGA1280*800
XGA1024*768
SVGA800*600
VGA640*480
QQVGA160*120
CIF352*288
PCLK像素时钟:一个PCLK时钟,输出一个(Raw格式)或半个(RGB565格式)像素
VSYNC帧同步信号
HREF/HSYNC行同步信号
ov2640的图像数据输出通过Y[9:0]寄存器输出,这里只使用一**字节(8位)**数据,再PCLK、VSYNC、HREF/HSYNC控制下进行
对于Raw格式数据,                                   1                         ∗                                   t                            p                                  =                         1                         ∗                                   T                                       P                               C                               L                               K                                                 1*t_p=1*T_{PCLK}                  1∗tp=1∗TPCLK
对于YUV/RGB格式数据,                                   1                         ∗                                   t                            p                                  =                         2                         ∗                                   T                                       P                               C                               L                               K                                                 1*t_p=2*T_{PCLK}                  1∗tp=2∗TPCLK
行输出时序

HREF高电平期间的PCLK上升沿进行输出,每个PCLK上升沿从Y[9:0]输出一个**字节(8位)**数据
PCLK最大可达36MHz
例:以UXGA(1600*1200)时序,采用RGB565格式输出,每2字节组成一个像素的颜色,且低字节在前高字节在后。这样每行输出总共有1600*2个PCLK周期输出1600*2个字节
帧输出时序

输出开始时,VSYNC输出                                   4                         ∗                                   t                                       L                               I                               N                               E                                                 4*t_{LINE}                  4∗tLINE有效电平(可自行设置为高/低)脉冲
                                   27193                         ∗                                   t                            p                                       27193*t_p                  27193∗tp后,HREF拉高,开始输出行数据,每行数据输出之间以                              322                      ∗                               t                         p                                  322*t_p               322∗tp为间隔,直到完成所有行输出
最后会有                              57697                      ∗                               t                         p                                  57697*t_p               57697∗tp间隔才能进行下一帧输出
JPEG时序

JPEG输出时,PCLK大大减少,HREF不连续,数据流以0xFF、0xD8开头,以0xFF、0xD9结束,将此间数据保存为.jpg文件即可在电脑打开查看
相关硬件配置

OV2640传感器窗口设置

传感器窗口设置允许用户设置整个传感器区域(1632*1220)的感兴趣部分,即在传感器里面开窗,开窗范围从2*2到1632*1220都可以设置,但要求这个窗口必须大于等于随后设置的图像尺寸
详细内容可查看数据手册
图像尺寸设置

DSP输出到LCD的图像最大尺寸,该尺寸要小于等于传感器窗口设置所设定的窗口尺寸
图像窗口设置

在设置的图像尺寸里面再次设置窗口大小,该窗口必须小于等于前面设置的图像尺寸,该窗口设置后的图像范围将用于输出到外部
图像输出大小设置(缩放设置)

控制最终输出到外部的图像尺寸
该设置仅会对图像进行缩放处理,如果设置的图像输出大小不等于图像窗口设置图像大小,那么图像就会被缩放处理,只有两者大小一样(图像输出大小=图像窗口设置大小)时,输出比例才是1:1
OV2640模块参数



  • 支持RGB565/JPEG数据输出
  • 支持最大UXGA分辨率输出
  • 支持图像任意缩放
  • 自带24M有源晶振、3.3V稳压电路、带滤光片的感光红外镜头
  • 支持手动对焦(旋下盖上螺丝调节镜头即可)

引脚参数:
[tr]脚位名称说明[/tr]
1GND接地
2VCC3.3接3.3V电源
3OV_SCLSCCB时钟线(I)
4OV_VSYNC帧同步信号(O)
5OV_SDASCCB数据线(I/O)
6OV_HREF行同步信号(O)
8OV_RESET复位信号,低电平有效(I)
15OV_PCLK像素时钟(O)
17OV_PWDN掉电模式使能,高电平有效(I)
18NC空脚
7、9、10、11、12、13、14、16OV_D0~D7数据线(O)
OV2640模块使用过程

初始化



  • 初始化IO口
  • 上电、复位
  • 读取传感器ID
  • 执行初始化序列

全部内容由OV2640公司提供源码
MCU读取模块图像数据



  • 等待帧同步(等待VSYNC信号)
  • 等待HRED为高电平
  • 等待第一个PCLK上升沿
  • 读取第一个像素的低字节
  • 等待第二个PCLK上升沿
  • 读取第一个像素的高字节
  • 等待下一个PCLK上升沿
  • 重复4-7步骤直到读完剩余像素
  • 结束读取

DCMI接口

DCMI(Digital Camera Interface)是STM32F4xx自带的数字摄像头接口,属于同步并行接口
特性:



  • 能够接受外部8、10、12、14位并行接口最高54MB/s的高速数据流
  • 支持内嵌码/外部行同步/帧同步
  • 支持连续模式或快照模式
  • 支持裁剪功能
  • 可支持不同数据格式:单色或原始拜尔(Bayer)格式、YCbCr 4:2:2逐行视频、RGB565逐行视频、压缩数据(JPEG)格式
  • 接口通过FIFO和数据格式化器直接与AHB总线相连

该接口包含14条数据线(D13-D0)和1条像素时钟线(PIXCLK),且像素时钟的有效电平可由用户程序决定,能在像素时钟的上升沿或下降沿捕获数据
DCMI接口包含以下信号:
[tr]DCMI接口引脚别名对应OV2640接口引脚[/tr]
数据流输入D[0:13]
数据流输出D[0:7]
水平同步输入HREF/HSYNC行同步行同步信号HREF/HSYNC
垂直同步输入VSYNC帧同步/场同步帧同步信号VSYNC
像素时钟输入PIXCLK像素时钟像素时钟PCLK
时序

数据与PIXCLK同步,并根据像素时钟的极性在像素时钟上升沿/下降沿发生变化
HREF/HSYNC指示行的开始或结束,VSYNC指示帧的开始或结束
DCMI时序与上述OV2640时序基本一致,但DCMI的PIXCLK有效沿可自定义,且HSYNC、VSYNC有效状态对应指示数据在并行接口上无效时,HSYNC/VSYNC引脚上的引脚电平(人话:和OV2640的有效状态相反)
数据存储

DCMI接收到的数据存储在DCMI_DR 32位寄存器内,接入OV2640模块时采用8位数据宽度,所以每4个像素时钟才捕获完32位数据,第一个字节存放在LSB位置,第四个字节存放在MSB位置遵守低字节在前,高字节在后
DCMI支持DMA传输,DCMI可被配置为每在其数据寄存器中收到一个完整的32位数据块时,发送一个DMA请求,由DMA将寄存器内的值搬运到目的地址(如LCD/SRAM)
注意:DCMI的DMA请求映射在DMA2 Channel1 Stream1上;如果使用DCMI->DMA->LCD的传输路径,因为LCD是16位宽(RGB565),但DCMI_DR是32位宽,所以一次DCMI引起的DMA请求将引发往LCD写2次数据
相关设置

DCMI支持连续模式和快照模式,连续模式=录像;快照模式=照相
DCMI支持内嵌码同步和硬件同步,一般采用硬件同步
硬件同步下使用HSYNC和VSYNC两个信号,系统会忽略两个信号有效电平期间接收的所有数据,即硬件同步模式下的HSYNC、VSYNC信号相当于消隐信号
初始化流程



  • 配置相关引脚复用为DCMI
  • 使能DCMI时钟
  • 设置DCMI工作模式和PCLK、HSYNC、VSYNC等参数
  • 设置DMA搬运DCMI数据
  • 使能DCMI传输

实际配置方法与代码

硬件配置

OV2640模块-转接-DCMI接口 对应好即可
软件配置




sccb协议驱动(与I2C协议类似)
sccb.h


#ifndef __SCCB_H
        #define __SCCB_H
        #include "sys.h"
        //IO方向设置
        #define SCCB_SDA_IN() {GPIOD->MODER&=~(3<<(7*2));GPIOD->MODER|=0<<7*2;} //PD7输入
        #define SCCB_SDA_OUT() {GPIOD->MODER&=~(3<<(7*2));GPIOD->MODER|=1<<7*2;} //PD7输出


        //IO操作函数
        #define SCCB_SCL PDout(6) //PD6配置为SCL(仅输出)
        #define SCCB_SDA PDout(7) //SDA输出
        #define SCCB_READ_SDA PDin(7) //SDA输出


        #define SCCB_ID 0X60 //OV2640的ID


        void SCCB_Init(void);//SCCB接口初始化
        void SCCB_Start(void);//起始信号
        void SCCB_Stop(void);//停止信号
        void SCCB_No_Ack(void);//NA信号
        u8 SCCB_WR_Byte(u8 dat);//写数据
        u8 SCCB_RD_Byte(void);//读数据
        u8 SCCB_WR_Reg(u8 reg,u8 data);//写寄存器
        u8 SCCB_RD_Reg(u8 reg);//读寄存器
#endif


sccb.c


#include "sccb.h"
#include "delay.h"


//初始化SCCB接口
void SCCB_Init(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;


        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//使能GPIOD时钟
   
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;//PD6、PD7
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//输出模式
          GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
          GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//100MHz
          GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//内部上拉
    //应用设置
          GPIO_Init(GPIOD,&GPIO_InitStructure);

        GPIO_SetBits(GPIOD,GPIO_Pin_6|GPIO_Pin_7);//初始为高电平
        SCCB_SDA_OUT();
}


//SCCB起始信号
//时钟为高时,数据线下降沿,为SCCB起始信号
//在激活状态下,SDA和SCL均为低电平
void SCCB_Start(void)
{
    SCCB_SDA=1;//数据线高电平          
    SCCB_SCL=1;//时钟线高时数据线下降沿
    delay_us(50);
    SCCB_SDA=0;
    delay_us(50);
    SCCB_SCL=0;//数据线恢复低电平,单操作函数必要          
}


//SCCB停止信号
//时钟为高时,数据线上升沿,为SCCB停止信号
//空闲状况下,SDA,SCL均为高电平
void SCCB_Stop(void)
{
    SCCB_SDA=0;
    delay_us(50);         
    SCCB_SCL=1;//数据线高电平
    delay_us(50);
    SCCB_SDA=1;//时钟线高时数据线上升沿
    delay_us(50);
}


//NA信号
void SCCB_No_Ack(void)
{
        delay_us(50);
        SCCB_SDA=1;//SDA、SCL都为高电平
        SCCB_SCL=1;
        delay_us(50);
        SCCB_SCL=0;
        delay_us(50);
        SCCB_SDA=0;
        delay_us(50);
}


//SCCB写入一个字节
//返回值:0,成功;1,失败
u8 SCCB_WR_Byte(u8 dat)
{
        u8 j,res;         
        for(j=0;j<8;j++)//循环8次发送数据
        {
                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();//设置SDA为输入
        delay_us(50);
        SCCB_SCL=1;//接收第九位,判断是否发送成功
        delay_us(50);
        if(SCCB_READ_SDA)//读取到NA数据
        res=1;//SDA=1发送失败,返回1
        else
        res=0;//SDA=0发送成功,返回0
        SCCB_SCL=0;                 
        SCCB_SDA_OUT();//设置SDA为输出
   
        return res;
}


//SCCB读取一个字节
//SCL上升沿,数据锁存
//返回值:读到的数据
u8 SCCB_RD_Byte(void)
{
        u8 temp=0,j;
        SCCB_SDA_IN();//设置SDA为输入  
        for(j=8;j>0;j--)//循环8次接收数据
        {
                delay_us(50);
                SCCB_SCL=1;
                temp=temp<<1;
                if(SCCB_READ_SDA)
            temp++;   
                delay_us(50);
                SCCB_SCL=0;
        }
        SCCB_SDA_OUT();//设置SDA为输出   
       
    return temp;
}


//写寄存器
//返回值:0,成功;1,失败.
u8 SCCB_WR_Reg(u8 reg,u8 data)
{
        u8 res=0;
        SCCB_Start();//启动SCCB传输
        if(SCCB_WR_Byte(SCCB_ID))
        res=1;//写器件ID          
        delay_us(100);
          if(SCCB_WR_Byte(reg))
        res=1;//写寄存器地址          
        delay_us(100);
          if(SCCB_WR_Byte(data))
       res=1;//写数据         
          SCCB_Stop();
          return
        res;
}


//读寄存器
//返回值:读到的寄存器值
u8 SCCB_RD_Reg(u8 reg)
{
        u8 val=0;
        SCCB_Start();//启动SCCB传输
        SCCB_WR_Byte(SCCB_ID);//写器件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;
}


ov2640驱动
ov2640.h


#ifndef _OV2640_H
#define _OV2640_H
#include "sys.h"
#include "sccb.h"


#define OV2640_PWDN PGout(9) //POWER_DOWN控制信号
#define OV2640_RST PGout(15) //复位控制信号


/*片内信息核对*/
#define OV2640_MID 0X7FA2
#define OV2640_PID 0X2642

//当选择DSP地址(0XFF=0X00)时,OV2640的DSP寄存器地址映射表
#define OV2640_DSP_R_BYPASS     0x05
#define OV2640_DSP_Qs           0x44
#define OV2640_DSP_CTRL         0x50
#define OV2640_DSP_HSIZE1       0x51
#define OV2640_DSP_VSIZE1       0x52
#define OV2640_DSP_XOFFL        0x53
#define OV2640_DSP_YOFFL        0x54
#define OV2640_DSP_VHYX         0x55
#define OV2640_DSP_DPRP         0x56
#define OV2640_DSP_TEST         0x57
#define OV2640_DSP_ZMOW         0x5A
#define OV2640_DSP_ZMOH         0x5B
#define OV2640_DSP_ZMHH         0x5C
#define OV2640_DSP_BPADDR       0x7C
#define OV2640_DSP_BPDATA       0x7D
#define OV2640_DSP_CTRL2        0x86
#define OV2640_DSP_CTRL3        0x87
#define OV2640_DSP_SIZEL        0x8C
#define OV2640_DSP_HSIZE2       0xC0
#define OV2640_DSP_VSIZE2       0xC1
#define OV2640_DSP_CTRL0        0xC2
#define OV2640_DSP_CTRL1        0xC3
#define OV2640_DSP_R_DVP_SP     0xD3
#define OV2640_DSP_IMAGE_MODE   0xDA
#define OV2640_DSP_RESET        0xE0
#define OV2640_DSP_MS_SP        0xF0
#define OV2640_DSP_SS_ID        0x7F
#define OV2640_DSP_SS_CTRL      0xF8
#define OV2640_DSP_MC_BIST      0xF9
#define OV2640_DSP_MC_AL        0xFA
#define OV2640_DSP_MC_AH        0xFB
#define OV2640_DSP_MC_D         0xFC
#define OV2640_DSP_P_STATUS     0xFE
#define OV2640_DSP_RA_DLMT      0xFF


//当选择传感器地址(0XFF=0X01)时,OV2640的DSP寄存器地址映射表
#define OV2640_SENSOR_GAIN       0x00
#define OV2640_SENSOR_COM1       0x03
#define OV2640_SENSOR_REG04      0x04
#define OV2640_SENSOR_REG08      0x08
#define OV2640_SENSOR_COM2       0x09
#define OV2640_SENSOR_PIDH       0x0A
#define OV2640_SENSOR_PIDL       0x0B
#define OV2640_SENSOR_COM3       0x0C
#define OV2640_SENSOR_COM4       0x0D
#define OV2640_SENSOR_AEC        0x10
#define OV2640_SENSOR_CLKRC      0x11
#define OV2640_SENSOR_COM7       0x12
#define OV2640_SENSOR_COM8       0x13
#define OV2640_SENSOR_COM9       0x14
#define OV2640_SENSOR_COM10      0x15
#define OV2640_SENSOR_HREFST     0x17
#define OV2640_SENSOR_HREFEND    0x18
#define OV2640_SENSOR_VSTART     0x19
#define OV2640_SENSOR_VEND       0x1A
#define OV2640_SENSOR_MIDH       0x1C
#define OV2640_SENSOR_MIDL       0x1D
#define OV2640_SENSOR_AEW        0x24
#define OV2640_SENSOR_AEB        0x25
#define OV2640_SENSOR_W          0x26
#define OV2640_SENSOR_REG2A      0x2A
#define OV2640_SENSOR_FRARL      0x2B
#define OV2640_SENSOR_ADDVSL     0x2D
#define OV2640_SENSOR_ADDVHS     0x2E
#define OV2640_SENSOR_YAVG       0x2F
#define OV2640_SENSOR_REG32      0x32
#define OV2640_SENSOR_ARCOM2     0x34
#define OV2640_SENSOR_REG45      0x45
#define OV2640_SENSOR_FLL        0x46
#define OV2640_SENSOR_FLH        0x47
#define OV2640_SENSOR_COM19      0x48
#define OV2640_SENSOR_ZOOMS      0x49
#define OV2640_SENSOR_COM22      0x4B
#define OV2640_SENSOR_COM25      0x4E
#define OV2640_SENSOR_BD50       0x4F
#define OV2640_SENSOR_BD60       0x50
#define OV2640_SENSOR_REG5D      0x5D
#define OV2640_SENSOR_REG5E      0x5E
#define OV2640_SENSOR_REG5F      0x5F
#define OV2640_SENSOR_REG60      0x60
#define OV2640_SENSOR_HISTO_LOW  0x61
#define OV2640_SENSOR_HISTO_HIGH 0x62


/*OV2640初始化函数*/
u8 OV2640_Init(void);
/*OV2640选项调节函数*/
void OV2640_JPEG_Mode(void);
void OV2640_RGB565_Mode(void);
void OV2640_Auto_Exposure(u8 level);
void OV2640_Light_Mode(u8 mode);
void OV2640_Color_Saturation(u8 sat);
void OV2640_Brightness(u8 bright);
void OV2640_Contrast(u8 contrast);
void OV2640_Special_Effects(u8 eft);
void OV2640_Color_Bar(u8 sw);
/*OV2640硬件软件"开窗"函数*/
void OV2640_Window_Set(u16 sx,u16 sy,u16 width,u16 height);
u8 OV2640_OutSize_Set(u16 width,u16 height);
u8 OV2640_ImageWin_Set(u16 offx,u16 offy,u16 width,u16 height);
u8 OV2640_ImageSize_Set(u16 width,u16 height);
#endif


ov2640.c


#include "ov2640.h"
#include "ov2640cfg.h"
#include "timer.h“
#include "sccb.h"
#include "delay.h"
#include "usart.h"


//初始化OV2640
//默认输出1600*1200尺寸的图片
//返回值:0,成功
//    其他,错误代码
u8 OV2640_Init(void)
{
        u16 i=0;
        u16 reg;


    /*设置IO连接OV2640*/
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
        //GPIOG9,15初始化设置
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_15;//PG9,15
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //普通输出模式
        GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//100MHz
        GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//内部上拉
    //应用设置
        GPIO_Init(GPIOG,&GPIO_InitStructure);


        OV2640_PWDN=0;//开始硬复位
        delay_ms(10);
        OV2640_RST=0;//复位OV2640
        delay_ms(10);
        OV2640_RST=1;//结束复位
   
        SCCB_Init();//初始化SCCB 的IO口         
        SCCB_WR_Reg(OV2640_DSP_RA_DLMT,0x01);//操作sensor寄存器
        SCCB_WR_Reg(OV2640_SENSOR_COM7,0x80);//开始软复位
        delay_ms(50);
        reg=SCCB_RD_Reg(OV2640_SENSOR_MIDH);//读取厂家ID 高八位
        reg<<=8;//存入寄存器
        reg|=SCCB_RD_Reg(OV2640_SENSOR_MIDL);//读取厂家ID 低八位 并 存入寄存器
        if(reg!=OV2640_MID)
        {
                printf("MID:%drn",reg);
                return 1;
        }
   
        reg=SCCB_RD_Reg(OV2640_SENSOR_PIDH);//读取厂家ID 高八位
        reg<<=8;
        reg|=SCCB_RD_Reg(OV2640_SENSOR_PIDL);//读取厂家ID 低八位
        if(reg!=OV2640_PID)
        {
                printf("HID:%drn",reg);
                return 2;
        }
   
        /*采用SXGA分辨率(1600*1200)初始化*/  
        for(i=0;i         {
                SCCB_WR_Reg(ov2640_sxga_init_reg_tbl[0],ov2640_sxga_init_reg_tbl[1]);
        }
   
        return 0x00;
}


/*参数选项函数*/
//OV2640切换为JPEG模式
void OV2640_JPEG_Mode(void)
{
        u16 i=0;
        //设置:YUV422格式
        for(i=0;i<(sizeof(ov2640_yuv422_reg_tbl)/2);i++)
        {
                SCCB_WR_Reg(ov2640_yuv422_reg_tbl[0],ov2640_yuv422_reg_tbl[1]);
        }
       
        //设置:输出JPEG数据
        for(i=0;i<(sizeof(ov2640_jpeg_reg_tbl)/2);i++)
        {
                SCCB_WR_Reg(ov2640_jpeg_reg_tbl[0],ov2640_jpeg_reg_tbl[1]);  
        }  
}
//OV2640切换为RGB565模式
void OV2640_RGB565_Mode(void)
{
        u16 i=0;
        //设置:RGB565输出
        for(i=0;i<(sizeof(ov2640_rgb565_reg_tbl)/2);i++)
        {
                SCCB_WR_Reg(ov2640_rgb565_reg_tbl[0],ov2640_rgb565_reg_tbl[1]);
        }
}
//自动曝光设置参数表,支持5个等级
const static u8 OV2640_AUTOEXPOSURE_LEVEL[5][8]=
{
        {
                0xFF,0x01,
                0x24,0x20,
                0x25,0x18,
                0x26,0x60,
        },
        {
                0xFF,0x01,
                0x24,0x34,
                0x25,0x1c,
                0x26,0x00,
        },
        {
                0xFF,0x01,       
                0x24,0x3e,       
                0x25,0x38,
                0x26,0x81,
        },
        {
                0xFF,0x01,
                0x24,0x48,
                0x25,0x40,
                0x26,0x81,
        },
        {
                0xFF,0x01,       
                0x24,0x58,       
                0x25,0x50,       
                0x26,0x92,       
        },
};
//OV2640自动曝光等级设置
//level:0~4
void OV2640_Auto_Exposure(u8 level)
{  
        u8 i;
        u8* p=(u8*)OV2640_AUTOEXPOSURE_LEVEL[level];
        for(i=0;i<4;i++)
        {
                SCCB_WR_Reg(p[i*2],p[i*2+1]);
        }
}
//白平衡设置
//0:自动
//1:太阳sunny
//2,阴天cloudy
//3,办公室office
//4,家里home
void OV2640_Light_Mode(u8 mode)
{
        u8 regccval=0X5E;//Sunny
        u8 regcdval=0X41;
        u8 regceval=0X54;
        switch(mode)
        {
                case 0://auto
                        SCCB_WR_Reg(0XFF,0X00);         
                        SCCB_WR_Reg(0XC7,0X10);//AWB ON
                        return;         
                case 2://cloudy
                        regccval=0X65;
                        regcdval=0X41;
                        regceval=0X4F;
                        break;       
                case 3://office
                        regccval=0X52;
                        regcdval=0X41;
                        regceval=0X66;
                        break;       
                case 4://home
                        regccval=0X42;
                        regcdval=0X3F;
                        regceval=0X71;
                        break;       
        }
        SCCB_WR_Reg(0XFF,0X00);         
        SCCB_WR_Reg(0XC7,0X40);        //AWB OFF
        SCCB_WR_Reg(0XCC,regccval);
        SCCB_WR_Reg(0XCD,regcdval);
        SCCB_WR_Reg(0XCE,regceval);  
}
//色度设置
//0:-2
//1:-1
//2,0
//3,+1
//4,+2
void OV2640_Color_Saturation(u8 sat)
{
        u8 reg7dval=((sat+2)<<4)|0X08;
        SCCB_WR_Reg(0XFF,0X00);               
        SCCB_WR_Reg(0X7C,0X00);               
        SCCB_WR_Reg(0X7D,0X02);                               
        SCCB_WR_Reg(0X7C,0X03);                       
        SCCB_WR_Reg(0X7D,reg7dval);                       
        SCCB_WR_Reg(0X7D,reg7dval);                
}
//亮度设置
//0:(0X00)-2
//1:(0X10)-1
//2,(0X20) 0
//3,(0X30)+1
//4,(0X40)+2
void OV2640_Brightness(u8 bright)
{
  SCCB_WR_Reg(0xff, 0x00);
  SCCB_WR_Reg(0x7c, 0x00);
  SCCB_WR_Reg(0x7d, 0x04);
  SCCB_WR_Reg(0x7c, 0x09);
  SCCB_WR_Reg(0x7d, bright<<4);
  SCCB_WR_Reg(0x7d, 0x00);
}
//对比度设置
//0:-2
//1:-1
//2,0
//3,+1
//4,+2
void OV2640_Contrast(u8 contrast)
{
        u8 reg7d0val=0X20;//默认为普通模式
        u8 reg7d1val=0X20;
          switch(contrast)
        {
                case 0://-2
                        reg7d0val=0X18;                  
                        reg7d1val=0X34;                  
                        break;       
                case 1://-1
                        reg7d0val=0X1C;                  
                        reg7d1val=0X2A;                  
                        break;       
                case 3://1
                        reg7d0val=0X24;                  
                        reg7d1val=0X16;                  
                        break;       
                case 4://2
                        reg7d0val=0X28;                  
                        reg7d1val=0X0C;                  
                        break;       
        }
        SCCB_WR_Reg(0xff,0x00);
        SCCB_WR_Reg(0x7c,0x00);
        SCCB_WR_Reg(0x7d,0x04);
        SCCB_WR_Reg(0x7c,0x07);
        SCCB_WR_Reg(0x7d,0x20);
        SCCB_WR_Reg(0x7d,reg7d0val);
        SCCB_WR_Reg(0x7d,reg7d1val);
        SCCB_WR_Reg(0x7d,0x06);
}
//特效设置
//0:普通模式   
//1,负片
//2,黑白   
//3,偏红色
//4,偏绿色
//5,偏蓝色
//6,复古            
void OV2640_Special_Effects(u8 eft)
{
        u8 reg7d0val=0X00;//默认为普通模式
        u8 reg7d1val=0X80;
        u8 reg7d2val=0X80;
        switch(eft)
        {
                case 1://负片
                        reg7d0val=0X40;
                        break;       
                case 2://黑白
                        reg7d0val=0X18;
                        break;         
                case 3://偏红色
                        reg7d0val=0X18;
                        reg7d1val=0X40;
                        reg7d2val=0XC0;
                        break;       
                case 4://偏绿色
                        reg7d0val=0X18;
                        reg7d1val=0X40;
                        reg7d2val=0X40;
                        break;       
                case 5://偏蓝色
                        reg7d0val=0X18;
                        reg7d1val=0XA0;
                        reg7d2val=0X40;
                        break;       
                case 6://复古
                        reg7d0val=0X18;
                        reg7d1val=0X40;
                        reg7d2val=0XA6;
                        break;         
        }
        SCCB_WR_Reg(0xff,0x00);
        SCCB_WR_Reg(0x7c,0x00);
        SCCB_WR_Reg(0x7d,reg7d0val);
        SCCB_WR_Reg(0x7c,0x05);
        SCCB_WR_Reg(0x7d,reg7d1val);
        SCCB_WR_Reg(0x7d,reg7d2val);
}
//彩条测试
//sw:0,关闭彩条
//   1,开启彩条(注意OV2640的彩条是叠加在图像上面的)
void OV2640_Color_Bar(u8 sw)
{
        u8 reg;
        SCCB_WR_Reg(0XFF,0X01);
        reg=SCCB_RD_Reg(0X12);
        reg&=~(1<<1);
        if(sw)reg|=1<<1;
        SCCB_WR_Reg(0X12,reg);
}


/*硬件软件窗口配置*/


//设置图像输出窗口
//sx,sy,起始地址
//width,height:宽度(对应:horizontal)和高度(对应:vertical)
void OV2640_Window_Set(u16 sx,u16 sy,u16 width,u16 height)
{
        u16 endx;
        u16 endy;
        u8 temp;
        endx=sx+width/2;//V*2
        endy=sy+height/2;
       
        SCCB_WR_Reg(0XFF,0X01);                       
        temp=SCCB_RD_Reg(0X03);//读取Vref之前的值
        temp&=0XF0;
        temp|=((endy&0X03)<<2)|(sy&0X03);
        SCCB_WR_Reg(0X03,temp);//设置Vref的start和end的最低2位
        SCCB_WR_Reg(0X19,sy>>2);//设置Vref的start高8位
        SCCB_WR_Reg(0X1A,endy>>2);//设置Vref的end的高8位
       
        temp=SCCB_RD_Reg(0X32);//读取Href之前的值
        temp&=0XC0;
        temp|=((endx&0X07)<<3)|(sx&0X07);
        SCCB_WR_Reg(0X32,temp);//设置Href的start和end的最低3位
        SCCB_WR_Reg(0X17,sx>>3);//设置Href的start高8位
        SCCB_WR_Reg(0X18,endx>>3);//设置Href的end的高8位
}
//设置图像输出大小
//OV2640输出图像的大小(分辨率),完全由改函数确定
//width,height:宽度(对应:horizontal)和高度(对应:vertical),width和height必须是4的倍数
//返回值:0,设置成功
//    其他,设置失败
u8 OV2640_OutSize_Set(u16 width,u16 height)
{
        u16 outh;
        u16 outw;
        u8 temp;
   
        if(width%4)
        return 1;
        if(height%4)
        return 2;
   
        outw=width/4;
        outh=height/4;
        SCCB_WR_Reg(0XFF,0X00);       
        SCCB_WR_Reg(0XE0,0X04);                       
        SCCB_WR_Reg(0X5A,outw&0XFF);//设置OUTW的低八位
        SCCB_WR_Reg(0X5B,outh&0XFF);//设置OUTH的低八位
   
        temp=(outw>>8)&0X03;
        temp|=(outh>>6)&0X04;
        SCCB_WR_Reg(0X5C,temp);//设置OUTH/OUTW的高位
        SCCB_WR_Reg(0XE0,0X00);
   
        return 0;
}
//设置图像开窗大小
//由:OV2640_ImageSize_Set确定传感器输出分辨率从大小.
//该函数则在这个范围上面进行开窗,用于OV2640_OutSize_Set的输出
//注意:本函数的宽度和高度,必须大于等于OV2640_OutSize_Set函数的宽度和高度
//     OV2640_OutSize_Set设置的宽度和高度,根据本函数设置的宽度和高度,由DSP
//     自动计算缩放比例,输出给外部设备.
//width,height:宽度(对应:horizontal)和高度(对应:vertical),width和height必须是4的倍数
//返回值:0,设置成功
//    其他,设置失败
u8 OV2640_ImageWin_Set(u16 offx,u16 offy,u16 width,u16 height)
{
        u16 hsize;
        u16 vsize;
        u8 temp;
   
        if(width%4)
        return 1;
        if(height%4)
        return 2;
   
        hsize=width/4;
        vsize=height/4;
        SCCB_WR_Reg(0XFF,0X00);       
        SCCB_WR_Reg(0XE0,0X04);                                       
        SCCB_WR_Reg(0X51,hsize&0XFF);//设置H_SIZE的低八位
        SCCB_WR_Reg(0X52,vsize&0XFF);//设置V_SIZE的低八位
        SCCB_WR_Reg(0X53,offx&0XFF);//设置offx的低八位
        SCCB_WR_Reg(0X54,offy&0XFF);//设置offy的低八位
   
        temp=(vsize>>1)&0X80;
        temp|=(offy>>4)&0X70;
        temp|=(hsize>>5)&0X08;
        temp|=(offx>>8)&0X07;
   
        SCCB_WR_Reg(0X55,temp);//设置H_SIZE/V_SIZE/OFFX,OFFY的高位
        SCCB_WR_Reg(0X57,(hsize>>2)&0X80);//设置H_SIZE/V_SIZE/OFFX,OFFY的高位
        SCCB_WR_Reg(0XE0,0X00);       
   
        return 0;
}
//该函数设置图像尺寸大小,也就是所选格式的输出分辨率
//UXGA:1600*1200,SVGA:800*600,CIF:352*288
//width,height:图像宽度和图像高度
//返回值:0,设置成功
//    其他,设置失败
u8 OV2640_ImageSize_Set(u16 width,u16 height)
{
        u8 temp;
   
        SCCB_WR_Reg(0XFF,0X00);                       
        SCCB_WR_Reg(0XE0,0X04);                       
        SCCB_WR_Reg(0XC0,(width)>>3&0XFF);//设置HSIZE的10:3位
        SCCB_WR_Reg(0XC1,(height)>>3&0XFF);//设置VSIZE的10:3位
   
        temp=(width&0X07)<<3;
        temp|=height&0X07;
        temp|=(width>>4)&0X80;
   
        SCCB_WR_Reg(0X8C,temp);       
        SCCB_WR_Reg(0XE0,0X00);
   
        return 0;
}


ov2640cfg.h


//OV2640 SXGA初始化寄存器序列表
//模式选择
//内容过长,略去,详见正点原子教程
1
2
3
dcmi接口配置
dcmi.h


#ifndef _DCMI_H
        #define _DCMI_H
        #include "sys.h"


        void My_DCMI_Init(void);
        void DCMI_DMA_Init(u32 DMA_Memory0BaseAddr,u16 DMA_BufferSize,u32 DMA_MemoryDataSize,u32 DMA_MemoryInc);
        void DCMI_Start(void);
        void DCMI_Stop(void);


        void DCMI_Set_Window(u16 sx,u16 sy,u16 width,u16 height);
        void DCMI_CR_Set(u8 pclk,u8 hsync,u8 vsync);


#endif


dcmi.c


#include "dcmi.h"
#include "lcd.h"
#include "led.h"
#include "ov2640.h”


u8 ov_frame=0;//帧率
extern void jpeg_data_process(void);//JPEG数据处理函数


DCMI_InitTypeDef DCMI_InitStructure;//全局变量注意


//DCMI中断服务函数
void DCMI_IRQHandler(void)
{
        if(DCMI_GetITStatus(DCMI_IT_FRAME)==SET)//捕获到一帧图像
        {
                jpeg_data_process();//jpeg数据处理       
                DCMI_ClearITPendingBit(DCMI_IT_FRAME);//清除帧中断
                LED1=!LED1;//LED指示捕获到图像
                ov_frame++;
                LCD_SetCursor(0,0);//重置LCD
                LCD_WriteRAM_Prepare();//开始写入GRAM
        }
}


//DCMI DMA配置
//DMA_Memory0BaseAddr:存储器地址——将要存储摄像头数据的内存地址(也可以是外设地址)
//DMA_BufferSize:存储器长度——0~65535
//DMA_MemoryDataSize:存储器位宽  
//DMA_MemoryInc:存储器增长方式
void DCMI_DMA_Init(u32 DMA_Memory0BaseAddr,u16 DMA_BufferSize,u32 DMA_MemoryDataSize,u32 DMA_MemoryInc)
{
        DMA_InitTypeDef  DMA_InitStructure;
       
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//使能DMA2时钟
        DMA_DeInit(DMA2_Stream1);//清空流
        while (DMA_GetCmdStatus(DMA2_Stream1)!=DISABLE);//等待DMA2Stream1可配置
       
          /*配置DMA2 Stream1 Channel1*/
          DMA_InitStructure.DMA_Channel=DMA_Channel_1;//DMA2Stream1Channel1
          DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)&DCMI->DR;//外设地址:DCMI->DR
          DMA_InitStructure.DMA_Memory0BaseAddr=DMA_Memory0BaseAddr;//DMA存储器0地址
          DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralToMemory;//外设到存储器模式
   
          DMA_InitStructure.DMA_BufferSize=DMA_BufferSize;//数据传输量
          DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设非增量模式
          DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc;//存储器增量模式
          DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Word;//外设数据长度:32位
          DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize;//存储器数据长度
   
          DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;//使用循环模式
          DMA_InitStructure.DMA_Priority=DMA_Priority_High;//高优先级
   
          DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Enable;//使能FIFO        
          DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_Full;//使用全FIFO
         
    DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;//外设突发单次传输
          DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;//存储器突发单次传输
    //应用设置
          DMA_Init(DMA2_Stream1,&DMA_InitStructure);
}


//DCMI初始化
void My_DCMI_Init(void)
{
          GPIO_InitTypeDef  GPIO_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;


    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|
                           RCC_AHB1Periph_GPIOB|
                                  RCC_AHB1Periph_GPIOC|
                           RCC_AHB1Periph_GPIOE,ENABLE);//使能GPIOA B C E时钟
        RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI,ENABLE);//使能DCMI时钟
         
    /*PA4、PA6、PB6、PB7、PC6、PC7、PC8、PC9、PC11、PE5、PE6设置为复用输出*/
          GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用功能
          GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
          GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//100MHz
          GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//内部上拉
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_6;//PA4、6复用输出
    //应用设置
          GPIO_Init(GPIOA, &GPIO_InitStructure);
          GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7|GPIO_Pin_6;//PB6、7复用输出
    //应用设置
          GPIO_Init(GPIOB, &GPIO_InitStructure);
          GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_11;//PC6、7、8、9、11 复用输出
    //应用设置
          GPIO_Init(GPIOC, &GPIO_InitStructure);
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;//PE5、6复用输出
    //应用设置
          GPIO_Init(GPIOE, &GPIO_InitStructure);


        GPIO_PinAFConfig(GPIOA,GPIO_PinSource4,GPIO_AF_DCMI);//PA4,AF13  DCMI_HSYNC
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_DCMI);//PA6,AF13  DCMI_PCLK  
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_DCMI);//PB7,AF13  DCMI_VSYNC
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_DCMI);//PC6,AF13  DCMI_D0  
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_DCMI);//PC7,AF13  DCMI_D1
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource8,GPIO_AF_DCMI);//PC8,AF13  DCMI_D2
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource9,GPIO_AF_DCMI);//PC9,AF13  DCMI_D3
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_DCMI);//PC11,AF13 DCMI_D4
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_DCMI);//PB6,AF13  DCMI_D5
        GPIO_PinAFConfig(GPIOE,GPIO_PinSource5,GPIO_AF_DCMI);//PE5,AF13  DCMI_D6
        GPIO_PinAFConfig(GPIOE,GPIO_PinSource6,GPIO_AF_DCMI);//PE6,AF13  DCMI_D7
       
        DCMI_DeInit();//清除原来的设置
   
          DCMI_InitStructure.DCMI_CaptureMode=DCMI_CaptureMode_Continuous;//连续模式
        DCMI_InitStructure.DCMI_CaptureRate=DCMI_CaptureRate_All_Frame;//全帧捕获
        DCMI_InitStructure.DCMI_ExtendedDataMode= DCMI_ExtendedDataMode_8b;//8位数据格式  
        DCMI_InitStructure.DCMI_HSPolarity= DCMI_HSPolarity_Low;//HSYNC低电平有效
    DCMI_InitStructure.DCMI_VSPolarity=DCMI_VSPolarity_Low;//VSYNC低电平有效
        DCMI_InitStructure.DCMI_PCKPolarity= DCMI_PCKPolarity_Rising;//PCLK上升沿有效
        DCMI_InitStructure.DCMI_SynchroMode= DCMI_SynchroMode_Hardware;//硬件同步HSYNC,VSYNC
    //应用设置
        DCMI_Init(&DCMI_InitStructure);


        DCMI_ITConfig(DCMI_IT_FRAME,ENABLE);//使能帧中断
       
        DCMI_Cmd(ENABLE);//使能DCMI
        //此时不能捕获,还要启动传输
    NVIC_InitStructure.NVIC_IRQChannel=DCMI_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级0
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//子优先级0
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//IRQ通道使能
    //应用设置
        NVIC_Init(&NVIC_InitStructure);
}


//DCMI,启动传输
void DCMI_Start(void)
{  
        LCD_SetCursor(0,0);//重置LCD
        LCD_WriteRAM_Prepare();//开始写入GRAM
        DMA_Cmd(DMA2_Stream1, ENABLE);//开启DMA2Stream1
        DCMI_CaptureCmd(ENABLE);//使能DCMI捕获
}
//DCMI,关闭传输
void DCMI_Stop(void)
{
          DCMI_CaptureCmd(DISABLE);//关闭DCMI捕获       
        while(DCMI->CR&0X01);//等待传输结束
        DMA_Cmd(DMA2_Stream1,DISABLE);//关闭DMA2Stream1
}


main()配置
main.c


#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "usmart.h"  
#include "usart2.h"  
#include "timer.h"
#include "ov2640.h"
#include "dcmi.h"


u8 ov2640_mode=0;//工作模式:0,RGB565模式;1,JPEG模式


#define jpeg_buf_size 31*1024//定义JPEG数据缓存jpeg_buf的大小(*4字节)
__align(4) u32 jpeg_buf[jpeg_buf_size];//JPEG数据缓存buf
volatile u32 jpeg_data_len=0;//buf中的JPEG有效数据长度
volatile u8 jpeg_data_ok=0;//JPEG数据采集完成标志
                                                   //0,数据没有采集完;
                                                   //1,数据采集完了,但是还没处理;
                                                   //2,数据已经处理完成了,可以开始下一帧接收
//JPEG尺寸支持列表
const u16 jpeg_img_size_tbl[][2]=
{
        176,144,        //QCIF
        160,120,        //QQVGA
        352,288,        //CIF
        320,240,        //QVGA
        640,480,        //VGA
        800,600,        //SVGA
        1024,768,        //XGA
        1280,1024,        //SXGA
        1600,1200,        //UXGA
};
const u8*EFFECTS_TBL[7]={"Normal","Negative","B&W","Redish","Greenish","Bluish","Antique"};//7种特效
const u8*JPEG_SIZE_TBL[9]={"QCIF","QQVGA","CIF","QVGA","VGA","SVGA","XGA","SXGA","UXGA"};//JPEG 9种尺寸


//处理JPEG数据
//当采集完一帧JPEG数据后,调用此函数,切换JPEG BUF.开始下一帧采集.
void jpeg_data_process(void)
{
        if(ov2640_mode)//只有在JPEG格式下,才需要做处理
        {
                if(jpeg_data_ok==0)//如果还未采集完数据
                {       
                        DMA_Cmd(DMA2_Stream1, DISABLE);//停止当前传输
                        while(DMA_GetCmdStatus(DMA2_Stream1)!=DISABLE);//等待DMA2_Stream1可配置  
                        jpeg_data_len=jpeg_buf_size-DMA_GetCurrDataCounter(DMA2_Stream1);//得到此次数据传输的长度
                        jpeg_data_ok=1;//标记JPEG数据采集完成,等待其他函数处理
                }
        
                if(jpeg_data_ok==2)//如果jpeg数据已经被处理了
                {
                        DMA2_Stream1->NDTR=jpeg_buf_size;       
                        DMA_SetCurrDataCounter(DMA2_Stream1,jpeg_buf_size);//传输长度为jpeg_buf_size*4字节
                        DMA_Cmd(DMA2_Stream1,ENABLE);//重新传输
                        jpeg_data_ok=0;//标记数据未采集
                }
        }
}


//JPEG测试
//JPEG数据,通过串口1发送给电脑.
void jpeg_test(void)
{
        u32 i;
        u8* p;
        u8 key;
        u8 effect=0,saturation=2,contrast=2;
        u8 size=3;//默认QVGA 320*240尺寸
        u8 msgbuf[15];//消息缓存区
        LCD_Clear(WHITE);
        POINT_COLOR=RED;
        LCD_ShowString(30,70,200,16,16,"OV2640 JPEG Mode");
        LCD_ShowString(30,100,200,16,16,"KEY0:Contrast");//对比度
        //LCD_ShowString(30,120,200,16,16,"KEY1:Saturation");//色彩饱和度
        //LCD_ShowString(30,140,200,16,16,"KEY2:Effects");//特效
        LCD_ShowString(30,160,200,16,16,"KEY_UP:Size");//分辨率设置
        sprintf((char*)msgbuf,"JPEG Size:%s",JPEG_SIZE_TBL[size]);
        LCD_ShowString(30,180,200,16,16,msgbuf);//显示当前JPEG分辨率
       
        OV2640_JPEG_Mode();//JPEG模式
        My_DCMI_Init();//初始化DCMI
        DCMI_DMA_Init((u32)&jpeg_buf,jpeg_buf_size,DMA_MemoryDataSize_Word,DMA_MemoryInc_Enable);//初始化DMA
        OV2640_OutSize_Set(jpeg_img_size_tbl[size][0],jpeg_img_size_tbl[size][1]);//设置输出尺寸
        DCMI_Start();//启动传输
       
    while(1)
        {
                if(jpeg_data_ok==1)//若已经采集完一帧图像
                {  
                        p=(u8*)jpeg_buf;
                        LCD_ShowString(30,210,210,16,16,"Sending JPEG data...");//提示正在传输数据
                        for(i=0;i                         {
                                while((USART1->SR&0X40)==RESET);//循环发送直到发送完毕                 
                                USART1->DR=p;
                                key=KEY_Scan(0);
                                if(key)
                    break;//若按键按下则需要处理,跳至下部分
                        }
                        if(key)//有按键按下,需要处理
                        {  
                                LCD_ShowString(30,210,210,16,16,"Quit Sending data");//提示退出数据传输
               
                                switch(key)
                                {                                    
                                        case KEY0_PRES://对比度设置
                                                contrast++;
                                                if(contrast>4)contrast=0;
                                                OV2640_Contrast(contrast);
                                                sprintf((char*)msgbuf,"Contrast:%d",(signed char)contrast-2);
                                                break;
                                        case KEY1_PRES://饱和度Saturation
                                                //saturation++;
                                                //if(saturation>4)saturation=0;
                                                //OV2640_Color_Saturation(saturation);
                                                //sprintf((char*)msgbuf,"Saturation:%d",(signed char)saturation-2);
                                                break;
                                        case KEY2_PRES://特效设置                                 
                                                //effect++;
                                                //if(effect>6)effect=0;
                                                //OV2640_Special_Effects(effect);//设置特效
                                                //sprintf((char*)msgbuf,"%s",EFFECTS_TBL[effect]);
                                                break;
                                        case WKUP_PRES://JPEG输出尺寸设置   
                                                size++;  
                                                if(size>8)size=0;   
                                                OV2640_OutSize_Set(jpeg_img_size_tbl[size][0],jpeg_img_size_tbl[size][1]);//设置输出尺寸  
                                                sprintf((char*)msgbuf,"JPEG Size:%s",JPEG_SIZE_TBL[size]);
                                                break;
                                }
               
                                LCD_Fill(30,180,239,190+16,WHITE);
                                LCD_ShowString(30,180,210,16,16,msgbuf);//显示提示内容
                                delay_ms(800);                                   
                        }
            else
                LCD_ShowString(30,210,210,16,16,"Send data complete!!");//提示传输结束设置
                        jpeg_data_ok=2;        //标记jpeg数据处理完毕,可以让DMA采集下一帧
                }               
        }   
}


//RGB565测试
//RGB数据直接显示在LCD上面
void rgb565_test(void)
{
        u8 key;
        u8 effect=0,saturation=2,contrast=2;
        u8 scale=1;//默认是全尺寸缩放
        u8 msgbuf[15];//消息缓存区
   
        LCD_Clear(WHITE);
    POINT_COLOR=RED;
        LCD_ShowString(30,70,200,16,16,"OV2640 RGB565 Mode");
        LCD_ShowString(30,100,200,16,16,"KEY0:Contrast");//对比度
        //LCD_ShowString(30,130,200,16,16,"KEY1:Saturation");//色彩饱和度
        //LCD_ShowString(30,150,200,16,16,"KEY2:Effects");//特效
        LCD_ShowString(30,170,200,16,16,"KEY_UP:FullSize/Scale");//1:1尺寸(显示真实尺寸)/全尺寸缩放
       
        OV2640_RGB565_Mode();//RGB565模式
        My_DCMI_Init();//DCMI配置
        DCMI_DMA_Init((u32)&LCD->LCD_RAM,1,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Disable);//DCMI DMA配置  
        OV2640_OutSize_Set(lcddev.width,lcddev.height);
        DCMI_Start();//启动传输
        while(1)
        {
                key=KEY_Scan(0);
                if(key)
                {
                        DCMI_Stop();//停止显示
                        switch(key)
                        {                                    
                                case KEY0_PRES://对比度设置
                                        contrast++;
                                        if(contrast>4)contrast=0;
                                        OV2640_Contrast(contrast);
                                        sprintf((char*)msgbuf,"Contrast:%d",(signed char)contrast-2);
                                        break;
                                case KEY1_PRES:        //饱和度Saturation
                                        //saturation++;
                                        //if(saturation>4)saturation=0;
                                        //OV2640_Color_Saturation(saturation);
                                        //sprintf((char*)msgbuf,"Saturation:%d",(signed char)saturation-2);
                                        break;
                                case KEY2_PRES://特效设置                                 
                                        //effect++;
                                        //if(effect>6)effect=0;
                                        //OV2640_Special_Effects(effect);//设置特效
                                        //sprintf((char*)msgbuf,"%s",EFFECTS_TBL[effect]);
                                        break;
                                case WKUP_PRES://1:1尺寸(显示真实尺寸)/缩放            
                                        scale=!scale;  
                                       
                    if(scale==0)
                                        {
                                                OV2640_ImageWin_Set((1600-lcddev.width)/2,(1200-lcddev.height)/2,lcddev.width,lcddev.height);//1:1真实尺寸
                                                OV2640_OutSize_Set(lcddev.width,lcddev.height);
                                                sprintf((char*)msgbuf,"Full Size 1:1");
                                        }
                    else
                                        {
                                                OV2640_ImageWin_Set(0,0,1600,1200);                                //全尺寸缩放
                                                OV2640_OutSize_Set(lcddev.width,lcddev.height);
                                                sprintf((char*)msgbuf,"Scale");
                                        }
                                        break;
                        }
                        LCD_ShowString(30,50,210,16,16,msgbuf);//显示提示内容
                        delay_ms(800);
                        DCMI_Start();//重新开始传输
                }
                delay_ms(10);               
        }   
}


int main(void)
{
        u8 key;
        u8 t;
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
        delay_init(168);//初始化延时函数
        uart_init(115200);//初始化串口波特率为115200
        usart2_init(42,115200);//初始化串口2波特率为115200
        LED_Init();//初始化LED
        LCD_Init();//LCD初始化  
        KEY_Init();//按键初始化
        TIM3_Int_Init(10000-1,8400-1);//10Khz计数,1秒钟中断一次
       
        usmart_dev.init(84);//初始化USMART
        POINT_COLOR=RED;//设置字体为红色


        while(OV2640_Init())//初始化OV2640
        {
                LCD_ShowString(30,130,240,16,16,"OV2640 ERR");
                delay_ms(200);
            LCD_Fill(30,130,239,170,WHITE);
                delay_ms(200);
        }
        LCD_ShowString(30,130,200,16,16,"OV2640 OK");
   
        while(1)
        {       
                key=KEY_Scan(0);
                if(key==KEY0_PRES)//RGB565模式
                {
                        ov2640_mode=0;   
                        break;
                }
        else if(key==WKUP_PRES)//JPEG模式
                {
                        ov2640_mode=1;
                        break;
                }
        
                t++;                                                                           
                if(t==100)
            LCD_ShowString(30,150,230,16,16,"KEY0:RGB565  KEY_UP:JPEG");//闪烁显示提示信息
                if(t==200)
                {       
                        LCD_Fill(30,150,230,150+16,WHITE);
                        t=0;
                }
                delay_ms(5);
        }
        if(ov2640_mode)
        jpeg_test();
        else
        rgb565_test();
}
举报

更多回帖

×
20
完善资料,
赚取积分