OV7670 摄像头模块与 STONE串口屏的连接

OV7670摄像头模块与STONE串口屏的连接,主要功能

  1. 显示屏实时显示摄像头采集的图像
  2. 点击按钮拍摄图像并保存至TF卡
  3. 切换颜色与灰度
  4. 分辨率可切换 (240*320, 240*240, 160*160, 80*80)
  5. 可切换至图片查看模式
  6. 可浏览上一张图片
  7. 可浏览下一张图片

在开始本项目之前,让我们先看看需要哪些硬件模块。

  1. STONE 7英寸 800*480分辨率串口显示模块
  2. STM32F103ZE开发板
  3. OV7670摄像头模块
  4. 少量相关线缆

STM32F103ZE开发板

ov7670-camera-module-connection-with STONE-display-module

该开发板集成了多项功能

    1. Cortex-M3核心芯片,STM32F103ZET6,
    2. 144针脚
    3. 外部晶体振荡器8M,时钟晶体振荡器32768Hz
    4. 标准20针插座,JTAG接口,用于下载调试程序如Jlink、Ulink和st-link
    5. 标准4针插座, SWD接口,采用2线通信方式进行调试和程序下载
    6. 所有I/O端口均用于插针,便于实验扩展
    7. USB-TTL串口转换电路,实现USB接口的串口通信
    8. 自动下载适配电路,通过串口下载无需频繁切换,一键即可完成下载
    9. MAX232转换电路,适用于外部串行线路
    10. 集成红外接收器,用户可实现远程红外接收功能
    11. DS18B20插座,直接插入芯片实现数字温度测量功能
    12. 带时钟备份电池,保持时钟和重要信息在断电时不丢失
    13. EEPROM芯片24C02,用于存储常用用户信息并采用IIC通信
    14. FLASH芯片W25Q64,8M内存,可存储图片、系统数据及其他信息
    15. SPI模式SD卡座,支持TF卡,PI通信
    16. SDIO模式SD卡座, TF卡,专用SDIO接口,高速稳定。
    17. RF24L01插座用于无线通信测试(至少需要2台设备)
    18. 3路普通按键输入功能,人机交互界面
    19. 1路唤醒按钮,用于从低功耗或待机模式唤醒
    20. 2路用户LED指示灯,显示基本状态和操作指令
    21. 1个USB设备接口,用于调试USB设备功能,如读卡器、USB串口功能
    22. TFT彩色屏幕LCD接口,包括触摸屏接口,可直接插入到支持屏幕中
    23. 摄像头预留接口,支持摄像头模块实现视频展示功能
    24. 1个蜂鸣器
    25. 1个触摸按钮功能
    26. 自恢复保险丝,保护计算机免受损坏
    27. 复位按钮
    28. 电源指示灯
    29. 选择插入引脚
    30. 选择带有VREF参考电压的引脚
    31. CAN、USB开关引脚
    32. 3.3V外部电源供电引脚插入
    33. 5V外部扩展电源供电引脚插入

    但实际上,我们仅使用其摄像头接口和串口,以及TF卡接口

    STONE串口屏

    STONE STVC070WT-01是一款7英寸显示模块,分辨率为800×480。该显示模块可通过STONE官方网站或STONE在线购物平台链接购买。

    STONE stvc070wt-01 的通信模式为 UART-RS232 和 UART-TTL。在本项目中,我使用了 UART-TTL 通信模式。

    显示模块的开发方式较为简单,MCU只需通过UART向STONE 发送指令, 显示模块内容即可实现控制。当用户触摸 STONE 显示屏时,显示模块会通过 UART 将相关指令发送至 MCU,随后 MCU 控制对应设备(如电机旋转、灯光开关等)。

    7 英寸 STONE STVC070WT-01

    制造商提供的材料如下:

    ov7670-camera-module-connection-with STONE-display-module

主包装清单

  1. 传输连接线
  2. USB-TTL适配器板
  3. USB闪存盘(含开发资料)
  4. Micro USB 数据线
  5. USB 传输板
  6. STONE STVC070WT-01 显示模块
  7. 12V 电源适配器

STONE串口屏规格

STVC070WT-01 是一款 TFT 显示屏与触摸控制器。它集成了处理器、控制程序、驱动程序、闪存、RS232/RS485/TTL 接口、触摸屏、电源等组件, 是一款强大的显示系统

