ov7725 stm32_如何给实验培养皿拍照

ov7725 stm32_如何给实验培养皿拍照平台:STM32ZET6(核心板)+ST-LINK/V2+SD卡+USB串口线+鹰眼OV7725摄像头(注意,为了减少摄像头连线的麻烦,建议初学者选取单片机时选用带有摄像头接口的板子)工程介绍:需要移植FatFs文件系统,同时需要了解BMP位图的存储数据结构,从而实现将摄像头输出的RGB565像素数据直接输出到sd卡上,保存为*.bmp文件。1.BMP位图的存储1.1 数据结构介绍//BMP头文…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

平台:STM32ZET6(核心板)+ST-LINK/V2+SD卡+USB串口线+鹰眼OV7725摄像头(注意,为了减少摄像头连线的麻烦,建议初学者选取单片机时选用带有摄像头接口的板子)

工程介绍:需要移植FatFs文件系统,同时需要了解BMP位图的存储数据结构,从而实现将摄像头输出的RGB565像素数据直接输出到sd卡上,保存为*.bmp文件。

ov7725 stm32_如何给实验培养皿拍照

1. BMP位图的存储

1.1 数据结构介绍

//BMP头文件
typedef __packed struct
{
    u16  bfType ;     //文件标志.只对'BM',用来识别BMP位图类型
    u32  bfSize ;	  //文件大小,占四个字节
    u16  bfReserved1 ;//保留
    u16  bfReserved2 ;//保留
    u32  bfOffBits ;  //从文件开始到位图数据(bitmap data)开始之间的的偏移量
}BITMAPFILEHEADER ;
//BMP信息头
typedef __packed struct
{
    u32 biSize ;		   	//说明BITMAPINFOHEADER结构所需要的字数。
    long  biWidth ;		   	//说明图象的宽度,以象素为单位 
    long  biHeight ;	   	        //说明图象的高度,以象素为单位 
    u16  biPlanes ;	   		//为目标设备说明位面数,其值将总是被设为1 
    u16  biBitCount ;	   	        //说明比特数/象素,其值为1、4、8、16、24、或32
    /*说明图象数据压缩的类型。其值可以是下述值之一:
		BI_RGB:没有压缩;
		BI_RLE8:每个象素8比特的RLE压缩编码,压缩格式由2字节组成(重复象素计数和颜色索引);  
                BI_RLE4:每个象素4比特的RLE压缩编码,压缩格式由2字节组成
  	        BI_BITFIELDS:每个象素的比特由指定的掩码决定。*/
    u32 biCompression ;  	
    u32 biSizeImage ;		//说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0  
    long  biXPelsPerMeter ;	//说明水平分辨率,用象素/米表示
    long  biYPelsPerMeter ;	//说明垂直分辨率,用象素/米表示
    u32 biClrUsed ;	  	//说明位图实际使用的彩色表中的颜色索引数
    u32 biClrImportant ; 	//说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。 
}BITMAPINFOHEADER ;
//彩色表 
typedef __packed struct 
{
    u8 rgbBlue ;        //指定蓝色强度
    u8 rgbGreen ;	//指定绿色强度 
    u8 rgbRed ;	  	//指定红色强度 
    u8 rgbReserved ;    //保留,设置为0 
}RGBQUAD ;
//整体信息头(以上数据结构的组合)
typedef __packed struct
{ 
	BITMAPFILEHEADER bmfHeader;
	BITMAPINFOHEADER bmiHeader;  
	RGBQUAD RGB_MASK[3];			//调色板用于存放RGB掩码.
}BITMAPINFO; 

1.2 设置方法

