OV2640

news/2024/12/23 4:20:50/

OV2640

硬件连接
在这里插入图片描述

通过开发板的OLED/CAMERA接口与摄像头模块连接。具体引脚连接如上图所示

SCCB时序
外部控制器对OV2640寄存器的配置参数是通过SCCB总线传输过去的,而SCCB总线跟I2C十分类似,在STM32驱动中直接使用片上I2C外设与它通讯。 SCCB与标准的I2C协议的区别是它每次传输只能写入或读取一个字节的数据,而I2C协议是支持突发读写的, 即在一次传输中可以写入多个字节的数据(EEPROM中的页写入时序即突发写)。
SCCB的起始、停止信号及数据有效性
SCCB的起始信号、停止信号及数据有效性与I2C完全一样
起始信号:在SIO_C为高电平时,SIO_D出现一个下降沿,则SCCB开始传输。
停止信号:在SIO_C为高电平时,SIO_D出现一个上升沿,则SCCB停止传输。
在这里插入图片描述

数据有效性:除了开始和停止状态,在数据传输过程中,当SIO_C为高电平时,必须保证SIO_D上的数据稳定,即SIO_D上的电平变换只能发生在SIO_C为低电平的时候,SIO_D的信号在SIO_C为高电平时被采集。
SCCB数据读写过程
在SCCB协议中定义的读写操作与I2C一样。它定义了两种写操作,即三步写操作和两步写操作。 三步写操作可向从设备的一个目的寄存器中写入数据 。第一阶段发送从设备的ID地址+W标志(等于I2C的设备地址:7位设备地址+读写方向标志),第二阶段发送从设备目标寄存器的8位地址, 第三阶段发送要写入寄存器的8位数据。图中的“X”数据位可写入1或0,对通讯无影响。(见下图)
在这里插入图片描述
而两步写操作没有第三阶段,即只向从器件传输了设备ID+W标志和目的寄存器的地址 。 两步写操作是用来配合后面的读寄存器数据操作的,它与读操作一起使用,实现I2C的复合过程。

在这里插入图片描述
两步读操作用于读取从设备目的寄存器中的数据。在第一阶段中发送从设备的设备ID+R标志(设备地址+读方向标志)和自由位, 在第二阶段中读取寄存器中的8位数据和写NA位(非应答信号)。由于两步读操作没有确定目的寄存器的地址, 所以在读操作前,必需有一个两步写操作,以提供读操作中的寄存器地址。
在这里插入图片描述

以上介绍的SCCB特性都与I2C无区别,而I2C比SCCB还多出了突发读写的功能,因此我们可以使用STM32的I2C外设来与OV2640进行SCCB通讯。

相关宏

/*摄像头接口 */
//IIC SCCB
#define CAMERA_I2C                          I2C1
#define CAMERA_I2C_CLK                      RCC_APB1Periph_I2C1#define CAMERA_I2C_SCL_PIN                  GPIO_Pin_8
#define CAMERA_I2C_SCL_GPIO_PORT            GPIOB
#define CAMERA_I2C_SCL_GPIO_CLK             RCC_AHB1Periph_GPIOB
#define CAMERA_I2C_SCL_SOURCE               GPIO_PinSource8
#define CAMERA_I2C_SCL_AF                   GPIO_AF_I2C1#define CAMERA_I2C_SDA_PIN                  GPIO_Pin_9
#define CAMERA_I2C_SDA_GPIO_PORT            GPIOB
#define CAMERA_I2C_SDA_GPIO_CLK             RCC_AHB1Periph_GPIOB
#define CAMERA_I2C_SDA_SOURCE               GPIO_PinSource9
#define CAMERA_I2C_SDA_AF                   GPIO_AF_I2C1//VSYNC
#define DCMI_VSYNC_GPIO_PORT            GPIOB
#define DCMI_VSYNC_GPIO_CLK             RCC_AHB1Periph_GPIOB
#define DCMI_VSYNC_GPIO_PIN             GPIO_Pin_7
#define DCMI_VSYNC_PINSOURCE            GPIO_PinSource7
#define DCMI_VSYNC_AF                     GPIO_AF_DCMI
// HSYNC
#define DCMI_HSYNC_GPIO_PORT            GPIOA
#define DCMI_HSYNC_GPIO_CLK             RCC_AHB1Periph_GPIOA
#define DCMI_HSYNC_GPIO_PIN             GPIO_Pin_4
#define DCMI_HSYNC_PINSOURCE            GPIO_PinSource4
#define DCMI_HSYNC_AF                     GPIO_AF_DCMI
//PIXCLK
#define DCMI_PIXCLK_GPIO_PORT           GPIOA
#define DCMI_PIXCLK_GPIO_CLK            RCC_AHB1Periph_GPIOA
#define DCMI_PIXCLK_GPIO_PIN            GPIO_Pin_6
#define DCMI_PIXCLK_PINSOURCE           GPIO_PinSource6
#define DCMI_PIXCLK_AF                    GPIO_AF_DCMI
//PWDN
#define DCMI_PWDN_GPIO_PORT         GPIOC
#define DCMI_PWDN_GPIO_CLK          RCC_AHB1Periph_GPIOC
#define DCMI_PWDN_GPIO_PIN          GPIO_Pin_0//数据信号线
#define DCMI_D0_GPIO_PORT           GPIOC
#define DCMI_D0_GPIO_CLK            RCC_AHB1Periph_GPIOC
#define DCMI_D0_GPIO_PIN            GPIO_Pin_6
#define DCMI_D0_PINSOURCE           GPIO_PinSource6
#define DCMI_D0_AF                    GPIO_AF_DCMI