操作系统简单,可由任何单片微控制器控制。STVC070WT-01 可实现所有基本功能,如文本显示、图像显示、曲线显示、触摸功能、视频和音频功能等。

  • 内置 Cortex CPU 和驱动程序
  • 可由任何单片微控制器控制
  • 显示图片/文本/曲线
  • 65536 色 TFT 显示屏
  • – 支持触摸操作
  • RS232/ RS485/ TTL UART 接口和 USB 端口
  • 宽电压范围

STVC070WT-01 显示模块控制原理

TFT-LCD 模块通过命令(十六进制)与 MCU 通信,MCU 将根据接收到的命令进行工作。

ov7670-camera-module-connection-with STONE-display-module

完成 STONE串口屏的固件开发需要三个步骤

使用STONE的TFT-LCD模块仅需3个步骤:

  1. 设计一套人机交互界面(UI)。
  2. UART-TTL 直接连接至客户的 MCU。
  3. 编写一个简单程序,通过 MCU 发送命令控制 TFT-LCD 模块。(十六进制代码)。

串口屏的串行命令帧由五个数据块组成,所有数据均以十六进制格式表示。数据传输方式为从MSB到LSB。例如,对于0x1234,首先发送0x12,然后发送0x34。

UI 图片设计计

用户使用 Photoshop 或其他软件设计 UI

ov7670-camera-module-connection-with STONE-display-module

我设计的界面如下:

第一张图片是主屏幕图片,第二张图片是按下按钮时的效果。

使用 TOOL2019 软件生成 LCD 模块配置文件

ov7670-camera-module-connection-with STONE-display-module

点击箭头按钮生成配置文件,然后将配置文件下载到显示模块以显示我们设计的UI界面。生成配置文件,然后将配置文件下载到显示模块以显示我们设计的UI界面。

此部分内容和教程的详细说明在此不再赘述,您可以前往STONE官网下载非常详细的教程。

此外,我们还需要设计一个与按钮按下效果相同的图片。只需将按钮位置的颜色更改为下表所示。

ov7670-camera-module-connection-with STONE-display-module

STM32 MCU与VO7670的接线与焊接MCU与VO7670的接线与焊接

在前面的内容中,我介绍了STONE STVC070WT-01的相关开发操作。在接下来的内容中,我将重点介绍STM32 MCU与VO7670摄像头。在开始之前,让我们先看看项目硬件部分的连接方式。

STONE项目完整接线图

ov7670-camera-module-connection-with STONE-display-module

OV7670 模块 — STM32 开发板:

OV_D0 ~ D7 — — — — — — — — — — – PC0 ~ 7
OV_SCL — — — — — — — — — — — — PD3
OV_SDA — — — — — — — — — — — — PG13
OV_VSYNC — — — — — — — — — — — — PA8
FIFO_RRST — — — — — — — — — — – PG14
FIFO_OE — — — — — — — — — — – PG15
FIFO_WRST — — — — — — — — — — — — PD6
FIFO_WEN — — — — — — — — — — — — PB3
FIFO_RCLK — — — — — — — — — — — — PB4

电源适配器为12V,需为STONE stvc070wt-01显示模块供电,并通过DC-DC降压模块将电压降至5V为MCU模块和OV7670供电。

项目所用配件

主要配件包括:

  1. STM32F103ZE开发板
  2. DC-DC降压模块
  3. UART 切换

由于 STONE STVC070WT-01 的默认通信模式为 UART-TTL,因此无需 RS232 接口进行连接切换,可移除 RS232 接口:

ov7670-camera-module-connection-with STONE-display-module

焊接

通过焊接这些部件,效果如下:

ov7670-camera-module-connection-with STONE-display-module

ov7670-camera-module-connection-with STONE-display-module

当该部分准备就绪后,即可为 MCU 编写程序。

OV7670 摄像头模块 摄像头模块

OV7670 功能块图

OV7670 是一种图像传感器,工作温度为 -30℃-70℃,模拟电压为 2.5-3.0V,光敏阵列为 640×480,功耗为 60mW/15fps。待机功耗小于 20μA。