//提前检查是否需要保存图片
	if(ov_sta && KEY_Scan(S1))//按键1按下(拍照)
	{
		printf("开始保存图片\r\n");
		
		//打开文件,若不存在就创建
		res_sd = f_open(&fnew, "0:test1.bmp", FA_OPEN_ALWAYS | FA_WRITE);
		
		//文件打开成功
		if(res_sd == FR_OK)
		{
			//填写文件信息头信息  
			bmp.bmfHeader.bfType = 0x4D42;			//bmp类型  
			bmp.bmfHeader.bfSize= 54 + 320*240*2;	        //文件大小(信息结构体+像素数据)
			bmp.bmfHeader.bfReserved1 = 0x0000;		//保留,必须为0
			bmp.bmfHeader.bfReserved2 = 0x0000;  			
			bmp.bmfHeader.bfOffBits=54;			//位图信息结构体所占的字节数
			
			//填写位图信息头信息  
			bmp.bmiHeader.biSize=40;  		            //位图信息头的大小
			bmp.bmiHeader.biWidth=320;  			    //位图的宽度
			bmp.bmiHeader.biHeight=240;  			    //图像的高度
			bmp.bmiHeader.biPlanes=1;  		            //目标设别的级别,必须是1
			bmp.bmiHeader.biBitCount=16;                        //每像素位数
			bmp.bmiHeader.biCompression=0;  	            //RGB555格式
			bmp.bmiHeader.biSizeImage=320*240*2;                //实际位图所占用的字节数(仅考虑位图像素数据)
			bmp.bmiHeader.biXPelsPerMeter=0;		    //水平分辨率
			bmp.bmiHeader.biYPelsPerMeter=0; 		    //垂直分辨率
			bmp.bmiHeader.biClrImportant=0;   	            //说明图像显示有重要影响的颜色索引数目,0代表所有的颜色一样重要
			bmp.bmiHeader.biClrUsed=0;  			    //位图实际使用的彩色表中的颜色索引数,0表示使用所有的调色板项
			
			//RGB565格式掩码
			bmp.RGB_MASK[0].rgbBlue = 0;
			bmp.RGB_MASK[0].rgbGreen = 0xF8;
			bmp.RGB_MASK[0].rgbRed = 0;
			bmp.RGB_MASK[0].rgbReserved = 0;
			
			bmp.RGB_MASK[1].rgbBlue = 0xE0;
			bmp.RGB_MASK[1].rgbGreen = 0x07;
			bmp.RGB_MASK[1].rgbRed = 0;
			bmp.RGB_MASK[1].rgbReserved = 0;
			
			bmp.RGB_MASK[2].rgbBlue = 0x1F;
			bmp.RGB_MASK[2].rgbGreen = 0;
			bmp.RGB_MASK[2].rgbRed = 0;
			bmp.RGB_MASK[2].rgbReserved = 0;
			
			//写文件头进文件  
			res_sd= f_write(&fnew, &bmp, sizeof(bmp), &fnum);
		}
		
		//读指针复位
		OV7725_RRST=0;				//开始复位读指针
		OV7725_RCK_L;
		OV7725_RCK_H;
		OV7725_RCK_L;
		OV7725_RRST=1;				//复位读指针结束 
		OV7725_RCK_H; 
		
		/*图像花屏的原因在于读取时的干扰和读取时漏掉几个像素*/
		for(i=0;i<240;i++)
		{
			for(j=0;j<320;j++)
			{
				OV7725_RCK_L;
				color=GPIOC->IDR&0XFF;	//读数据
				OV7725_RCK_H; 
				color<<=8;  
				OV7725_RCK_L;
				color|=GPIOC->IDR&0XFF;	//读数据
				OV7725_RCK_H; 
				
				//写位图信息头进内存卡(FatFs中的方法)
				f_write(&fnew, &color, sizeof(color), &fnum);
			}
		}
		//关闭文件
		f_close(&fnew);
		
		delay_ms(1000);
		return;
	}

2. OV7725驱动程序设计

2.1 OV7725寄存器设置

#ifndef _OV7725CFG_H
#define _OV7725CFG_H
#include "ov7725.h"	
/* OV7725寄存器宏定义 */
#define GAIN      0x00
#define BLUE      0x01
#define RED       0x02
#define RED       0x02
#define GREEN     0x03
#define BAVG      0x05
#define GAVG      0x06
#define RAVG      0x07
#define AECH      0x08
#define COM2      0x09
#define PID       0x0A
#define VER       0x0B
#define COM3      0x0C
#define COM4      0x0D
#define COM5      0x0E
#define COM6      0x0F
#define AEC       0x10
#define CLKRC     0x11
#define COM7      0x12
#define COM8      0x13
#define COM9      0x14
#define COM10     0x15
#define REG16     0x16
#define HSTART    0x17
#define HSIZE     0x18
#define VSTRT     0x19
#define VSIZE     0x1A
#define PSHFT     0x1B
#define MIDH      0x1C
#define MIDL      0x1D
#define LAEC      0x1F
#define COM11     0x20
#define BDBase    0x22
#define BDMStep   0x23
#define AEW       0x24
#define AEB       0x25
#define VPT       0x26
#define REG28     0x28
#define HOutSize  0x29
#define EXHCH     0x2A
#define EXHCL     0x2B
#define VOutSize  0x2C
#define ADVFL     0x2D
#define ADVFH     0x2E
#define YAVE      0x2F
#define LumHTh    0x30
#define LumLTh    0x31
#define HREF      0x32
#define DM_LNL    0x33
#define DM_LNH    0x34
#define ADoff_B   0x35
#define ADoff_R   0x36
#define ADoff_Gb  0x37
#define ADoff_Gr  0x38
#define Off_B     0x39
#define Off_R     0x3A
#define Off_Gb    0x3B
#define Off_Gr    0x3C
#define COM12     0x3D
#define COM13     0x3E
#define COM14     0x3F
#define COM16     0x41
#define TGT_B     0x42
#define TGT_R     0x43
#define TGT_Gb    0x44
#define TGT_Gr    0x45
#define LC_CTR    0x46
#define LC_XC     0x47
#define LC_YC     0x48
#define LC_COEF   0x49
#define LC_RADI   0x4A
#define LC_COEFB  0x4B 
#define LC_COEFR  0x4C
#define FixGain   0x4D
#define AREF1     0x4F
#define AREF6     0x54
#define UFix      0x60
#define VFix      0x61
#define AWBb_blk  0x62
#define AWB_Ctrl0 0x63
#define DSP_Ctrl1 0x64
#define DSP_Ctrl2 0x65
#define DSP_Ctrl3 0x66
#define DSP_Ctrl4 0x67
#define AWB_bias  0x68
#define AWBCtrl1  0x69
#define AWBCtrl2  0x6A
#define AWBCtrl3  0x6B
#define AWBCtrl4  0x6C
#define AWBCtrl5  0x6D
#define AWBCtrl6  0x6E
#define AWBCtrl7  0x6F
#define AWBCtrl8  0x70
#define AWBCtrl9  0x71
#define AWBCtrl10 0x72
#define AWBCtrl11 0x73
#define AWBCtrl12 0x74
#define AWBCtrl13 0x75
#define AWBCtrl14 0x76
#define AWBCtrl15 0x77
#define AWBCtrl16 0x78
#define AWBCtrl17 0x79
#define AWBCtrl18 0x7A
#define AWBCtrl19 0x7B
#define AWBCtrl20 0x7C
#define AWBCtrl21 0x7D 
#define GAM1      0x7E
#define GAM2      0x7F
#define GAM3      0x80
#define GAM4      0x81
#define GAM5      0x82
#define GAM6      0x83
#define GAM7      0x84
#define GAM8      0x85
#define GAM9      0x86
#define GAM10     0x87
#define GAM11     0x88
#define GAM12     0x89
#define GAM13     0x8A
#define GAM14     0x8B
#define GAM15     0x8C
#define SLOP      0x8D
#define DNSTh     0x8E
#define EDGE0     0x8F
#define EDGE1     0x90
#define DNSOff    0x91
#define EDGE2     0x92
#define EDGE3     0x93
#define MTX1      0x94
#define MTX2      0x95
#define MTX3      0x96
#define MTX4      0x97
#define MTX5      0x98
#define MTX6      0x99
#define MTX_Ctrl  0x9A
#define BRIGHT    0x9B
#define CNST      0x9C
#define UVADJ0    0x9E
#define UVADJ1    0x9F
#define SCAL0     0xA0
#define SCAL1     0xA1
#define SCAL2     0xA2
#define SDE       0xA6
#define USAT      0xA7
#define VSAT      0xA8
#define HUECOS    0xA9
#define HUESIN    0xAA
#define SIGN      0xAB
#define DSPAuto   0xAC