要点:
1.初始化DCMI时钟,I2C时钟;
2.使用I2C接口向OV2640写入寄存器配置;
3.初始化DCMI工作模式;
4.初始化DMA,用于搬运DCMI的数据到显存空间进行显示;
5.编写测试程序,控制采集图像数据并显示到液晶屏。

初始化DCMI的 GPIO及I2C

void OV2640_HW_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;I2C_InitTypeDef  I2C_InitStruct;/***DCMI引脚配置***//* 使能DCMI时钟 */RCC_AHB1PeriphClockCmd(DCMI_PWDN_GPIO_CLK|DCMI_VSYNC_GPIO_CLK |DCMI_HSYNC_GPIO_CLK | DCMI_PIXCLK_GPIO_CLK|DCMI_D0_GPIO_CLK| DCMI_D1_GPIO_CLK|, ENABLE);/*控制/同步信号线*/GPIO_InitStructure.GPIO_Pin = DCMI_VSYNC_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;GPIO_Init(DCMI_VSYNC_GPIO_PORT, &GPIO_InitStructure);GPIO_PinAFConfig(DCMI_VSYNC_GPIO_PORT, DCMI_VSYNC_PINSOURCE, DCMI_VSYNC_AF);GPIO_InitStructure.GPIO_Pin = DCMI_HSYNC_GPIO_PIN ;GPIO_Init(DCMI_HSYNC_GPIO_PORT, &GPIO_InitStructure);GPIO_PinAFConfig(DCMI_HSYNC_GPIO_PORT, DCMI_HSYNC_PINSOURCE, DCMI_HSYNC_AF);GPIO_InitStructure.GPIO_Pin = DCMI_PIXCLK_GPIO_PIN ;GPIO_Init(DCMI_PIXCLK_GPIO_PORT, &GPIO_InitStructure);GPIO_PinAFConfig(DCMI_PIXCLK_GPIO_PORT, DCMI_PIXCLK_PINSOURCE, DCMI_PIXCLK_AF);GPIO_InitStructure.GPIO_Pin = DCMI_PWDN_GPIO_PIN ;GPIO_Init(DCMI_PWDN_GPIO_PORT, &GPIO_InitStructure);/*PWDN引脚,高电平关闭电源,低电平供电*/GPIO_ResetBits(DCMI_PWDN_GPIO_PORT,DCMI_PWDN_GPIO_PIN);/*数据信号*/GPIO_InitStructure.GPIO_Pin = DCMI_D0_GPIO_PIN ;GPIO_Init(DCMI_D0_GPIO_PORT, &GPIO_InitStructure);GPIO_PinAFConfig(DCMI_D0_GPIO_PORT, DCMI_D0_PINSOURCE, DCMI_D0_AF);/*...省略部分数据信号线*//****** 配置I2C,使用I2C与摄像头的SCCB接口通讯*****//* 使能I2C时钟 */RCC_APB1PeriphClockCmd(CAMERA_I2C_CLK, ENABLE);/* 使能I2C使用的GPIO时钟 */RCC_AHB1PeriphClockCmd(CAMERA_I2C_SCL_GPIO_CLK|CAMERA_I2C_SDA_GPIO_CLK, ENABLE);/* 配置引脚源 */GPIO_PinAFConfig(CAMERA_I2C_SCL_GPIO_PORT, CAMERA_I2C_SCL_SOURCE, CAMERA_I2C_SCL_AF);GPIO_PinAFConfig(CAMERA_I2C_SDA_GPIO_PORT, CAMERA_I2C_SDA_SOURCE, CAMERA_I2C_SDA_AF);/* 初始化GPIO */GPIO_InitStructure.GPIO_Pin = CAMERA_I2C_SCL_PIN ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(CAMERA_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);GPIO_PinAFConfig(CAMERA_I2C_SCL_GPIO_PORT, CAMERA_I2C_SCL_SOURCE, CAMERA_I2C_SCL_AF);GPIO_InitStructure.GPIO_Pin = CAMERA_I2C_SDA_PIN ;GPIO_Init(CAMERA_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);/*初始化I2C模式 */I2C_DeInit(CAMERA_I2C);I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;I2C_InitStruct.I2C_OwnAddress1 = 0xFE;I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_InitStruct.I2C_ClockSpeed = 40000;/* 写入配置 */I2C_Init(CAMERA_I2C, &I2C_InitStruct);/* 使能I2C */I2C_Cmd(CAMERA_I2C, ENABLE);
}

