• STM32+TFT+OV7670实现图片的显示


    原文:https://blog.csdn.net/qq_45134854/article/details/107833326?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22107833326%22%2C%22source%22%3A%22unlogin%22%7D

    最近在做一个项目,使用OV7670来采集图片将采集好的图片上传到云端,通过手机可以在云端中查看。这两天就先搞了通过TFT显示采集的图片,后面再通过esp8266上传到云端。

    材料的准备
    STM32F103ZET6 ,主控芯片;

    TFT显示屏(某宝上的图片) ;

    OV7670(带FIFO);


    OV7670简介
    (从这里开始就只介绍OV7670了 因为其他两个的资料都差不多)

    OV7670 是 OV( OmniVision)公司生产的一颗 1/6 寸的 CMOS VGA 图像传感器。该传感器体积小、工作电压低,提供单片 VGA 摄像头和影像处理器的所有功能。通过 SCCB 总线控制,可以输出整帧、子采样、取窗口等方式的各种分辨率 8 位影像数据。该产品 VGA 图像最高达到 30 帧/秒。用户可以完全控制图像质量、数据格式和传输方式。所有图像处理功能过程包括伽玛曲线、白平衡、度、色度等都可以通过 SCCB 接口编程。 OmmiVision 图像传感器应用独有的传感器技术,通过减少或消除光学或电子缺陷如固定图案噪声、托尾、浮散等,提高图像质量,得到清晰的稳定的彩色图像。
    OV7670 的特点有:
    (1)高灵敏度、低电压适合嵌入式应用
    (2)标准的 SCCB 接口,兼容 IIC 接口
    (3)支持 RawRGB、RGB(GBR4:2:2,RGB565/RGB555/RGB444),YUV(4:2:2)
    和 YCbCr( 4:2:2)输出格式
    (4)支持 VGA、 CIF,和从 CIF 到 40*30 的各种尺寸输出
    (5)支持自动曝光控制、自动增益控制、自动白平衡、自动消除灯光条纹、
    自动黑电平校准等自动控制功能。同时支持色饱和度、色相、伽马、锐度等设置。
    (6)支持闪光灯
    (7)支持图像缩放
    OV7670 的功能框图图如图所示:

    原理图

    从上图可以看出, PZ-OV7670 摄像头模块自带了有源晶振 Y1,用于产生 12M时钟作为 OV7670 的 XCLK 输入。同时自带了稳压芯片,用于提供 OV7670 稳定的 2.8V 工作电压,并带有一个 FIFO 芯片(AL422B),该 FIFO 芯片的容量是384K 字节,足够存储 2 帧 QVGA 的图像数据。

    管脚功能如图所示:


    OV7670使用方法
    1、存储图像数据。
    OV7670 摄像头模块存储图像数据的过程为:等待 OV7670 同步信号→FIFO 写指针复位→FIFO 写使能→等待第二个 OV7670 同步信号→FIFO 写禁止。通过以上 5 个步骤,我们就完成了 1 帧图像数据的存储。

    2、读取图像数据。
    在存储完一帧图像以后,我们就可以开始读取图像数据了。读取过程为:
    FIFO 读指针复位→给 FIFO 读时钟( FIFO_RCLK)→读取第一个像素高字节→给 FIFO 读时钟→读取第一个像素低字节→给 FIFO 读时钟→读取第二个像素高字节→循环读取剩余像素→结束。

    从上诉可知,摄像头模块数据的读取也是十分简单,比如 QVGA 模式,RGB565 格式,我们总共循环读取 3202402 次,就可以读取 1 帧图像数据,把这些数据写入 TFT 模块,我们就可以看到摄像头捕捉到的画面了。

    与STM32单片机的连接
    //OV7670摄像头模块接线说明:

    //D0-D7:PF0-PF7
    //WEN:PB6
    //RCLK:PB7
    //VSYNC:PA7
    //SDA:PC6
    //SCL:PC4
    //RRST:PC2
    //OE:PC3
    //WRST:PE6
    //GND:GND
    //3.3V:3.3V
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    代码部分
    1、SCCB总线
    1.1 sccb.h

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


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

    //IO操作函数
    #define SCCB_SCL PCout(4)//PBout(12) //SCL
    #define SCCB_SDA PCout(6)//PBout(13) //SDA

    #define SCCB_READ_SDA PCin(6) //输入SDA
    #define SCCB_ID 0X42 //OV7670的ID

    ///
    void SCCB_Init(void);
    void SCCB_Start(void);
    void SCCB_Stop(void);
    void SCCB_No_Ack(void);
    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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    1.2 sccb.c

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


    void SCCB_SDA_OUT(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // 端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    }

    void SCCB_SDA_IN(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // 端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //输入
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    }

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

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // 端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_SetBits(GPIOC,GPIO_Pin_6); // 输出高

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_SetBits(GPIOC,GPIO_Pin_4); // 输出高

    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;
    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)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;
    }


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    2、OV7670驱动程序

    2.1 ov7670.h

    //OV7670摄像头模块接线说明:

    //D0-D7:PF0-PF7
    //WEN:PB6
    //RCLK:PB7
    //VSYNC:PA7
    //SDA:PC6
    //SCL:PC4
    //RRST:PC2
    //OE:PC3
    //WRST:PE6
    //GND:GND
    //3.3V:3.3V
    //自己可以根据自己的需求改脚位

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


    #define OV7670_VSYNC PAin(7) //同步信号检测IO
    #define OV7670_WRST PEout(6) //写指针复位
    #define OV7670_WREN PBout(6) //写入FIFO使能
    #define OV7670_RCK_H GPIO_SetBits(GPIOB,GPIO_Pin_7)//GPIOB->BSRRH=1<<7设置读数据时钟高电平
    #define OV7670_RCK_L GPIO_ResetBits(GPIOB,GPIO_Pin_7)//GPIOB->BSRRL=1<<7// //设置读数据时钟低电平
    #define OV7670_RRST PCout(2) //读指针复位
    #define OV7670_CS PCout(3) //片选信号(OE)

    #define OV7670_DATA GPIOF->IDR&0x00FF //数据输入端口
    /

    u8 OV7670_Init(void);
    void OV7670_Light_Mode(u8 mode);
    void OV7670_Color_Saturation(u8 sat);
    void OV7670_Brightness(u8 bright);
    void OV7670_Contrast(u8 contrast);
    void OV7670_Special_Effects(u8 eft);
    void OV7670_Window_Set(u16 sx,u16 sy,u16 width,u16 height);


    #endif


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    2.2 ov7670cfg.h

    #ifndef _OV7670CFG_H
    #define _OV7670CFG_H
    #include "ov7670.h"


    //初始化寄存器序列及其对应的值
    const u8 ov7670_init_reg_tbl[][2]=
    {
    /*以下为OV7670 QVGA RGB565参数 */
    {0x3a, 0x04},//dummy
    {0x40, 0xd0},//565
    {0x12, 0x14},//QVGA,RGB输出

    //输出窗口设置
    {0x32, 0x80},//HREF control bit[2:0] HREF start 3 LSB bit[5:3] HSTOP HREF end 3LSB
    {0x17, 0x16},//HSTART start high 8-bit MSB
    {0x18, 0x04},//5 HSTOP end high 8-bit
    {0x19, 0x02},
    {0x1a, 0x7b},//0x7a,
    {0x03, 0x06},//0x0a,帧竖直方向控制

    {0x0c, 0x00},
    {0x15, 0x00},//0x00
    {0x3e, 0x00},//10
    {0x70, 0x3a},
    {0x71, 0x35},
    {0x72, 0x11},
    {0x73, 0x00},//

    {0xa2, 0x02},//15
    {0x11, 0x81},//时钟分频设置,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},//全窗口, 位[5:4]: 01 半窗口,10 1/4窗口,11 1/4窗口
    {0x14, 0x28},//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, 0x00},
    {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},//对比度 0x40
    {0x57, 0x40},//0x40, change according to Jim's request
    ///
    //以下部分代码由开源电子网网友:duanzhang512 提出
    //添加此部分代码将可以获得更好的成像效果,但是最下面一行会有蓝色的抖动.
    //如不想要,可以屏蔽此部分代码.然后将:OV7670_Window_Set(12,176,240,320);
    //改为:OV7670_Window_Set(12,174,240,320);,即可去掉最下一行的蓝色抖动
    {0x6a, 0x40},
    {0x01, 0x40},
    {0x02, 0x40},
    {0x13, 0xe7},
    {0x15, 0x00},


    {0x58, 0x9e},

    {0x41, 0x08},
    {0x3f, 0x00},
    {0x75, 0x05},
    {0x76, 0xe1},
    {0x4c, 0x00},
    {0x77, 0x01},
    {0x3d, 0xc2},
    {0x4b, 0x09},
    {0xc9, 0x60},
    {0x41, 0x38},

    {0x34, 0x11},
    {0x3b, 0x02},

    {0xa4, 0x89},
    {0x96, 0x00},
    {0x97, 0x30},
    {0x98, 0x20},
    {0x99, 0x30},
    {0x9a, 0x84},
    {0x9b, 0x29},
    {0x9c, 0x03},
    {0x9d, 0x4c},
    {0x9e, 0x3f},
    {0x78, 0x04},

    {0x79, 0x01},
    {0xc8, 0xf0},
    {0x79, 0x0f},
    {0xc8, 0x00},
    {0x79, 0x10},
    {0xc8, 0x7e},
    {0x79, 0x0a},
    {0xc8, 0x80},
    {0x79, 0x0b},
    {0xc8, 0x01},
    {0x79, 0x0c},
    {0xc8, 0x0f},
    {0x79, 0x0d},
    {0xc8, 0x20},
    {0x79, 0x09},
    {0xc8, 0x80},
    {0x79, 0x02},
    {0xc8, 0xc0},
    {0x79, 0x03},
    {0xc8, 0x40},
    {0x79, 0x05},
    {0xc8, 0x30},
    {0x79, 0x26},
    {0x09, 0x00},
    ///

    };

    #endif


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    2.3 ov7670.c

    #include "sys.h"
    #include "ov7670.h"
    #include "ov7670cfg.h"
    #include "time.h"
    #include "delay.h"
    #include "usart.h"
    #include "sccb.h"
    #include "exti.h"


    //初始化OV7670
    //返回0:成功
    //返回其他值:错误代码
    u8 OV7670_Init(void)
    {
    u8 temp;
    u16 i=0;
    //设置IO
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOF|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOC,ENABLE);

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //上拉模式
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//速度为50M
    GPIO_Init(GPIOA,&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);


    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin=0xff;
    GPIO_Init(GPIOF, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
    GPIO_Init(GPIOE, &GPIO_InitStructure);
    GPIO_SetBits(GPIOE,GPIO_Pin_6);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_SetBits(GPIOC,GPIO_Pin_2|GPIO_Pin_3);

    SCCB_Init(); //初始化SCCB 的IO口
    if(SCCB_WR_Reg(0x12,0x80))return 1; //复位SCCB
    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)/sizeof(ov7670_init_reg_tbl[0]);i++)
    {
    SCCB_WR_Reg(ov7670_init_reg_tbl[i][0],ov7670_init_reg_tbl[i][1]);
    }
    return 0x00; //ok
    }

    //OV7670功能设置
    //白平衡设置
    //0:自动
    //1:太阳sunny
    //2,阴天cloudy
    //3,办公室office
    //4,家里home
    void OV7670_Light_Mode(u8 mode)
    {
    u8 reg13val=0XE7;//默认就是设置为自动白平衡
    u8 reg01val=0;
    u8 reg02val=0;
    switch(mode)
    {
    case 1://sunny
    reg13val=0XE5;
    reg01val=0X5A;
    reg02val=0X5C;
    break;
    case 2://cloudy
    reg13val=0XE5;
    reg01val=0X58;
    reg02val=0X60;
    break;
    case 3://office
    reg13val=0XE5;
    reg01val=0X84;
    reg02val=0X4c;
    break;
    case 4://home
    reg13val=0XE5;
    reg01val=0X96;
    reg02val=0X40;
    break;
    }
    SCCB_WR_Reg(0X13,reg13val);//COM8设置
    SCCB_WR_Reg(0X01,reg01val);//AWB蓝色通道增益
    SCCB_WR_Reg(0X02,reg02val);//AWB红色通道增益
    }
    //色度设置
    //0:-2
    //1:-1
    //2,0
    //3,1
    //4,2
    void OV7670_Color_Saturation(u8 sat)
    {
    u8 reg4f5054val=0X80;//默认就是sat=2,即不调节色度的设置
    u8 reg52val=0X22;
    u8 reg53val=0X5E;
    switch(sat)
    {
    case 0://-2
    reg4f5054val=0X40;
    reg52val=0X11;
    reg53val=0X2F;
    break;
    case 1://-1
    reg4f5054val=0X66;
    reg52val=0X1B;
    reg53val=0X4B;
    break;
    case 3://1
    reg4f5054val=0X99;
    reg52val=0X28;
    reg53val=0X71;
    break;
    case 4://2
    reg4f5054val=0XC0;
    reg52val=0X33;
    reg53val=0X8D;
    break;
    }
    SCCB_WR_Reg(0X4F,reg4f5054val); //色彩矩阵系数1
    SCCB_WR_Reg(0X50,reg4f5054val); //色彩矩阵系数2
    SCCB_WR_Reg(0X51,0X00); //色彩矩阵系数3
    SCCB_WR_Reg(0X52,reg52val); //色彩矩阵系数4
    SCCB_WR_Reg(0X53,reg53val); //色彩矩阵系数5
    SCCB_WR_Reg(0X54,reg4f5054val); //色彩矩阵系数6
    SCCB_WR_Reg(0X58,0X9E); //MTXS
    }
    //亮度设置
    //0:-2
    //1:-1
    //2,0
    //3,1
    //4,2
    void OV7670_Brightness(u8 bright)
    {
    u8 reg55val=0X00;//默认就是bright=2
    switch(bright)
    {
    case 0://-2
    reg55val=0XB0;
    break;
    case 1://-1
    reg55val=0X98;
    break;
    case 3://1
    reg55val=0X18;
    break;
    case 4://2
    reg55val=0X30;
    break;
    }
    SCCB_WR_Reg(0X55,reg55val); //亮度调节
    }
    //对比度设置
    //0:-2
    //1:-1
    //2,0
    //3,1
    //4,2
    void OV7670_Contrast(u8 contrast)
    {
    u8 reg56val=0X40;//默认就是contrast=2
    switch(contrast)
    {
    case 0://-2
    reg56val=0X30;
    break;
    case 1://-1
    reg56val=0X38;
    break;
    case 3://1
    reg56val=0X50;
    break;
    case 4://2
    reg56val=0X60;
    break;
    }
    SCCB_WR_Reg(0X56,reg56val); //对比度调节
    }
    //特效设置
    //0:普通模式
    //1,负片
    //2,黑白
    //3,偏红色
    //4,偏绿色
    //5,偏蓝色
    //6,复古
    void OV7670_Special_Effects(u8 eft)
    {
    u8 reg3aval=0X04;//默认为普通模式
    u8 reg67val=0XC0;
    u8 reg68val=0X80;
    switch(eft)
    {
    case 1://负片
    reg3aval=0X24;
    reg67val=0X80;
    reg68val=0X80;
    break;
    case 2://黑白
    reg3aval=0X14;
    reg67val=0X80;
    reg68val=0X80;
    break;
    case 3://偏红色
    reg3aval=0X14;
    reg67val=0Xc0;
    reg68val=0X80;
    break;
    case 4://偏绿色
    reg3aval=0X14;
    reg67val=0X40;
    reg68val=0X40;
    break;
    case 5://偏蓝色
    reg3aval=0X14;
    reg67val=0X80;
    reg68val=0XC0;
    break;
    case 6://复古
    reg3aval=0X14;
    reg67val=0XA0;
    reg68val=0X40;
    break;
    }
    SCCB_WR_Reg(0X3A,reg3aval);//TSLB设置
    SCCB_WR_Reg(0X68,reg67val);//MANU,手动U值
    SCCB_WR_Reg(0X67,reg68val);//MANV,手动V值
    }
    //设置图像输出窗口
    //对QVGA设置。
    void OV7670_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;
    if(endy>784)endy-=784;
    temp=SCCB_RD_Reg(0X03); //读取Vref之前的值
    temp&=0XF0;
    temp|=((endx&0X03)<<2)|(sx&0X03);
    SCCB_WR_Reg(0X03,temp); //设置Vref的start和end的最低2位
    SCCB_WR_Reg(0X19,sx>>2); //设置Vref的start高8位
    SCCB_WR_Reg(0X1A,endx>>2); //设置Vref的end的高8位

    temp=SCCB_RD_Reg(0X32); //读取Href之前的值
    temp&=0XC0;
    temp|=((endy&0X07)<<3)|(sy&0X07);
    SCCB_WR_Reg(0X17,sy>>3); //设置Href的start高8位
    SCCB_WR_Reg(0X18,endy>>3); //设置Href的end的高8位
    }


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    3、main主函数

    #include "delay.h"
    #include "sys.h"
    #include "lcd.h"
    #include "touch.h"
    #include "gui.h"
    #include "test.h"
    #include "ov7670.h"
    #include "time.h"
    #include "exti.h"
    #include "led.h"
    #include "key.h"
    extern u8 ov_sta; //在exit.c里面定义
    extern u8 ov_frame; //在time.c里面定义

    //更新LCD显示
    void camera_refresh(void)
    {
    u32 j;
    // u16 i;
    u16 color;

    if(ov_sta)//有帧中断更新?
    {

    LCD_direction(1);
    LCD_SetWindows(0,0,320-1,240-1);

    OV7670_RRST=0; //开始复位读指针
    OV7670_RCK_L;
    OV7670_RCK_H;
    OV7670_RCK_L;
    OV7670_RRST=1; //复位读指针结束
    OV7670_RCK_H;
    // for(i=0;i<240;i++) //此种方式可以兼容任何彩屏,但是速度很慢
    // {
    // for(j=0;j<320;j++)
    // {
    // OV7670_RCK_L;
    // color=GPIOF->IDR&0XFF; //读数据
    // OV7670_RCK_H;
    // color<<=8;
    // OV7670_RCK_L;
    // color|=GPIOF->IDR&0XFF; //读数据
    // OV7670_RCK_H;
    // LCD_DrawFRONT_COLOR(i,j,color);
    // }
    // }
    for(j=0;j<76800;j++) //此种方式需清楚TFT内部显示方向控制寄存器值 速度较快
    {
    OV7670_RCK_L;
    color=GPIOF->IDR&0XFF; //读数据
    OV7670_RCK_H;
    color<<=8;
    OV7670_RCK_L;
    color|=GPIOF->IDR&0XFF; //读数据
    OV7670_RCK_H;
    Lcd_WriteData_16Bit(color);
    }
    EXTI_ClearITPendingBit(EXTI_Line7);//清零帧中断标记
    ov_sta=0; //下一次扫描
    ov_frame++;

    }
    }


    int main(void)
    {

    KEY_Init();
    LED_Init();
    SystemInit();//初始化RCC 设置系统主频为72MHZ
    delay_init(72); //延时初始化
    LCD_Init(); //液晶屏初始化
    LCD_Clear(0xffff);
    LCD_Clear(BLUE);
    LCD_ShowString(8,8,16,"1234567",1);

    while(OV7670_Init())//初始化OV7670
    {
    LCD_ShowString(100,20,16,"ERROR",1);
    delay_ms(200);
    LCD_Fill(0,80,239,206,BLACK);
    delay_ms(200);
    }
    LCD_ShowString(200,200,16,"ok",1);
    delay_ms(1500);
    OV7670_Light_Mode(0);
    OV7670_Color_Saturation(2);
    OV7670_Brightness(2);
    OV7670_Contrast(2);
    OV7670_Special_Effects(0);
    LCD_Clear(BLACK);

    EXTI7_Init();
    OV7670_CS=0;
    LCD_Clear(BLACK);

    while(1){

    camera_refresh();//更新显示
    }


    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    最后连接好之后显示的图像
    大概就是下面这样的(屏幕坏的 -_- )

    写得太差了,希望大佬们不要吐槽

    下面是源码下载链接

    百度网盘链接

    提取码:a61c
    ————————————————
    版权声明:本文为CSDN博主「[有红包][QQ红包]恭喜发财」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/qq_45134854/article/details/107833326

  • 相关阅读:
    四组API
    常用的辅助类(必会
    时间戳
    SpringMVC JSON乱码解决
    数据显示到前端
    ubuntu vim字体高亮
    vi编辑文件保存后,提示""vimrc" E212: Can't open file for writing Press ENTER or type command to continu"
    C语言程序设计100例之(25):确定进制
    C语言程序设计100例之(24):数制转换
    C语言程序设计100例之(23):数列求和
  • 原文地址:https://www.cnblogs.com/bruce1992/p/16660044.html
Copyright © 2020-2023  润新知