//初始化寄存器序列及其对应的值
const u8 ov7725_init_reg_tb1[][2]= 
{   
	/*输出窗口设置*/
	{CLKRC,     0x00}, //clock config
	{COM7,      0x06}, //VGA RGB565
	{HSTART,    0x3f}, //水平起始位置
	{HSIZE,     0x50}, //水平尺寸
	{VSTRT,     0x03}, //垂直起始位置
	{VSIZE,     0x78}, //垂直尺寸
	{HREF,      0x00},
	{HOutSize,  0x50}, //输出尺寸
	{VOutSize,  0x78}, //输出尺寸
	
	/*DSP control*/
	{TGT_B,     0x7f},
	{FixGain,   0x09},
	{AWB_Ctrl0, 0xe0},
	{DSP_Ctrl1, 0xff},
	{DSP_Ctrl2, 0x00},
	{DSP_Ctrl3,	0x00},
	{DSP_Ctrl4, 0x00},

	/*AGC AEC AWB*/
	{COM8,		0xf0},
	{COM4,		0x81}, /*Pll AEC CONFIG*/
	{COM6,		0xc5},
	{COM9,		0x11},
	{BDBase,	0x7F},
	{BDMStep,	0x03},
	{AEW,		0x40},
	{AEB,		0x30},
	{VPT,		0xa1},
	{EXHCL,		0x9e},
	{AWBCtrl3,  0xaa},
	{COM8,		0xff},
	
	/*matrix shapness brightness contrast*/
	{EDGE1,		0x08},
	{DNSOff,	0x01},
	{EDGE2,		0x03},
	{EDGE3,		0x00},
	{MTX1,		0xb0},
	{MTX2,		0x9d},
	{MTX3,		0x13},
	{MTX4,		0x16},
	{MTX5,		0x7b},
	{MTX6,		0x91},
	{MTX_Ctrl,  0x1e},
	{BRIGHT,	0x08},
	{CNST,		0x20},
	{UVADJ0,	0x81},
	{SDE, 		0X06},
	{USAT,		0x65},
	{VSAT,		0x65},
	{HUECOS,	0X80},
	{HUESIN, 	0X80},
	
        /*GAMMA config*/
	{GAM1,		0x0c},
	{GAM2,		0x16},
	{GAM3,		0x2a},
	{GAM4,		0x4e},
	{GAM5,		0x61},
	{GAM6,		0x6f},
	{GAM7,		0x7b},
	{GAM8,		0x86},
	{GAM9,		0x8e},
	{GAM10,		0x97},
	{GAM11,		0xa4},
	{GAM12,		0xaf},
	{GAM13,		0xc5},
	{GAM14,		0xd7},
	{GAM15,		0xe8},
	{SLOP,		0x20},

	
	{COM3,		0x50},/*Horizontal mirror image*/
					  //注:datasheet默认0x10,即改变YUV为UVY格式。但是摄像头不是芯片而是模组时,
					  //要将0X10中的1变成0,即设置YUV格式。
	/*night mode auto frame rate control*/ 
	{COM5,		0xf5},	 /*在夜视环境下,自动降低帧率,保证低照度画面质量*/
	//{COM5,		0x31},	/*夜视环境帧率不变*/
	
};
#endif

2.2 OV7725初始化

#define OV7725_MID				0X7FA2    
#define OV7725_PID				0X7721