配置DCMI的模式

void OV2640_Init(void)
{DCMI_InitTypeDef DCMI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;/*** 配置DCMI接口 ***//* 使能DCMI时钟 */RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);/* DCMI 配置*/DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_Low;DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;DCMI_Init(&DCMI_InitStructure);//配置DMA传输,直接配置循环传输即可OV2640_DMA_Config(FSMC_LCD_ADDRESS,1);/* 配置中断 */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);/* 配置帧中断,接收到帧同步信号就进入中断 */NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn ;  //帧中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);DCMI_ITConfig (DCMI_IT_FRAME,ENABLE);
}

配置DMA数据传输

void OV2640_DMA_Config(uint32_t DMA_Memory0BaseAddr,uint16_t DMA_BufferSize)
{DMA_InitTypeDef  DMA_InitStructure;/* 配置DMA从DCMI中获取数据*//* 使能DMA*/RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);DMA_Cmd(DMA2_Stream1,DISABLE);while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE) {}DMA_InitStructure.DMA_Channel = DMA_Channel_1;DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS; //DCMI数据寄存器地址//DMA传输的目的地址(传入的参数)DMA_InitStructure.DMA_Memory0BaseAddr = DMA_Memory0BaseAddr;DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;DMA_InitStructure.DMA_BufferSize =DMA_BufferSize;     //传输的数据大小(传入的参数)DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//液晶数据地址,不自增DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;         //循环模式DMA_InitStructure.DMA_Priority = DMA_Priority_High;DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC8;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;/*DMA初始化 */DMA_Init(DMA2_Stream1, &DMA_InitStructure);DMA_Cmd(DMA2_Stream1,ENABLE);while (DMA_GetCmdStatus(DMA2_Stream1) != ENABLE) {}

配置帧中断