体积小,工作电压低,具备单个VGA摄像头和图像处理器的所有功能。通过SCCB总线控制,可输入全帧、子采样、窗口等多种分辨率的8位图像数据。该产品的VGA图像最高可达30帧/秒。用户可完全控制图像质量、数据格式和传输方式。所有图像处理功能,包括伽马曲线、白平衡、饱和度、色度等,均可通过SCCB接口进行编程。通过减少或消除固定图案噪声、尾部支持、漂移等光学或电子缺陷,可提升图像质量,获得清晰稳定的彩色图像。漂移等光学或电子缺陷,可提升图像质量,获得清晰稳定的彩色图像。

OV7670是OV(OmniVision)生产的1/6英寸CMOS VGA图像传感器。该传感器

该设备体积小巧,工作电压低,集成了单个VGA摄像头和图像处理器的所有功能。通过SCCB总线控制,可输出全帧、子采样、窗口等多种分辨率的8位图像数据。产品VGA图像最高可达30帧每秒。用户可完全控制图像质量、数据格式及传输。所有图像处理过程,包括伽马曲线、白平衡、亮度、色彩等,均可通过SCCB接口进行编程。OmniVision图像传感器采用独特传感器技术,通过减少或消除固定图案噪声、尾部支持、漂移等光学或电子缺陷,提升图像质量,获得清晰稳定的彩色图像。行编程。OmniVision图像传感器采用独特传感器技术,通过减少或消除固定图案噪声、尾部支持、漂移等光学或电子缺陷,提升图像质量,获得清晰稳定的彩色图像。

OV7670的特点包括:

  1. 高灵敏度,低电压,适用于嵌入式应用
  2. 标准SCCB接口,兼容IIC接口
  3. 支持 VGA、CIF 以及从 CIF 到 40×30 的所有尺寸持 VGA、CIF 以及从 CIF 到 40×30 的所有尺寸
  4. 支持自动曝光控制、自动增益控制、自动白平衡和自动消除光线条纹
  5. 闪光灯支持灯支持
  6. 支持图像缩放

OV7670传感器包含以下功能模块。

  1. 图像阵列

OV7670总像素为656×488,其中640×480为有效像素(即有效像素为30W)。

  1. 视频定时发生器

序列发生器具有以下功能:全序列控制和帧率生成(以7种不同格式输出)、内部信号发生器535及分配、帧率定时、自动曝光控制,以及外部定时输出(VSYNC、HREF/HSYNC 和 PCLK)。制和帧率生成(以7种不同格式输出)、内部信号发生器535及分配、帧率定时、自动曝光控制,以及外部定时输出(VSYNC、HREF/HSYNC 和 PCLK)。

  1. 模拟信号处理

模拟信号处理模块负责所有模拟功能,包括自动增益控制(AGC)和自动白平衡(AWB)。B)。

  1. 模数转换(A/D)

原始信号经过模拟处理模块后,通过G和BR通道进入10位A/D转换器。

A/D转换器以12MHz的采样频率运行,与像素频率完全同步(转换频率与帧率相关)。

A/D 范围乘积与 A/D 范围控制共同设定 A/D 范围和最大值,允许用户根据应用需求调整图像亮度。

接下来,介绍OV7670的图像数据输出格式。首先,简要说明一些定义:7670的图像数据输出格式。首先,简要说明一些定义:

VGA,即分辨率为640×480的输出模式;

QVGA,分辨率为320×240的输出格式,本章所需的格式。

QQVGA,即分辨率为160×120的输出格式;格式;

PCLK,即像素时钟,一个PCLK时钟输出一个像素(或半个像素)。

VSYNC,帧同步信号。HREF/HSYNC,行同步信号。

OV7670的图像数据输出(通过 D[7:0])由 PCLK、VSYNC 和 HREF/HSYNC 控制。

ov7670-camera-module-connection-with STONE-display-module

如下所示。首先,查看行输出的时序,如图所示:

如上图所示,当 HREF 为高电平时输出图像数据,当每个 PCLK

时钟高电平时,输出一个字节的数据。例如,我们使用 VGA 时序,RGB565 格式输出,每 2 字节构成一个像素颜色(高字节在前,低字节在后),因此每行输出总共需要 640*2 个 PCLK 周期,输出 640*2 个字节。