#define OV7725_VSYNC  	PAin(8)			        //同步信号检测IO
#define OV7725_WRST		PDout(6)		//写指针复位
#define OV7725_WREN		PBout(3)		//写入FIFO使能
#define OV7725_RCK_H	GPIOB->BSRR=1<<4                //设置读数据时钟高电平
#define OV7725_RCK_L	GPIOB->BRR=1<<4	                //设置读数据时钟低电平
#define OV7725_RRST		PGout(14)  		//读指针复位
#define OV7725_CS		PGout(15)  		//片选信号(OE)
								  					 
#define OV7725_DATA   	GPIO_ReadInputData(GPIOC,0x00FF) 	//数据输入端口
#include "sys.h"
#include "ov7725.h"
#include "ov7725config.h"	  
#include "delay.h"
#include "usart.h"			 
#include "sccb.h"	
//初始化OV7725
//返回0:成功
//返回其他值:错误代码
u8 OV7725_Init(void)
{
	u16 i=0;
	u16 reg=0;
	//设置IO
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOG|RCC_APB2Periph_AFIO, ENABLE);//使能相关端口时钟
 
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_8; 	//PA8 输入 上拉
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_SetBits(GPIOA,GPIO_Pin_8);
		
 	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; //PC0~7 输入 上拉
	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;	//软复位OV7725
	delay_ms(100); 
	reg=SCCB_RD_Reg(0X1c);		//读取厂家ID 高八位
	reg<<=8;
	reg|=SCCB_RD_Reg(0X1d);		//读取厂家ID 低八位
	if(reg!=OV7725_MID)
	{
		printf("MID:%d\r\n",reg);
		return 1;
	}
	reg=SCCB_RD_Reg(0X0a);		//读取厂家ID 高八位
	reg<<=8;
	reg|=SCCB_RD_Reg(0X0b);		//读取厂家ID 低八位
	if(reg!=OV7725_PID)
	{
		printf("HID:%d\r\n",reg);
		return 2;
	}
 	//初始化 OV7725,采用QVGA分辨率(320*240)  
	for(i=0;i<sizeof(ov7725_init_reg_tb1)/sizeof(ov7725_init_reg_tb1[0]);i++)
	{
	   	SCCB_WR_Reg(ov7725_init_reg_tb1[i][0],ov7725_init_reg_tb1[i][1]);
 	} 
	printf("HID:%d\r\n",reg);
  return 0x00; 	//ok
} 

2.3 OV7725其他功能设置


//OV7725功能设置
//白平衡设置
//0:自动模式
//1:晴天
//2,多云
//3,办公室
//4,家里
//5,夜晚
void OV7725_Light_Mode(u8 mode)
{
	switch(mode)
	{
		case 0:	//Auto,自动模式
			SCCB_WR_Reg(0x13, 0xff); //AWB on 
			SCCB_WR_Reg(0x0e, 0x65);
			SCCB_WR_Reg(0x2d, 0x00);
			SCCB_WR_Reg(0x2e, 0x00);
			break;
		case 1://sunny,晴天
			SCCB_WR_Reg(0x13, 0xfd); //AWB off
			SCCB_WR_Reg(0x01, 0x5a);
			SCCB_WR_Reg(0x02, 0x5c);
			SCCB_WR_Reg(0x0e, 0x65);
			SCCB_WR_Reg(0x2d, 0x00);
			SCCB_WR_Reg(0x2e, 0x00);
			break;	
		case 2://cloudy,多云
			SCCB_WR_Reg(0x13, 0xfd); //AWB off
			SCCB_WR_Reg(0x01, 0x58);
			SCCB_WR_Reg(0x02, 0x60);
			SCCB_WR_Reg(0x0e, 0x65);
			SCCB_WR_Reg(0x2d, 0x00);
			SCCB_WR_Reg(0x2e, 0x00);
			break;	
		case 3://office,办公室
			SCCB_WR_Reg(0x13, 0xfd); //AWB off
			SCCB_WR_Reg(0x01, 0x84);
			SCCB_WR_Reg(0x02, 0x4c);
			SCCB_WR_Reg(0x0e, 0x65);
			SCCB_WR_Reg(0x2d, 0x00);
			SCCB_WR_Reg(0x2e, 0x00);
			break;	
		case 4://home,家里
			SCCB_WR_Reg(0x13, 0xfd); //AWB off
			SCCB_WR_Reg(0x01, 0x96);
			SCCB_WR_Reg(0x02, 0x40);
			SCCB_WR_Reg(0x0e, 0x65);
			SCCB_WR_Reg(0x2d, 0x00);
			SCCB_WR_Reg(0x2e, 0x00);
			break;	

		case 5://night,夜晚
			SCCB_WR_Reg(0x13, 0xff); //AWB on
			SCCB_WR_Reg(0x0e, 0xe5);
			break;
	}
}		  
//色度设置
//sat:-4~+4
void OV7725_Color_Saturation(s8 sat)
{
 	if(sat>=-4 && sat<=4)
	{	
		SCCB_WR_Reg(USAT,(sat+4)<<4); 
		SCCB_WR_Reg(VSAT,(sat+4)<<4);
	}
}
//亮度设置
//bright:-4~+4
void OV7725_Brightness(s8 bright)
{
	u8 bright_value,sign;
  	switch(bright)
	{
		case 4:
			bright_value = 0x48;
			sign = 0x06;
			break;
		case 3:
			bright_value = 0x38;
			sign = 0x06;		
			break;	
		case 2:
			bright_value = 0x28;
			sign = 0x06;			
			break;	
		case 1:
			bright_value = 0x18;
			sign = 0x06;			
			break;
		case 0:
			bright_value = 0x08;
			sign = 0x06;			
			break;	
		case -1:
			bright_value = 0x08;
			sign = 0x0e;		
			break;		
		case -2:
			bright_value = 0x18;
			sign = 0x0e;		
			break;	
		case -3:
			bright_value = 0x28;
			sign = 0x0e;		
			break;	
		case -4:
			bright_value = 0x38;
			sign = 0x0e;		
			break;	
	}
	SCCB_WR_Reg(BRIGHT, bright_value);
	SCCB_WR_Reg(SIGN, sign);
}
//对比度设置
//contrast:-4~+4
void OV7725_Contrast(s8 contrast)
{
	if(contrast >= -4 && contrast <=4)
	{
		SCCB_WR_Reg(CNST,(0x30-(4-contrast)*4));
	}
}
//特效设置
//0:普通模式    
//1,负片
//2,黑白   
//3,偏红色
//4,偏绿色
//5,偏蓝色
//6,复古	    
void OV7725_Special_Effects(u8 eft)
{
	switch(eft)
	{
		case 0://正常
			SCCB_WR_Reg(0xa6, 0x06);//TSLB设置
			SCCB_WR_Reg(0x60, 0x80);//MANV,手动V值
			SCCB_WR_Reg(0x61, 0x80);//MANU,手动U值
			break;
		case 1://负片
			SCCB_WR_Reg(0xa6, 0x46);
			break;
		case 2://黑白
			SCCB_WR_Reg(0xa6, 0x26);
			SCCB_WR_Reg(0x60, 0x80);
			SCCB_WR_Reg(0x61, 0x80);
			break;		
		case 3://偏红
			SCCB_WR_Reg(0xa6, 0x1e);
			SCCB_WR_Reg(0x60, 0x80);
			SCCB_WR_Reg(0x61, 0xc0);		
			break;
		case 4://偏绿
			SCCB_WR_Reg(0xa6, 0x1e);
			SCCB_WR_Reg(0x60, 0x60);
			SCCB_WR_Reg(0x61, 0x60);		
			break;
		case 5://偏蓝
			SCCB_WR_Reg(0xa6, 0x1e);
			SCCB_WR_Reg(0x60, 0xa0);
			SCCB_WR_Reg(0x61, 0x40);	
			break;
		case 6://复古
			SCCB_WR_Reg(0xa6, 0x1e);
			SCCB_WR_Reg(0x60, 0x40);
			SCCB_WR_Reg(0x61, 0xa0);
			break;	

	}
}