extern uint8_t fps;//使用帧中断重置line_num,可防止有时掉数据的时候DMA传送行数出现偏移
void DCMI_IRQHandler(void)
{if (  DCMI_GetITStatus (DCMI_IT_FRAME) == SET ) {/*传输完一帧,计数复位*/fps++; //帧率计数DCMI_ClearITPendingBit(DCMI_IT_FRAME);}
}

读取摄像头ID

//存储摄像头ID的结构体
typedef struct
{uint8_t Manufacturer_ID1;uint8_t Manufacturer_ID2;uint8_t PIDH;uint8_t PIDL;
} OV2640_IDTypeDef;
/*寄存器地址*/
#define OV2640_DSP_RA_DLMT       0xFF
#define OV2640_SENSOR_MIDH       0x1C
#define OV2640_SENSOR_MIDL       0x1D
#define OV2640_SENSOR_PIDH       0x0A
#define OV2640_SENSOR_PIDL       0x0B
/**
* @brief  读取摄像头的ID.
* @param  OV2640ID: 存储ID的结构体
* @retval None
*/
void OV2640_ReadID(OV2640_IDTypeDef *OV2640ID)
{/*OV2640有两组寄存器,设置0xFF寄存器的值为0或为1时可选择使用不同组的寄存器*/OV2640_WriteReg(OV2640_DSP_RA_DLMT, 0x01);/*读取寄存芯片ID*/OV2640ID->Manufacturer_ID1 = OV2640_ReadReg(OV2640_SENSOR_MIDH);OV2640ID->Manufacturer_ID2 = OV2640_ReadReg(OV2640_SENSOR_MIDL);OV2640ID->PIDH = OV2640_ReadReg(OV2640_SENSOR_PIDH);OV2640ID->PIDL = OV2640_ReadReg(OV2640_SENSOR_PIDL);
}

向OV2640写入寄存器配置

uint16_t img_width=852, img_height=480;
/* 使用用 UXGA 模式,再根据所需的图像窗口裁剪 */
const unsigned char OV2640_UXGA[][2]=
{0xff, 0x00,0x2c, 0xff,0x2e, 0xdf,0xff, 0x01,0x3c, 0x32,0x11, 0x00,0x09, 0x02,0x04, 0xD8,    //水平翻转0x13, 0xe5,/*....以下省略*/
}/**
* @brief  配置OV2640为UXGA模式,并设置输出图像大小
* @param  None
* @retval None
*/
void OV2640_UXGAConfig(void)
{uint32_t i;/* 写入寄存器配置 */for (i=0; i<(sizeof(OV2640_UXGA)/2); i++){OV2640_WriteReg(OV2640_UXGA[i][0], OV2640_UXGA[i][1]);}/*设置输出的图像大小*/OV2640_OutSize_Set(img_width,img_height);
}

http://www.ppmy.cn/news/297883.html

相关文章

GEngine一个基于WebGPU的渲染引擎

一、废话篇&#xff1a; 2019年时候就有写一个渲染引擎想法&#xff0c;一直到现在才真正意义上算给实现了当初的想法&#xff0c;写了好几个月了和小伙伴这才有个初版&#xff08;虽然里面还有一堆bug哈&#xff0c;没时间改啊&#xff09;。说在前面GEngine借鉴了其他渲染引擎…

引领618首波爆发!实在RPA数字员工与海尔等品牌共赢全域增量

作为全面放开之后的首个现象级电商大促&#xff0c;今年618的重要性不言而喻。如何在“毛遂自荐”的大促秀场中&#xff0c;满足甚至超过消费者购物需求&#xff0c;成为每个品牌商家的必修课。 疫情的催化和直播间强互动属性&#xff0c;越来越多消费者倾向直播购物&#xff0…

grep命令的使用

grep命令是Linux中常用的文本搜索工具&#xff0c;它可以根据用户指定的模式&#xff0c;在文件或标准输入中查找匹配的文本行并返回。 下面是grep命令的一些常见选项&#xff1a; -i&#xff1a;忽略大小写-n&#xff1a;显示匹配行的行号-v&#xff1a;显示不匹配的行-r&am…

希望之星、黄昏之星、三只乌鸦……怎么用 DolphinDB 快速计算 K 线?

K 线技术分析是股票投资中很常用的一种分析方法&#xff0c;主要通过历史价格图表中的数据来预测未来市场趋势。一根 K 线包括四个价格&#xff1a;开盘价、收盘价、最高价和最低价&#xff0c;通常简称为 OHLC。K 线按照周期一般可以分为日、周、月、年&#xff0c;以及五分钟…

Coggle 30 Days of ML 打卡任务一

Coggle 30 Days of ML 打卡任务一 任务一&#xff1a;两个赛题数据可视化 难度/分值&#xff1a;低/1 打卡内容&#xff1a; 参赛选手名称&#xff1a;AppleDoctor完成日期&#xff1a;2023.6.6任务完成情况&#xff1a; 使用的编程语言&#xff1a;Python实现的功能&#…

android 4.4版miui v5,基于Android 4.4的MIUI V5公测开始,适配17款非小米机型

拼 命 加 载 中 ... 小米MIUI V5此前已经升级为对低端手机有更好的优化的Android 4.4 KitKat&#xff0c;此前仅支持小米自家机型&#xff0c;上月月底才公布了源代码&#xff0c;经过合作开发组的努力&#xff0c;日前终于是开始公测了&#xff0c;支持的非小米机型共有17款。…

n918st能刷Android5吗?,获取中兴N918st (V5S 双4G)ROOT权限教程,新手必看

中兴N918st (V5S 双4G)如何获取ROOT权限?用什么ROOT工具最简单?请跟着小编一起来看看如何用奇兔刷机对中兴N918st (V5S 双4G)进行一键ROOT&#xff0c;小编特别亲手制作了详细的中兴N918st (V5S 双4G) ROOT教程图解&#xff0c;非常适合初次接触ROOT的朋友&#xff0c;具体步…

android+6.0中兴v5s,中兴V5S的手机系统是什么?中兴V5S能升级安卓4.3吗?

中兴V5S的手机系统是什么 中兴V5S的手机系统是Android 4.4.4。 中兴V5S配备500w像素前置摄像头&#xff0c;主摄像头为1300w像素&#xff0c;采用Exmor RS CMOS传感器&#xff0c;f/2.2光圈&#xff0c;配备LED补光灯&#xff0c;支持电子防抖。那么中兴V5S的手机系统是什么? …