帧时序(VGA 模式) :

ov7670-camera-module-connection-with STONE-display-moduleov7670-camera-module-connection-with STONE-display-module

实际上这是同一引脚的信号,但在不同情况下以不同方式使用,本章中使用 HREF。

由于 OV7670 的像素时钟(PCLK)可达 24MHz,我们使用 STM32F103ZET6 的 IO 端口直接捕获,

这非常困难且占用大量CPU资源

(IO端口可通过降低PCLK输出频率实现捕获,但不推荐)。困难且占用大量CPU资源 (IO端口可通过降低PCLK输出频率实现捕获,但不推荐)。

本项目采用RGB565模式,捕获的图像数据为原始RGB数据,随后通过UART传输至STONE串口屏。

ov7670-camera-module-connection-with STONE-display-module

OV7670摄像头模块驱动程序

u8 OV7670_Init(void)
{
u8 temp;
u16 i=0;
GPIO_InitTypeDef  GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOG, ENABLE);
GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4);
GPIO_InitStructure.GPIO_Pin  = 0xff;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_SetBits(GPIOD,GPIO_Pin_6);
GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOG, &GPIO_InitStructure);
GPIO_SetBits(GPIOG,GPIO_Pin_14|GPIO_Pin_15);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //SWD
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_rgb565) sizeof=""></sizeof(ov7670_init_reg_tbl_rgb565)>
{
SCCB_WR_Reg(ov7670_init_reg_tbl_RGB565[i][0],ov7670_init_reg_tbl_RGB565[i][1]);
delay_ms(2);
}
return 0x00; //ok
}
OV7670_CONFIG ov7670_config;
//ÅäÖÃOV7670µÄÊä³ö
void config_ov7670_OutPut(u16 xsta,u16 ysta,u16 width,u16 height,u8 ouput_mode){
int i=0;
ov7670_config.xsta = xsta;
ov7670_config.ysta = ysta;
ov7670_config.width = width;
ov7670_config.height = height;
ov7670_config.mode = ouput_mode;
if(ouput_mode){ //²ÊÉ«Êä³ö
for(i=0;i<sizeof(ov7670_init_reg_tbl_yuv) sizeof=""></sizeof(ov7670_init_reg_tbl_yuv)>
{
SCCB_WR_Reg(ov7670_init_reg_tbl_YUV[i][0],ov7670_init_reg_tbl_YUV[i][1]);
delay_ms(2);
}
}else{ //ºÚ°×Êä³ö
for(i=0;i<sizeof(ov7670_init_reg_tbl_rgb565) sizeof=""></sizeof(ov7670_init_reg_tbl_rgb565)>
{
SCCB_WR_Reg(ov7670_init_reg_tbl_RGB565[i][0],ov7670_init_reg_tbl_RGB565[i][1]);
delay_ms(2);
}
}
OV7670_Window_Set(176,10,width,height); //ÉèÖô°¿Ú
LCD_Clear(WHITE);
}
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);
SCCB_WR_Reg(0X01,reg01val);
SCCB_WR_Reg(0X02,reg02val);
}
void OV7670_Color_Saturation(u8 sat)
{
u8 reg4f5054val=0X80;
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);
SCCB_WR_Reg(0X50,reg4f5054val);
SCCB_WR_Reg(0X51,0X00);
SCCB_WR_Reg(0X52,reg52val);
SCCB_WR_Reg(0X53,reg53val);
SCCB_WR_Reg(0X54,reg4f5054val);
SCCB_WR_Reg(0X58,0X9E);
}
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);
}
void OV7670_Contrast(u8 contrast)
{
u8 reg56val=0X40;
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);
}
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);
SCCB_WR_Reg(0X68,reg67val);
SCCB_WR_Reg(0X67,reg68val);
}
void OV7670_Window_Set(u16 sx,u16 sy,u16 width,u16 height)
{
u16 endx;
u16 endy;
u8 temp;
endx=(sx+width*2)%784; //   sx:HSTART endx:HSTOP
endy=sy+height*2; //   sy:VSTRT endy:VSTOP
//ÉèÖÃHREF
temp=SCCB_RD_Reg(0X32);
temp&=0XC0;
temp|=((endx&0X07)<<3)|(sx&0X07);
SCCB_WR_Reg(0X032,temp);
SCCB_WR_Reg(0X17,sx>>3);
SCCB_WR_Reg(0X18,endx>>3);
//ÉèÖÃVREF
temp=SCCB_RD_Reg(0X03);
temp&=0XF0;
temp|=((endy&0X03)<<2)|(sy&0X03);
SCCB_WR_Reg(0X03,temp);
SCCB_WR_Reg(0X19,sy>>2);
SCCB_WR_Reg(0X1A,endy>>2);
}