2.4 设置OV7725输出窗口和输出数据的格式(QVGA或VGA)

//设置图像输出窗口
//width:输出图像宽度,<=320
//height:输出图像高度,<=240
//mode:0,QVGA输出模式;1,VGA输出模式
//QVGA模式可视范围广但近物不是很清晰,VGA模式可视范围小近物清晰
void OV7725_Window_Set(u16 width,u16 height,u8 mode)
{
	u8 raw,temp;
	u16 sx,sy;	
	if(mode)
	{
		sx=(640-width)/2;
		sy=(480-height)/2;
		SCCB_WR_Reg(COM7,0x06);		//设置为VGA模式
		SCCB_WR_Reg(HSTART,0x23); 	//水平起始位置
		SCCB_WR_Reg(HSIZE,0xA0); 	//水平尺寸
		SCCB_WR_Reg(VSTRT,0x07); 	//垂直起始位置
		SCCB_WR_Reg(VSIZE,0xF0); 	//垂直尺寸
		SCCB_WR_Reg(HREF,0x00);
		SCCB_WR_Reg(HOutSize,0xA0); //输出尺寸
		SCCB_WR_Reg(VOutSize,0xF0); //输出尺寸
	}
	else
	{
		sx=(320-width)/2;
		sy=(240-height)/2;
		SCCB_WR_Reg(COM7,0x46);		//设置为QVGA模式
		SCCB_WR_Reg(HSTART,0x3f); 	//水平起始位置
		SCCB_WR_Reg(HSIZE, 0x50); 	//水平尺寸
		SCCB_WR_Reg(VSTRT, 0x03); 	//垂直起始位置
		SCCB_WR_Reg(VSIZE, 0x78); 	//垂直尺寸
		SCCB_WR_Reg(HREF,  0x00);
		SCCB_WR_Reg(HOutSize,0x50);	//输出尺寸
		SCCB_WR_Reg(VOutSize,0x78); //输出尺寸
	}
	raw=SCCB_RD_Reg(HSTART);
	temp=raw+(sx>>2);//sx高8位存在HSTART,低2位存在HREF[5:4]
	SCCB_WR_Reg(HSTART,temp);
	SCCB_WR_Reg(HSIZE,width>>2);//width高8位存在HSIZE,低2位存在HREF[1:0]
	
	raw=SCCB_RD_Reg(VSTRT);
	temp=raw+(sy>>1);//sy高8位存在VSTRT,低1位存在HREF[6]
	SCCB_WR_Reg(VSTRT,temp);
	SCCB_WR_Reg(VSIZE,height>>1);//height高8位存在VSIZE,低1位存在HREF[2]
	
	raw=SCCB_RD_Reg(HREF);
	temp=((sy&0x01)<<6)|((sx&0x03)<<4)|((height&0x01)<<2)|(width&0x03)|raw;
	SCCB_WR_Reg(HREF,temp);
	
	SCCB_WR_Reg(HOutSize,width>>2);
	SCCB_WR_Reg(VOutSize,height>>1);
	
	SCCB_RD_Reg(EXHCH);	
	temp = (raw|(width&0x03)|((height&0x01)<<2));	
	SCCB_WR_Reg(EXHCH,temp);	
}

