OV7670 摄像头模块连接 STONE 显示模组

本文将介绍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-显示模块

该开发板具有多项集成功能

  1. Cortex-m3核心芯片,STM32F103ZET6,
  2. 144P针
  3. 外接晶振8M,时钟晶振32768Hz
  4. 标准20P插座,JTAG接口,用于下载Jlink、Ulink、st-link等调试程序
  5. 标准4P插针,SWD接口,使用2线通讯调试下载程序
  6. 所有 I/O 端口均用于插入针头,方便实验扩展
  7. USB-TTL串口转换电路,实现USB接口的串口通讯
  8. 自动下载适配器电路,使用串口下载无需频繁切换,一键下载
  9. MAX232转换电路,适合外接串口线
  10. 集成红外接收器,用户远程红外接收功能
  11. DS18B20插座,直接插入芯片实现数字测温功能
  12. 带时钟备用电池,保持时钟和重要信息不掉电
  13. EEPROM芯片24c02存储常用用户信息,使用IIC进行通信
  14. FLASH芯片W25Q64,8,XNUMXM内存,可存储图片、系统数据等信息
  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彩屏液晶接口,包括触摸屏接口,可直接插入配套屏幕
  23. 摄像头预留接口,支持摄像头模组实现视频演示功能
  24. 1号蜂鸣器
  25. 1个触摸按键功能
  26. 自恢复保险丝,保护计算机免受损坏
  27. 复位按钮
  28. 电源指示灯
  29. 选择插入引脚
  30. 选择具有 VREF 参考电压的引脚
  31. CAN、USB开关针
  32. 3.3v外置电源插针
  33. 5V外扩电源引脚插入

但实际上我们只用了他的相机接口和串口,还有TF卡接口

STONE TFT-LCD显示模块

STONE STVC070WT-01是一款7英寸显示模组,分辨率为800*480。 这个显示模块可以从 STONE的官网或来自 STONE的网购平台链接。
的通讯方式 STONE stvc070wt-01是uart-rs232和uart-ttl。在这个项目中,我使用了uart-TTL通信方式。
显示模块开发方式简单,MCU只需通过UART发送指令到 STONE,显示模块的内容,控制就ok了,用户触摸的时候原理一样 STONE 显示屏、显示模块及相关指令通过UART发送给MCU,然后MCU控制相应的设备(如电机转动、灯开关等)。

7英寸 STONE STVC070WT-01

厂家提供的材料如下:

ov7670-camera-module-connection-with STONE-显示模块

主要装箱单

  1. 传输连接和连接
  2. USB-TTL转接板
  3. U盘(含开发资料)
  4. 微型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-显示模块

完成固件开发需要三个步骤 STONE 显示模块

运用 STONE的TFT-LCD模组只需要3个步骤:

  1. 设计一组人机画面(UI)。
  2. UART-TTL 直接连接到客户的 MCU。
  3. 编写一个简单的程序,由单片机通过命令控制TFT-LCD模块。 (十六进制代码)。

TFT LCD 模块的串行命令帧由五个数据块组成,全部以十六进制格式表示。 数据传输到 MSB 的方式。例如,对于 0x1234,先发送 0x12,然后发送 0x34。

UI图片设计

用户使用 Photoshop 或其他软件设计 UI
我设计的界面如下:

ov7670-camera-module-connection-with STONE-显示模块

第一张是主屏画面,第二张是按键按下时的效果。

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

ov7670-camera-module-connection-with STONE-显示模块

点击箭头按钮生成配置文件,然后将配置文件下载到显示模块,即可显示我们设计的UI界面。
这部分内容和教程我就不赘述了,大家可以去 STONE 网站下载非常详细的教程。
此外,我们还需要设计一个与按钮按下时的效果一模一样的图片。 我们只需要将按钮位置的颜色更改为下表。

ov7670-camera-module-connection-with STONE-显示模块

STM32 MCU和VO7670接线和焊接

在之前的内容中,我介绍了相关的开发操作 STONE STVC070WT-01。 在接下来的内容中,我将重点介绍STM32 MCU和VO7670摄像头。 在我们这样做之前,让我们看一下项目的硬件部分是如何连接的。

一个完整的接线图 STONE 项目

ov7670-camera-module-connection-with STONE-显示模块

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降压至7670伏为MCU模块和OV5供电。

项目中使用的配件

主要配件有:

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

由于默认的通信模式 STONE STVC070WT-01为uart-TTL,我们不需要RS232接口进行切换连接,去掉RS232接口:

ov7670-camera-module-connection-with STONE-显示模块

焊接

通过将这些部件焊接在一起,效果如下:

ov7670-camera-module-connection-with STONE-显示模块

ov7670-camera-module-connection-with STONE-显示模块

当这部分准备好后,您就可以为 MCU 编写程序了。

OV7670 摄像头模组

OV7670功能框图