TF卡驱动程序

该项目还需要一张TF卡来存储拍摄的图像。由于TF卡驱动程序过长,这里不再赘述。您可以自行搜索相关代码使用。

STM32F103ZEF103ZE

关于该芯片的网络资料和开发文档非常丰富,这里仅做简要介绍。

ov7670-camera-module-connection-with STONE-display-module

我对该芯片做过详细说明。芯片下载代码使用j-link,如下图所示:

ov7670-camera-module-connection-with STONE-display-module

这是j-link的简易版本,仅支持SWD调试和下载,不支持JTAG。但对于STM32芯片开发,SWD调试已足够。

将代码下载到STM32芯片

确保j-link与STM32F103ZE的连接正确,然后可在KEIL开发环境中识别出芯片:M32F103ZE的连接正确,然后可在KEIL开发环境中识别出芯片:

ov7670-camera-module-connection-with STONE-display-module

点击下载按钮将代码下载到芯片:

ov7670-camera-module-connection-with STONE-display-module

STM32控制代码

STONE串口屏的数据接收每次只能接收255字节,而单个RGB565数据的图像大小为240×320×2=153600字节=153.6KB,因此需要分批传输。示模块的数据接收每次只能接收255字节,而单个RGB565数据的图像大小为240×320×2=153600字节=153.6KB,因此需要分批传输。

此外,由于串行通信速率的限制,图片实时刷新效果不佳。串口波特率配置为921600,这也是STONE串行显示模块的最高通信波特率。

显示屏上的按钮和文本具有对应的地址。在本项目中,显示屏组件的地址如下:。在本项目中,显示屏组件的地址如下:

拍照按钮:0X002A

颜色和灰度按钮:0X002B

更改比例按钮:0X002C

上一张图片按钮:0X002D

下一张图片按钮:0X002E

浏览按钮:0X002F