3. VSYNC中断配置(帧中断信号处理)

3.1 中断GPIO口初始化

//外部中断8初始化
void EXTI8_Init(void)
{   
	EXTI_InitTypeDef EXTI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure; 
	
	//选择中断信号源,开启中断线
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource8);//PA8对中断线8
	
	EXTI_InitStructure.EXTI_Line=EXTI_Line8;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;;//下降沿触发
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);		//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;			//使能按键所在的外部中断通道
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	//抢占优先级0 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;					//子优先级0 
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}

3.2 中断服务程序

 //外部中断5~9服务程序,外部中断5-9和中断10-15向量存放在一起
void EXTI9_5_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line8)==SET)//是8线的中断
	{
		if(ov_sta<2)
		{
			if(ov_sta==0)
			{
				OV7725_WRST=0;	 	//复位写指针		  		 
				OV7725_WRST=1;	
				OV7725_WREN=1;		//允许写入FIFO
			}else 
			{
				OV7725_WREN=0;		//禁止写入FIFO 
				OV7725_WRST=0;	 	//复位写指针		  		 
				OV7725_WRST=1;	
			}
			ov_sta++;
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line8);  //清除EXTI8线路挂起位
} 

4. 主函数

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"
#include "string.h"
#include "OV7725.h"
#include "timer.h"
#include "exti.h"
#include "ff.h"
#include "sdio.h"

//const u8*LMODE_TBL[5]={"Auto","Sunny","Cloudy","Office","Home"};															//5种光照模式
//const u8*EFFECTS_TBL[7]={"Normal","Negative","B&W","Redish","Greenish","Bluish","Antique"};		//7种特效
extern u8 ov_sta;	//在exit.c里面定义
extern u8 ov_frame;	//在timer.c里面定义

//由于OV7725传感器安装方式原因,OV7725_WINDOW_WIDTH相当于LCD的高度,OV7725_WINDOW_HEIGHT相当于LCD的宽度
//注意:此宏定义只对OV7725有效
#define  OV7725_WINDOW_WIDTH		320 // <=320
#define  OV7725_WINDOW_HEIGHT		240 // <=240

//内存卡的读写状态
SD_Error Status;
FATFS fs; //FatFs文件系统对象
FIL fnew; //文件对象
FRESULT res_sd;//文件操作结果
UINT fnum; //文件成功读写数量

//BMP头文件
typedef __packed struct
{
    u16  bfType ;     //文件标志.只对'BM',用来识别BMP位图类型
    u32  bfSize ;	  //文件大小,占四个字节
    u16  bfReserved1 ;//保留
    u16  bfReserved2 ;//保留
    u32  bfOffBits ;  //从文件开始到位图数据(bitmap data)开始之间的的偏移量
}BITMAPFILEHEADER ;
//BMP信息头
typedef __packed struct
{
    u32 biSize ;		   		//说明BITMAPINFOHEADER结构所需要的字数。
    long  biWidth ;		   	//说明图象的宽度,以象素为单位 
    long  biHeight ;	   	//说明图象的高度,以象素为单位 
    u16  biPlanes ;	   		//为目标设备说明位面数,其值将总是被设为1 
    u16  biBitCount ;	   	//说明比特数/象素,其值为1、4、8、16、24、或32
		/*说明图象数据压缩的类型。其值可以是下述值之一:
		BI_RGB:没有压缩;
		BI_RLE8:每个象素8比特的RLE压缩编码,压缩格式由2字节组成(重复象素计数和颜色索引);  
    BI_RLE4:每个象素4比特的RLE压缩编码,压缩格式由2字节组成
  	BI_BITFIELDS:每个象素的比特由指定的掩码决定。*/
    u32 biCompression ;  	
    u32 biSizeImage ;		//说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0  
    long  biXPelsPerMeter ;	//说明水平分辨率,用象素/米表示
    long  biYPelsPerMeter ;	//说明垂直分辨率,用象素/米表示
    u32 biClrUsed ;	  	 	//说明位图实际使用的彩色表中的颜色索引数
    u32 biClrImportant ; 	//说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。 
}BITMAPINFOHEADER ;
//彩色表 
typedef __packed struct 
{
    u8 rgbBlue ;    //指定蓝色强度
    u8 rgbGreen ;	//指定绿色强度 
    u8 rgbRed ;	  	//指定红色强度 
    u8 rgbReserved ;//保留,设置为0 
}RGBQUAD ;
//整体信息头
typedef __packed struct
{ 
	BITMAPFILEHEADER bmfHeader;
	BITMAPINFOHEADER bmiHeader;  
	RGBQUAD RGB_MASK[3];			//调色板用于存放RGB掩码.
}BITMAPINFO; 