OV7670是一种图像传感器,工作温度-30℃-70℃,模拟电压2.5-3.0v,感光阵列640*480,功耗60mW/15fps。休眠时小于20uA .
体积小,工作电压低,提供单个 VGA 摄像头和图像处理器的所有功能。 通过SCCB总线控制,可以输入各种分辨率8位图像数据的整帧、子采样、窗口等多种方式。 该产品的VGA图像最高可达每秒30帧。 用户可以完全控制图像质量、数据格式和传输。 所有图像处理功能,包括伽马曲线、白平衡、饱和度、色度等,都可以通过 SCCB 接口进行编程。 通过减少或消除固定图案噪声、尾托、浮动等光学或电子缺陷,提高图像质量,获得清晰稳定的彩色图像。
OV7670 是 OV(OmniVision)生产的 1/6 英寸 CMOS VGA 图像传感器。
该器件体积小,工作电压低,提供单个VGA摄像头和图像处理器的所有功能。 通过SCCB总线控制,可以输出整帧、子采样、窗口等各种分辨率的8位图像数据。 该产品的 VGA 图像最高可达每秒 30 帧。 用户可以完全控制图像质量、数据格式和传输。 包括伽马曲线、白平衡、度数、颜色等在内的所有图像处理过程都可以通过 SCCB 接口进行编程。OmniVision 图像传感器采用独特的传感器技术,通过减少或消除固定图案噪声等光学或电子缺陷来提高图像质量、尾托、浮动等,获得清晰稳定的彩色图像。
OV7670 的特点包括:

  1.  适用于嵌入式应用的高灵敏度、低电压
  2. 标准SCCB接口,兼容IIC接口
  3. 支持 RawRGB、RGB(gbr4:2:2、RGB565/RGB555/RGB444)、YUV(4:2:2) 和 YCbCr
  4. 支持 VGA、CIF 以及从 CIF 到 40*30 的所有尺寸
  5. 支持自动曝光控制、自动增益控制、自动白平衡和自动消除光纹
  6. 自动黑电平校准和其他自动控制功能。 同时支持色彩饱和度、色调、伽玛、锐度等设置。
  7. 支持Flash
  8. 支持图像缩放

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

1. 图像阵列

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

2. 视频定时发生器

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

3.模拟信号处理

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

4、A/D转换(A/D)

原始信号经过模拟处理器模块后,通过G、BR通道进入A 10位A/D转换器。
A/D转换器以12M的A频率工作,与像素频率完全同步(转换频率与帧率有关)。
A/D 范围产品和 A/D 范围控制共同设置 A/D 范围和最大值,允许用户根据应用调整图像的亮度。
接下来介绍一下OV7670的图像数据输出格式。 首先,让我们简单介绍一些定义:
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-显示模块

从上图可以看出,当HREF为高电平时输出图像数据,而当每个PCLK时HREF为高电平时输出图像数据
时钟,输出一个字节的数据。 比如我们使用VGA时序,RGB565格式输出,每2个字节构成一个像素颜色(高字节前,低字节后)这样每行输出总共有640*2个PCLK周期,输出640* 2 个字节。
帧时序(VGA 模式):

ov7670-camera-module-connection-with STONE-显示模块ov7670-camera-module-connection-with STONE-显示模块

上图清晰的显示了OV7670在VGA模式下的数据输出。 注意图中的HSYNC和HREF
它实际上是来自同一个引脚的信号,但是在不同的情况下以不同的方式,我们在本章中使用 HREF。
由于OV7670的像素时钟(PCLK)最高可以达到24Mhz,所以我们使用STM32F103ZET6的IO口直接抓取,难度很大,占用CPU很多(IO口可以通过降低PCLK的输出频率来抓取,但不推荐)。
在这个项目中,我使用的是RGB565模式,采集到的图像数据是RGB的原始数据,然后传输到 STONE 通过UART显示模块。

ov7670-camera-module-connection-with STONE-显示模块

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卡驱动太长,这里就不贴了。 您可以在网络上搜索相关代码来使用。

STM32F103ZE

网络上有很多关于这款芯片的资料和开发文档,这里简单介绍一下这款芯片。

ov7670-camera-module-connection-with STONE-显示模块

这个芯片我就不多说了。 芯片下载代码使用j-link,如下图所示:

ov7670-camera-module-connection-with STONE-显示模块

这是一个简单版的j-link,只支持SWD调试和下载,不支持JTAG。 但是对于STM32芯片的开发,SWD调试就足够了。

下载代码到STM32芯片

确保j-link和STM32F103ZE的连接正确,然后在KEIL开发环境中就可以识别芯片了:

ov7670-camera-module-connection-with STONE-显示模块

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

ov7670-camera-module-connection-with STONE-显示模块

STM32控制代码

数据接收 STONE 显示模块一次只能接收255个字节,而单个RGB565数据的图像大小为240*320*2=153600Byte=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芯片上,然后把完成的电路板接到显示屏上,保证供电稳定。 可以通过VO7670看到的图片 STONE 显示模块。

ov7670摄像头模块连接 STONE 显示模块项目结束。

运行效果

ov7670-camera-module-connection-with STONE-显示模块

ov7670-camera-module-connection-with STONE-显示模块

滚动到顶部