主功能代码如下:

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"
#include "string.h"
#include "ov7670.h"
#include "tpad.h"
#include "timer.h"
#include "exti.h"
#include "usmart.h"
#include "dma.h"
#include "sdio_sdcard.h"
extern u8 ov_sta;
extern u8 img_dis_cnt;
extern u8 data_ready;
extern u8 USART_RX_END;
u16 user_width=240;
u16 user_heigh=240;
#define PIC_TOTAL     20
u8 sd_select=1;
u16 color_r;
u16 color_g;
u16 color_b;
void UART1_Send_Array(u8 send_array[],u16 num)
{
u16 i=0;
while(i<num)< span=""></num)<>
{
USART_SendData(USART1,send_array[i]);
while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);
i++;
}
}
void ov7670_clock_set(u8 PLL)
{
u8 temp=0;
RCC->CFGR&=0XFFFFFFFC;
RCC->CR&=~0x01000000;
RCC->CFGR&=~(0XF<<18);
PLL-=2;//µÖÏû2¸öµ¥Î»
RCC->CFGR|=PLL<<18;
RCC->CFGR|=1<<16;    //PLLSRC ON
FLASH->ACR|=0x12;
RCC->CR|=0x01000000;   //PLLON
while(!(RCC->CR>>25));
RCC->CFGR|=0x02;
while(temp!=0x02)
{
temp=RCC->CFGR>>2;
temp&=0x03;
}
}
#define SEND_BUF_SIZE   169
#define LCD_X_H         5
#define LCD_X_L         6
#define LCD_Y_H         7
#define LCD_Y_L         8
u8 lcd_send_buf[SEND_BUF_SIZE]={0xa5,0x5a,0xa6,0x85,0x00,0x00,0x00,0x00,0x00};
u8 lcd_send_buf1[512]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
u8 upda_flag=1;
u16 dis_fixel=0;
void camera_refresh()
{
u16 i=0,j=0,k=0;
u8 color;
u8 cnt=9;
u16 user_x_cnt=0,user_x_start=0,lcd_send_times=0;
u16 user_width1=user_width;
u16 user_heigh1=user_heigh;
if(user_width1==240)
{
user_x_cnt=2;
user_x_start=450;
}
else if(user_width1==320)
{
user_x_cnt=3;
user_x_start=410;
}
else if(user_width1==160)
{
user_x_cnt=1;
user_x_start=490;
}
else if(user_width1==80)
{
user_x_cnt=0;
user_x_start=530;
}
if(ov_sta==2)
{
OV7670_RRST=0;
OV7670_RCK_L;
OV7670_RCK_H;
OV7670_RCK_L;
OV7670_RRST=1;
OV7670_RCK_H;
upda_flag=0;
for(i=0;i<user_heigh1;i++)< span=""></user_heigh1;i++)<>
{
k=i+150;
lcd_send_buf[LCD_Y_L] = (u8)(k & 0x00ff);
lcd_send_buf[LCD_Y_H] = (u8)(k >> 8);
cnt=9;
lcd_send_times=0;
for(j=0;j<user_width1*2;j++)></user_width1*2;j++)>
{
OV7670_RCK_L;
color=(u8)GPIOC->IDR&0XFF;
OV7670_RCK_H;
lcd_send_buf[cnt++]=color;
if(cnt > 168)
{
if(lcd_send_times==0)
{
dis_fixel=user_x_start;
lcd_send_buf[LCD_X_H] =(u8)(dis_fixel >> 8);
lcd_send_buf[LCD_X_L] = (u8)(dis_fixel & 0x00ff);
}
else if(lcd_send_times==1)
{
dis_fixel+=80;
lcd_send_buf[LCD_X_H] =(u8)(dis_fixel >> 8);
lcd_send_buf[LCD_X_L] = (u8)(dis_fixel & 0x00ff);
}
else if(lcd_send_times==2)
{
dis_fixel+=80;
lcd_send_buf[LCD_X_H] =(u8)(dis_fixel >> 8);
lcd_send_buf[LCD_X_L] = (u8)(dis_fixel & 0x00ff);
}
else if(lcd_send_times==3)
{
dis_fixel+=80;
lcd_send_buf[LCD_X_H] =(u8)(dis_fixel >> 8);
lcd_send_buf[LCD_X_L] = (u8)(dis_fixel & 0x00ff);
}
if(USART_RX_END==1)
{
EXTI_ClearITPendingBit(EXTI_Line8);
ov_sta=0;
upda_flag=1;
return;
}
else
{
UART1_Send_Array(lcd_send_buf,169);
}
lcd_send_times++;
if(lcd_send_times>user_x_cnt)
lcd_send_times=0;
cnt=9;
}
}
}
EXTI_ClearITPendingBit(EXTI_Line8);
ov_sta=0;
upda_flag=1;
}
}
void clear_display()
{
u16 i=0,j=0,k=0;
u8 cnt=9,lcd_send_times=0;
u8 color;
u16 user_x_cnt=0,user_x_start=0;
u16 user_width1=user_width;
u16 user_heigh1=user_heigh;
if(user_width1==240)
{
user_x_cnt=2;
user_x_start=450;
}
else if(user_width1==320)
{
user_x_cnt=3;
user_x_start=410;
}
else if(user_width1==160)
{
user_x_cnt=1;
user_x_start=490;
}
else if(user_width1==80)
{
user_x_cnt=0;
user_x_start=530;
}
upda_flag=0;
for(i=0;i<user_heigh1;i++)< span=""></user_heigh1;i++)<>
{
k=i+150;
lcd_send_buf[LCD_Y_L] = (u8)(k & 0x00ff);
lcd_send_buf[LCD_Y_H] = (u8)(k >> 8);
cnt=9;
lcd_send_times=0;
for(j=0;j<user_width1*2;j++)></user_width1*2;j++)>
{
OV7670_RCK_L;
color=(u8)GPIOC->IDR&0XFF;
OV7670_RCK_H;
lcd_send_buf[cnt++]=0xff;
if(cnt > 168)
{
if(lcd_send_times==0)
{
dis_fixel=user_x_start;
lcd_send_buf[LCD_X_H] =(u8)(dis_fixel >> 8);
lcd_send_buf[LCD_X_L] = (u8)(dis_fixel & 0x00ff);
}
else if(lcd_send_times==1)
{
dis_fixel+=80;
lcd_send_buf[LCD_X_H] =(u8)(dis_fixel >> 8);
lcd_send_buf[LCD_X_L] = (u8)(dis_fixel & 0x00ff);
}
else if(lcd_send_times==2)
{
dis_fixel+=80;
lcd_send_buf[LCD_X_H] =(u8)(dis_fixel >> 8);
lcd_send_buf[LCD_X_L] = (u8)(dis_fixel & 0x00ff);
}
else if(lcd_send_times==3)
{
dis_fixel+=80;
lcd_send_buf[LCD_X_H] =(u8)(dis_fixel >> 8);
lcd_send_buf[LCD_X_L] = (u8)(dis_fixel & 0x00ff);
}
UART1_Send_Array(lcd_send_buf,169);
lcd_send_times++;
if(lcd_send_times>user_x_cnt)
lcd_send_times=0;
cnt=9;
}
}
}
EXTI_ClearITPendingBit(EXTI_Line8);
ov_sta=0;
upda_flag=1;
}
void user_save_image()
{
u16 i=0,j=0,k=0;
u8 color;
u8 cnt=9,m_cnt=0;
u16 user_x_cnt=0,user_x_start=0,lcd_send_times=0;
u16 user_width1=user_width;
if(user_width1==240)
{
user_x_cnt=2;
user_x_start=450;
}
else
{
return;
}
while(ov_sta!=2);
if(ov_sta==2)
{
OV7670_RRST=0;
OV7670_RCK_L;
OV7670_RCK_H;
OV7670_RCK_L;
OV7670_RRST=1;
OV7670_RCK_H;
upda_flag=0;
for(i=0;i<240;i++)
{
k=i+150;
lcd_send_buf[LCD_Y_L] = (u8)(k & 0x00ff);
lcd_send_buf[LCD_Y_H] = (u8)(k >> 8);
cnt=9;
lcd_send_times=0;
for(j=0;j<240*2;j++)
{
OV7670_RCK_L;
color=(u8)GPIOC->IDR&0XFF;
OV7670_RCK_H;
lcd_send_buf[cnt++]=color;
if(cnt > 168)
{
m_cnt=0;
if(lcd_send_times==0)
{
dis_fixel=user_x_start;
lcd_send_buf[LCD_X_H] =(u8)(dis_fixel >> 8);
lcd_send_buf[LCD_X_L] = (u8)(dis_fixel & 0x00ff);
for(m_cnt=0;m_cnt<169;m_cnt++)
{
lcd_send_buf1[m_cnt]=lcd_send_buf[m_cnt];
}
}
else if(lcd_send_times==1)
{
dis_fixel+=80;
lcd_send_buf[LCD_X_H] =(u8)(dis_fixel >> 8);
lcd_send_buf[LCD_X_L] = (u8)(dis_fixel & 0x00ff);
for(m_cnt=0;m_cnt<169;m_cnt++)
{
lcd_send_buf1[m_cnt+169]=lcd_send_buf[m_cnt];
}
}
else if(lcd_send_times==2)
{
dis_fixel+=80;
lcd_send_buf[LCD_X_H] =(u8)(dis_fixel >> 8);
lcd_send_buf[LCD_X_L] = (u8)(dis_fixel & 0x00ff);
for(m_cnt=0;m_cnt<169;m_cnt++)
{
lcd_send_buf1[m_cnt+169*2]=lcd_send_buf[m_cnt];
}
}
UART1_Send_Array(lcd_send_buf,169);
lcd_send_times++;
if(lcd_send_times>user_x_cnt)
{
SD_WriteDisk(lcd_send_buf1,i+240*sd_select,1);
lcd_send_times=0;
}
cnt=9;
}
}
}
}
EXTI_ClearITPendingBit(EXTI_Line8);
ov_sta=0;
upda_flag=1;
}
void read_image()
{
u8 i=0;
for(i=0;i<240;i++)
{
if(SD_ReadDisk(lcd_send_buf1,i+240*sd_select,1)==0)
{
UART1_Send_Array(lcd_send_buf1,507);
}
}
}
int main(void)
{
u8 pixel_ch_flag=0,user_effect_flag=0;
delay_init();
NVIC_Configuration();
uart_init(921600);
LED_Init();
LCD_Init();
delay_ms(1000);
delay_ms(1000);
while(OV7670_Init())//³õʼ»¯OV7670
{
delay_ms(200);
}
while(SD_Init())
{
delay_ms(500);
LED0=!LED0;
}
if(SD_ReadDisk(lcd_send_buf1,240*(PIC_TOTAL+10),1)==0)
{
sd_select=lcd_send_buf1[0];
if(sd_select>=PIC_TOTAL )
{
lcd_send_buf1[0]=0x00;
SD_WriteDisk(lcd_send_buf1,240*(PIC_TOTAL+10),1);
sd_select=0;
}
}
//show_sdcard_info();
EXTI8_Init();
OV7670_CS=0;
config_ov7670_OutPut(20,60,user_width,user_heigh,0);
while(1)
{
if(USART_RX_END==1)
{
switch(USART_RX_BUF[5])
{
case 0x2c:
clear_display();
pixel_ch_flag+=1;//!pixel_ch_flag;
if(pixel_ch_flag>3)
pixel_ch_flag=0;
if(pixel_ch_flag==1)
{
user_width=160;
user_heigh=160;
}
else if(pixel_ch_flag==2)
{
user_width=80;
user_heigh=80;
}
else if(pixel_ch_flag==3)
{
user_width=320;
user_heigh=240;
}
else
{
user_width=240;
user_heigh=240;
}
config_ov7670_OutPut(20,60,user_width,user_heigh,0);
if(user_effect_flag)
OV7670_Special_Effects(1);
else
OV7670_Special_Effects(0);
break;
case 0x2b:
user_effect_flag=!user_effect_flag;
if(user_effect_flag)
OV7670_Special_Effects(1);
else
OV7670_Special_Effects(0);
break;
case 0x2a:
if(user_width!=240)break;
if(img_dis_cnt==0)
{
img_dis_cnt=1;
}
else
{
if(SD_ReadDisk(lcd_send_buf1,240*(PIC_TOTAL+10),1)==0)
{
if(lcd_send_buf1[0]>=PIC_TOTAL)
{
lcd_send_buf1[0]=PIC_TOTAL;
sd_select=1;
}
else
{
sd_select=lcd_send_buf1[0]+1;
lcd_send_buf1[0]=sd_select;
}
SD_WriteDisk(lcd_send_buf1,240*(PIC_TOTAL+10),1);
user_save_image();
//sd_select=lcd_send_buf1[0];
}
}
break;
case 0x2d:
if(SD_ReadDisk(lcd_send_buf1,240*(PIC_TOTAL+10),1)==0)
{
if(lcd_send_buf1[0]==0)
break;
else
{
sd_select-=1;
if(sd_select==0)sd_select=lcd_send_buf1[0];
}
if(sd_select>lcd_send_buf1[0])
sd_select=1;
}
if(user_width==320)
clear_display();
read_image();
img_dis_cnt=0;
break;
case 0x2e:
if(SD_ReadDisk(lcd_send_buf1,240*(PIC_TOTAL+10),1)==0)
{
if(lcd_send_buf1[0]==0)
break;
if(sd_select>=lcd_send_buf1[0])
{
sd_select=1;
}
else
{
sd_select+=1;
}
}
if(user_width==320)
clear_display();
read_image();
img_dis_cnt=0;
break;
case 0x2f:
img_dis_cnt=0;
break;
default:
break;
}
USART_RX_END=0;
USART_RX_STA=0;
}
else
{
// USART_RX_END=0;
// USART_RX_STA=0;
if(img_dis_cnt==1)
camera_refresh();
}
}
}

}

最后,将代码下载到STM32芯片,然后将完成的电路板连接到显示屏,并确保电源稳定。您可以通过STONE串口屏查看VO7670拍摄的图片。

OV7670摄像头模块与STONE串口屏连接,项目结束。

运行效果

ov7670-camera-module-connection-with STONE-display-module

ov7670-camera-module-connection-with STONE-display-module

滚动至顶部