//更新LCD显示
void camera_refresh(void)
{
	u32 i,j;
 	u16 color;
	BITMAPINFO bmp;
	
	//提前检查是否需要保存图片
	if(ov_sta && KEY_Scan(S1))//按键1按下
	{
		printf("开始保存图片\r\n");
		
		//打开文件,若不存在就创建
		res_sd = f_open(&fnew, "0:test1.bmp", FA_OPEN_ALWAYS | FA_WRITE);
		
		//文件打开成功
		if(res_sd == FR_OK)
		{
			//填写文件信息头信息  
			bmp.bmfHeader.bfType = 0x4D42;				//bmp类型  
			bmp.bmfHeader.bfSize= 54 + 320*240*2;	//文件大小(信息结构体+像素数据)
			bmp.bmfHeader.bfReserved1 = 0x0000;		//保留,必须为0
			bmp.bmfHeader.bfReserved2 = 0x0000;  			
			bmp.bmfHeader.bfOffBits=54;						//位图信息结构体所占的字节数
			
			//填写位图信息头信息  
			bmp.bmiHeader.biSize=40;  				    //位图信息头的大小
			bmp.bmiHeader.biWidth=320;  					//位图的宽度
			bmp.bmiHeader.biHeight=240;  			    //图像的高度
			bmp.bmiHeader.biPlanes=1;  				    //目标设别的级别,必须是1
			bmp.bmiHeader.biBitCount=16;          //每像素位数
			bmp.bmiHeader.biCompression=0;  	    //RGB555格式
			bmp.bmiHeader.biSizeImage=320*240*2;  //实际位图所占用的字节数(仅考虑位图像素数据)
			bmp.bmiHeader.biXPelsPerMeter=0;		  //水平分辨率
			bmp.bmiHeader.biYPelsPerMeter=0; 			//垂直分辨率
			bmp.bmiHeader.biClrImportant=0;   	  //说明图像显示有重要影响的颜色索引数目,0代表所有的颜色一样重要
			bmp.bmiHeader.biClrUsed=0;  			    //位图实际使用的彩色表中的颜色索引数,0表示使用所有的调色板项
			
			//RGB565格式掩码
			bmp.RGB_MASK[0].rgbBlue = 0;
			bmp.RGB_MASK[0].rgbGreen = 0xF8;
			bmp.RGB_MASK[0].rgbRed = 0;
			bmp.RGB_MASK[0].rgbReserved = 0;
			
			bmp.RGB_MASK[1].rgbBlue = 0xE0;
			bmp.RGB_MASK[1].rgbGreen = 0x07;
			bmp.RGB_MASK[1].rgbRed = 0;
			bmp.RGB_MASK[1].rgbReserved = 0;
			
			bmp.RGB_MASK[2].rgbBlue = 0x1F;
			bmp.RGB_MASK[2].rgbGreen = 0;
			bmp.RGB_MASK[2].rgbRed = 0;
			bmp.RGB_MASK[2].rgbReserved = 0;
			
			//写文件头进文件  
			res_sd= f_write(&fnew, &bmp, sizeof(bmp), &fnum);
		}
		
		//读指针复位
		OV7725_RRST=0;				//开始复位读指针
		OV7725_RCK_L;
		OV7725_RCK_H;
		OV7725_RCK_L;
		OV7725_RRST=1;				//复位读指针结束 
		OV7725_RCK_H; 
		
		/*图像花屏的原因在于读取时的干扰和读取时漏掉几个像素*/
		for(i=0;i<240;i++)
		{
			for(j=0;j<320;j++)
			{
				OV7725_RCK_L;
				color=GPIOC->IDR&0XFF;	//读数据
				OV7725_RCK_H; 
				color<<=8;  
				OV7725_RCK_L;
				color|=GPIOC->IDR&0XFF;	//读数据
				OV7725_RCK_H; 
				
				//写位图信息头进内存卡
				f_write(&fnew, &color, sizeof(color), &fnum);
			}
		}
			
		//关闭文件
		f_close(&fnew);
		
		delay_ms(1000);
		return;
	}
	
	//不需要保存图片,继续刷新LCD
	if(ov_sta)
	{
		LCD_Scan_Dir(U2D_L2R);		//从上到下,从左到右 
		LCD_WriteRAM_Prepare();   //开始写入GRAM	
		
		//读指针复位
		OV7725_RRST=0;				//开始复位读指针 
		OV7725_RCK_L;
		OV7725_RCK_H;
		OV7725_RCK_L;
		OV7725_RRST=1;				//复位读指针结束 
		OV7725_RCK_H; 
		
		/*图像花屏的原因在于读取时的干扰和读取时漏掉几个像素*/
		for(i=0;i<240;i++)
		{
			for(j=0;j<320;j++)
			{
				OV7725_RCK_L;
				color=GPIOC->IDR&0XFF;	//读数据
				OV7725_RCK_H; 
				color<<=8;  
				OV7725_RCK_L;
				color|=GPIOC->IDR&0XFF;	//读数据
				OV7725_RCK_H; 
				LCD->LCD_RAM=color; 
			}
		}
		ov_sta=0;					//开始下一次采集
		ov_frame++; 
		LCD_Scan_Dir(DFT_SCAN_DIR);	//恢复默认扫描方向 
	}
}
 int main(void)
 {
	u8 lightmode=0,saturation=2,brightness=2,contrast=2;
	u8 effect=0;
 	u8 i=0;

	delay_init();	    	 	                //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 		        //串口初始化为 115200
 	LED_Init();		  			//初始化与LED连接的硬件接口
	KEY_Init();					//初始化按键
	LCD_Init();			   		//初始化LCD  
	
	//初始化SD卡
	if(SD_Init() == SD_OK)
	{
		printf("SD卡初始化成功,即将挂载SD卡。\r\n");
	}
	
	//挂载SD卡
	res_sd = f_mount(&fs, "0:", 1);
	
 	POINT_COLOR=RED;//设置字体为红色 
	LCD_ShowString(60,50,200,16,16,"M3S STM32");	
	LCD_ShowString(60,70,200,16,16,"OV7725 TEST");	
	LCD_ShowString(60,90,200,16,16,"www.doflye.net");
	LCD_ShowString(60,110,200,16,16,"need a 7725 camera");  
	LCD_ShowString(60,130,200,16,16,"S1:Light Mode");
	LCD_ShowString(60,150,200,16,16,"S2:Saturation");
	LCD_ShowString(60,170,200,16,16,"S3:Brightness");
	LCD_ShowString(60,190,200,16,16,"S4:Contrast");
	LCD_ShowString(60,210,200,16,16,"OV7725 Init...");	  
	
 	while(1)
	{
		//初始化ov7725
		if(OV7725_Init()==0)
		{
			LCD_ShowString(60,210,200,16,16,"OV7725 Init OK       ");
                        OV7725_Light_Mode(lightmode);
			OV7725_Color_Saturation(saturation);
			OV7725_Brightness(brightness);
			OV7725_Contrast(contrast);
			OV7725_Special_Effects(effect);
			//设置输出格式
			OV7725_Window_Set(OV7725_WINDOW_WIDTH,OV7725_WINDOW_HEIGHT,0);    //QVGA模式输出
			//输出使能
			OV7725_CS=0;
			break;
		}
	}						  
	EXTI8_Init();			//使能定时器捕获				
	LCD_Clear(BLACK);		//可以防止割屏
	while(1)
	{
		camera_refresh();       //更新显示
		i++;
		if(i==15)               //DS0闪烁.
		{
			i=0;
			LED0=!LED0;
		}
	}
}

5. 实验效果

按下按钮S1,LCD图像停止刷新一秒,然后再SD卡上生成一张test1.bmp文件,在电脑端查看如下所示

ov7725 stm32_如何给实验培养皿拍照

(数据有点问题,(:)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/190077.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • redis可视化工具使用_redis图形化

    redis可视化工具使用_redis图形化启动redis服务执行命令:redis-server.exe建立连接redis-cli.exe-h127.0.0.1-p6379搞一条件数据key1–>myRedis下载redisClient客户端只有一个exe文件,不用安装,直接打开就行添加连接后可以看到一共有16个库,刚才添加的数据已经在缓存数据库里边了done!!!…

    2022年10月10日
  • pycharm整体向前缩进_pycharm快速缩进

    pycharm整体向前缩进_pycharm快速缩进在PyCharm以及Vs中,只要拉住我们想要修改的选块后,不松开鼠标的同时按下tab键后,整个块就会缩进;同时按下shift+tab键后,就会进行反向缩进。如下图:…

  • MODIS数据说明

    MODIS数据说明MODIS目前主要存在于两颗卫星上:TERRA和AQUA。TERRA卫星每日地方时上午10:30时过境,因此也把它称作地球观测第一颗上午星(EOS-AM1)。AQUA每日地方时下午过境,因此称作地球观测第一颗下午星(EOS-PM1)。两颗星相互配合,每1-2天可重复观测整个地球表面,得到36个波段(表1)的观测得到,这些数据广泛用于全球陆地、海洋和低层大气内的动态变化过程研究。MODIS获

  • armv7在哪儿看(armv7s)

    iOS中的armv7,armv7s,arm64,i386,x86_64都是什么在做静态库的时候以及引用静态库的时候经常会遇到一些关于真机模拟器不通用的情况,会报错找不到相应库导致编译失败,这里简单记录一下各种设备支持的架构。iOS测试分为模拟器测试和真机测试,处理器分为32位处理器,和64位处理器,模拟器32位处理器测试需要i386架构,(iphone5,iphone5s以下的模拟器…

  • 电脑爱好者GHOSTWIN7纯净版v2.0

    电脑爱好者GHOSTWIN7纯净版v2.0系统特点:全自动无人值守安装,采用万能GHOST技术,安装系统过程只需5-8分钟,适合新旧各种机型。集成常见硬件驱动,智能识别+预解压技术,绝大多数硬件可以快速自动安装相应的驱动。VC++2005|2008|2010|2012|2013系统使用系统总裁论坛最新封装工具和IT天空论坛(稳定版)最新驱动包制作而成。我的文档收藏夹虚拟内存智能转移精简列表:示例文件Wi…

  • java实现简单的图书管理系统「建议收藏」

    java实现简单的图书管理系统「建议收藏」一、项目分布Book类:定义了书的一些属性(书名,作者,价格,分类,状态)并且写了属性的get、set方法Library类:写了登录函数(1、普通用户,2、管理员,3、退出系统),Person类:定义的人的属性(姓名,性别,年龄)并且写了属性的get、set方法,定义了一些书。operate接口:操作的接口,操作方法:查询/查阅,删除/借阅,增加/还书,显示书籍列表Root类:继承…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号