STM32驱动OV7670摄像头:从SCCB配置到图像采集实战解析
2026/9/2 7:06:22 网站建设 项目流程

简介:面向使用STM32驱动OV7670摄像头做图像采集的嵌入式开发者,该驱动源程序覆盖了从寄存器初始化、GPIO/时钟控制、SCCB/I2C通信,到图像读取、简单图像处理及LCD或SD卡显示的完整链路,适合毕设、电子竞赛与物联网项目快速起步。压缩包共126个文件,大小仅2.18MB,以44个C文件和52个头文件为主体,另含启动汇编、Keil工程配置、PDF说明及示例图片,目录划分清晰,便于按模块阅读。已有2252人学习下载,表明其在STM32摄像头开发领域具有一定参考价值。代码不仅实现了OV7670初始化与FIFO时序读取,还包含SD卡文件系统、BMP编码等辅助模块,可为二次开发提供可靠基线,便于扩展颜色识别、帧差检测等视觉应用。 做了几年嵌入式,手里过了不少摄像头方案,OV7670算是很多新手入坑视觉的第一颗Sensor。这颗30万像素的CMOS传感器,虽然老,但把图像采集、时序同步、DMA传输这些基本功练扎实了,后面再上OV2640、GC0308甚至RGB摄像头,思路基本都是通的。这次我把基于STM32的OV7670驱动源程序完整拆一遍,从硬件接法到代码框架,再到实际调试中遇到的各种坑,一次性写清楚。

1. 项目整体设计与思路拆解

1.1 OV7670的核心参数与选型理由

OV7670是OmniVision出品的一颗1/6英寸CMOS图像传感器,有效像素30万,最大输出分辨率640x480(VGA),支持RGB565、RGB555、RGB444、YUV422、YCbCr422和RAW Bayer等多种输出格式。它最常用的接口是DVP(Digital Video Port)并行接口,8根数据线D0-D7,加上PCLK(像素时钟)、VSYNC(帧同步)、HREF(行同步)三根同步线,就能把图像数据源源不断地送出来。

这颗芯片在2024年的今天依然有大量教学案例和项目在用,核心原因是它的控制接口SCCB(类似I2C)和并行数据时序非常典型,是学习嵌入式图像采集的标准教材。相比现在流行的DVP接口摄像头(比如OV2640),OV7670帧率低、分辨率小,但正因为简单,反而适合用来理解图像数据是怎么从Sensor流到MCU再流到屏幕上的完整链路。对于做STM32入门视觉、智能车、简易图像识别的开发者来说,它是性价比最高的练手方案。

1.2 两种主流硬件接法:FIFO方案与直连DCMI方案

STM32驱动OV7670,硬件接法上主流有两条路:一是通过AL422B FIFO芯片中转,二是用STM32F4/F7/H7系列自带的DCMI接口直连。

FIFO方案是老派做法,也是目前网上绝大多数源程序的硬件基础。OV7670的PCLK在VGA分辨率下可达到24MHz,而STM32F103这类Cortex-M3内核芯片的GPIO翻转速度有限,直接接GPIO大概率丢数据。AL422B是一颗256KB的FIFO缓存,可以先把一帧图像完整存进去,OV7670以它自己的节奏往FIFO里写,STM32再从FIFO慢慢读出来,两边互不干扰。这个方案牺牲了一点实时性,但稳定性极高,代码简单,几乎不用考虑时序同步问题。我早期做STM32F103+OV7670就是用的这个方案,跑320x240分辨率,稳定不掉帧。

DCMI(Digital Camera Interface)方案则是STM32家族里带DCMI外设的芯片专属玩法(F103没有DCMI,F407及以上的型号才带)。DCMI本身就是为摄像头设计的同步并行接口,硬件上自动处理VSYNC/HREF/PCLK同步,还能配合DMA直接将图像帧写入内存,CPU几乎零负担。用DCMI可以直接把OV7670的8根数据线接在DCMI_D0-D7上,加上VSYNC、HREF、PCLK三根线,不需要FIFO,PCB面积更小,代码也更简洁。

下表是两种方案的对比,方便大家根据手上的板子选型:

对比项FIFO方案(AL422B)DCMI直连方案
适用芯片STM32F1全系列STM32F4/F7/H7等带DCMI的型号
硬件复杂度需要外挂FIFO芯片直接连接,无需额外芯片
帧率受FIFO读出速度限制可跑满Sensor输出
时序处理由FIFO隔离,MCU端简单DCMI硬件自动同步
代码量稍多(FIFO读写控制)较少(寄存器配置为主)
适合场景入门学习、F103老平台图像处理、高性能采集

2. 驱动源程序的核心机制与初始化流程

2.1 SCCB通信协议与GPIO模拟实现

OV7670的所有图像参数(分辨率、输出格式、增益、曝光等)都是通过SCCB接口写寄存器配置的。SCCB协议与I2C非常相似,但不完全兼容——它没有I2C那种应答机制中的NAK概念,读操作也略有差别。实际用GPIO模拟SCCB时,绝大多数人都直接按I2C时序来写,实测也能正常工作,因为OV7670对时序的容忍度比较高。

SCCB初始化代码的核心是两根线:SIO_C(时钟)和SIO_D(数据)。在GPIO配置上,时钟线设为推挽输出,数据线设为开漏输出并外接上拉电阻,这样既能输出又能读取。写寄存器流程是:起始信号 -> 发送设备地址0x42(写) -> 发送寄存器地址 -> 发送数据 -> 停止信号。读寄存器流程稍微复杂:起始 -> 发送0x42 -> 发送寄存器地址 -> 重新起始 -> 发送0x43(读) -> 读取数据 -> 停止。

#define SCCB_SCL_PIN GPIO_Pin_6 #define SCCB_SDA_PIN GPIO_Pin_7 #define SCCB_PORT GPIOB void SCCB_Start(void) { SDA_HIGH(); SCL_HIGH(); Delay_Us(5); SDA_LOW(); Delay_Us(5); SCL_LOW(); } void SCCB_Stop(void) { SDA_LOW(); SCL_HIGH(); Delay_Us(5); SDA_HIGH(); Delay_Us(5); } uint8_t SCCB_WriteByte(uint8_t data) { uint8_t i; for (i = 0; i < 8; i++) { if (data & 0x80) SDA_HIGH(); else SDA_LOW(); data <<= 1; SCL_HIGH(); Delay_Us(2); SCL_LOW(); Delay_Us(2); } SDA_HIGH(); // 释放数据线,等待应答 SCL_HIGH(); Delay_Us(2); if (SDA_READ() == 0) // 判断应答位 { SCL_LOW(); return 1; // 写成功 } SCL_LOW(); return 0; }

这里要特别提醒:SCCB的时钟频率不要超过100kHz,实际上40-50kHz最稳。我遇到过用400kHz去写导致OV7670间歇性工作异常的情况,图像时好时坏,排查了很久才发现是SCCB速度过快,将延时加大后一切正常。

2.2 寄存器初始化序列的配置思路

OV7670内部有上百个寄存器,但实际项目中不需要全部配置。网上流传的初始化序列大同小异,核心目的是把Sensor配置成“能出图”的状态。配置思路围绕四件事展开:设置输出分辨率、设置像素格式、调整时钟分频、优化图像质量。

首先是分辨率设置。OV7670默认上电输出VGA(640x480)RAW Bayer格式。要在源程序里输出RGB565格式并缩小到320x240(QQVGA),需要修改寄存器0x12(COM7)的值。这个寄存器是全局控制寄存器,bit2设置为0表示输出RGB格式,bit3设置为0表示VGA分辨率,bit4设置为1表示RGB565颜色格式。

// OV7670初始化序列(部分关键寄存器) void OV7670_Init(void) { // 软件复位 SCCB_WriteReg(0x12, 0x80); Delay_Ms(10); // 设置输出格式为RGB565,VGA SCCB_WriteReg(0x12, 0x00); // COM7: 0x00 = RGB565, VGA // 设置RGB565颜色空间,全范围输出 SCCB_WriteReg(0x40, 0x10); // COM15: RGB565全范围 // 关闭测试图案 SCCB_WriteReg(0x70, 0x3A); // COM9: 最大增益上限 SCCB_WriteReg(0x71, 0x35); // COM8: 使能AGC、AWB、AEC // 设置PCLK分频 SCCB_WriteReg(0x11, 0x03); // CLKRC: PCLK = XCLK / (2 + 3) = 6MHz // 设置HREF开始和结束位置(320x240窗口) SCCB_WriteReg(0x32, 0xB6); // HREF_START SCCB_WriteReg(0x17, 0x16); // HSTART SCCB_WriteReg(0x18, 0x04); // HSTOP // ... 其他图像质量寄存器 }

关于分频系数,这里有个关键的数学关系。如果外部晶振XCLK给了24MHz,寄存器0x11设置为0x03,那么PCLK = XCLK / (分频值+1) / 2,即24MHz / 4 / 2 = 3MHz。这个频率对STM32F103的GPIO读取来说比较友好。而如果直接跑VGA全分辨率,PCLK可以达到12MHz以上,FIFO方案没问题,但F103直连就非常吃力了。

2.3 MCLK主时钟的选择与PCLK分频计算

OV7670需要外部提供主时钟(XCLK/MCLK),典型范围是6-24MHz,最高不超过48MHz。这个时钟来源在STM32项目中一般用定时器输出PWM波提供。我习惯用TIM2的CH1(PA0)输出PWM,频率配到24MHz,占空比50%。

为什么选24MHz而不是更高?因为虽然OV7670标称最高支持48MHz时钟,但实际用48MHz时发热明显,且PCLK会变得过高,FIFO方案还能勉强应对,DCMI方案在部分STM32上会采样出错。压低到24MHz后,Sensor内部逻辑更稳定,图像噪点更少,PCLK也更可控。

void MCLK_Init(void) { TIM_TimeBaseInitTypeDef TIM_BaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; GPIO_InitTypeDef GPIO_InitStructure; // 使能GPIOC时钟(PA0引脚是TIM2_CH1) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_BaseInitStructure.TIM_Period = 1; // 自动重装载值 TIM_BaseInitStructure.TIM_Prescaler = 0; // 预分频 TIM_BaseInitStructure.TIM_ClockDivision = 0; TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_BaseInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 1; // 占空比50% TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM2, &TIM_OCInitStructure); TIM_Cmd(TIM2, ENABLE); }

如果系统主频是72MHz,TIM2挂载在APB1总线上(36MHz),预分频设为0,自动重装载值设为1,输出频率就是18MHz而不是24MHz。想要精确得到24MHz,需要把系统时钟进行特定配置,或者简单一点的做法是用PLL输出到MCO引脚——STM32F103的PA8可以通过MCO功能输出系统PLL时钟(最高72MHz),再配合TIM2分频得到想要的频率。不过我实测TIM2输出18MHz给OV7670也能正常工作,Sensor对MCLK精度要求没那么苛刻,18/24MHz都在允许范围内。

3. 驱动源程序的关键代码模块

3.1 FIFO方案:图像数据读取与DMA传输

FIFO方案里,AL422B承担数据缓冲角色。AL422B内部有393216字节的存储空间(384KB),其读写时序是:写侧由OV7670的PCLK驱动写时钟WCK,VSYNC帧同步信号控制写使能;读侧由STM32控制RCK(读时钟)和RE(读使能)。

核心逻辑其实就三步:OV7670一帧数据开始(VSYNC低电平)时,拉高FIFO写使能(WE),让数据写入FIFO;一帧结束(VSYNC回到高电平)时,拉低WE停止写入;STM32在VSYNC高电平期间,用DMA从FIFO读取数据到内存缓冲区,用于显示或处理。

void OV7670_ReadFrame(uint16_t *buffer, uint16_t width, uint16_t height) { uint32_t i; // 等待VSYNC低电平(帧起始) while (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == Bit_SET); // 等待VSYNC高电平(帧结束),期间FIFO写入一帧数据 while (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == Bit_RESET); // 帧数据已存入FIFO,拉低读使能,开始读取 FIFO_RE_LOW(); // 使用DMA读取FIFO数据到buffer // 这里以SPI接口读取FIFO为例 SPI_DMA_Transfer((uint8_t *)buffer, width * height * 2); // 读完释放读使能 FIFO_RE_HIGH(); }

这里一个容易踩坑的地方是DMA传输长度的设置。RGB565格式下每个像素占2字节,所以一帧320x240图像需要 320x240x2 = 153600字节 = 150KB,而AL422B是384KB,容量充足。但如果跑VGA全分辨率,一帧需要640x480x2 = 614400字节 = 600KB,AL422B就装不下了,这是很多人在FIFO方案里跑不动VGA分辨率的根本原因。解决办法是降分辨率,或者改为边写边读(需要处理FIFO半满中断)。

3.2 DCMI方案:寄存器配置与DMA采集

如果用的是STM32F407或F429,DCMI外设让代码简化很多。DCMI配置的核心是选择合适的同步模式、像素时钟极性和数据宽度。

DCMI有两种同步模式:内嵌同步(Embedded)和外同步(Hardware)。OV7670输出的是VSYNC/HREF独立信号,属于典型的外同步模式。数据宽度选8位(对应D0-D7),像素时钟极性选上升沿采样(OV7670默认PCLK上升沿数据稳定)。捕获模式选逐帧捕获,DMA循环模式将数据源源不断送到内存。

void DCMI_Init(void) { DCMI_InitTypeDef DCMI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; DMA_InitTypeDef DMA_InitStructure; // 配置DCMI相关引脚(D0-D7、VSYNC、HREF、PCLK) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_DCMI); // ... 其他引脚复用配置 // DCMI配置:外同步、8位宽度、上升沿采样、逐帧捕获 DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Snapshop; 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配置:内存地址递增、外设到内存、循环模式 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&DCMI->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)imageBuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 320 * 240 * 2; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_Init(DMA2_Stream1, &DMA_InitStructure); DMA_Cmd(DMA2_Stream1, ENABLE); DCMI_Cmd(ENABLE); DCMI_CaptureCmd(ENABLE); }

DCMI方案最爽的地方在于DMA的循环模式。配置好之后,摄像头图像帧会自动持续写入内存缓冲区,CPU完全不参与。后续做图像处理直接在缓冲区上跑就行,帧率比FIFO方案高出不少。实测F407+DCMI驱动OV7670跑320x240 RGB565,帧率可以到30fps,而F103+FIFO方案通常只能到10-15fps。

3.3 图像显示链路:从缓冲区到LCD屏幕

采集到图像后,显示是最直观的验证手段。无论是FIFO方案还是DCMI方案,最终都得到一块RGB565格式的帧缓冲区。以ILI9341 LCD为例,320x240分辨率正好与QQVGA匹配,可以一像素一像素地刷过去,不需要缩放。

void Display_Image(uint16_t *image, uint16_t width, uint16_t height) { uint32_t i; LCD_SetCursor(0, 0); LCD_WriteRAM_Prepare(); // 直接连续写入整个图像缓冲区 for (i = 0; i < width * height; i++) { LCD_WriteRAM(image[i]); } }

这里有个提升显示帧率的小技巧:ILI9341支持2线的SPI或16位并口写数据,并口明显快很多。如果只追求“能显示图像”,SPI刷320x240黑白图像都吃力,RGB565全彩基本卡成PPT。建议使用FSMC(Flexible Static Memory Controller)方式驱动LCD,可以把LCD当成外部SRAM直接写地址,速度提升一个量级。F103系列就有FSMC外设,接上LCD后写一帧320x240的RGB565图像大概只需30ms,能跑到30fps,体验完全不同。

4. 常见问题与排查技巧实录

4.1 白屏、黑屏问题:先查SCCB后查时钟

图像完全不出,屏幕白屏或者黑屏,第一件事是确认SCCB通信是否正常,而不是去怀疑数据线接没接对。我踩过最多次的坑就是寄存器没写进去,Sensor还在默认的YUV模式运行,导致后面所有配置都不生效。

排查方法很简单:回读OV7670的厂商ID寄存器。OV7670的PID(0x0A)和VER(0x0B)寄存器分别存储产品ID号和版本号,正常情况下PID读到0x76,VER读到0x73。如果读出来是0xFF或者0x00,说明SCCB根本没打通。

uint8_t OV7670_CheckID(void) { uint8_t pid, ver; pid = SCCB_ReadReg(0x0A); ver = SCCB_ReadReg(0x0B); if (pid == 0x76 && ver == 0x73) return 1; else return 0; }

如果ID读不到,按顺序排查三处:一是SIO_C和SIO_D的GPIO模式是否配置正确,数据线必须开漏输出加上拉;二是地址是否正确,OV7670的SCCB设备地址是0x42(写)。三是上电时序,OV7670的RESET引脚必须在上电后保持至少1ms的低电平再拉高,随后延时10ms后才能通过SCCB读写,否则Sensor内部还没启动完成。

4.2 图像花屏、彩色条纹的常见原因

SCCB配置成功后,最常见的异常是图像花屏、彩色条纹或者颜色明显偏绿偏紫。这类问题绝大多数出在时序匹配上。

花屏是指画面呈现杂乱的雪花点或者横向条纹,通常是因为读取数据时PCLK采样沿不对。OV7670默认在PCLK上升沿数据稳定,但受布线长度和延时影响,STM32端看到的数据可能还没稳定就采了。解决办法是在DCMI配置中切换PCLK极性为下降沿采样,或者在FIFO方案中调整RCK的相位。

还有一种常见情况是颜色偏绿偏紫,这基本是RGB格式配置问题。OV7670内部输出顺序是RGBG(拜耳),配置成RGB565后需要确保寄存器0x12(COM7)的RGB比特位和0x40(COM15)的RGB565配置一致。如果输出本来是RGB565但初始化代码配成了YUV,图像会显示成灰绿相间的奇怪颜色。可以在初始化后回读寄存器0x12和0x40,确认写入值与预期一致。

图像出现左右颠倒或上下颠倒,是镜像和翻转寄存器没配。OV7670的寄存器0x1E(MVFP)控制镜像和翻转,bit4控制水平镜像,bit3控制垂直翻转。根据实际安装方向设置即可。

4.3 帧率上不去的瓶颈分析

费劲调通图像后,很多人发现帧率比理论值低很多。FIFO方案跑320x240如果帧率只有5-8fps,多半是读取效率太低。

我遇到过的情况是:FIFO方案中通过GPIO模拟时序读FIFO,每读一个字节要翻转好几根引脚,速度受限。改成SPI读FIFO + DMA后,帧率直接翻倍。AL422B读侧支持最高50MHz的读时钟,SPI2(36MHz)足够喂饱大部分应用。另一个瓶颈是LCD显示,如果用FSMC刷屏,同时进行DMA采集,要合理安排优先级,避免DMA在传输图像时被LCD频繁打断。

一个实用的优化技巧是采用双缓冲机制。配置两块内存缓冲区,DMA采集时交替使用,采集完成标志置位后再启动显示,这样采集和显示可以并行进行。实测在F407上双缓冲能稳定跑到30fps,并且图像撕裂感明显减少。

4.4 调试工具与环境搭建要点

调OV7670这类图像项目,示波器和逻辑分析仪几乎是必需品。我自己常用的排查手段是:用逻辑分析仪抓VSYNC、HREF、PCLK三根线,确认Sensor输出时序是否正常。正常一帧图像应该有:一个VSYNC低电平脉冲(标记帧起始),然后640个(或320个)HREF有效行,每个HREF有效期间有对应数量的PCLK脉冲。如果PCLK数量不对,说明Sensor输出分辨率与配置不符,检查CLKRC分频配置。

软件层面,推荐在串口调试助手中打印关键状态信息,比如SCCB读写次数、DMA传输完成标志、捕获的帧计数等。这里需要提一下调试工具的驱动问题——很多人用CH340串口模块时,电脑识别不了设备,大概率是驱动没装对。Windows 10以上系统一般联网自动装CH340驱动,但部分精简版系统需要手动指定驱动目录。J-Link和ST-Link的驱动安装同理,装好之后在设备管理器里能看到对应的调试器设备,才能正常烧录仿真。

用ST-Link调试时,如果出现连接失败,优先检查接线。ST-Link的SWDIO和SWCLK对应STM32的PA13/PA14引脚,这两根线不能接反。还有一点,如果程序里配置了复用功能占用了PA13/PA14(比如把这个引脚当普通IO用了),会导致下次烧录时找不到芯片,解决办法是把BOOT0拉高进入ISP模式,先用串口烧一个空程序,再切回SWD模式。

5. 源程序工程规划与实战建议

5.1 驱动代码的文件组织

一个清晰易维护的OV7670驱动源程序,建议按模块拆分为几个独立文件:sccb.c负责底层时序读写,ov7670.c负责Sensor寄存器配置和初始化,ov7670_platform.c负责硬件平台相关引脚初始化和时钟配置。这样分层的好处是,更换MCU平台时只需要修改platform层,SCCB协议层和OV7670寄存器配置逻辑可以完全复用。

我自己一般把工程文件组织成下面这样的结构:

/User /Src main.c // 主函数,初始化并显示图像 sccb.c // SCCB通信协议实现 ov7670.c // OV7670驱动:初始化、寄存器配置、帧读取 ov7670_platform.c // 平台相关:GPIO初始化、TIM输出MCLK lcd.c // LCD显示驱动 /Inc sccb.h ov7670.h ov7670_platform.h lcd.h

这种结构在工程规模变大后优势非常明显。比如后续要接OV2640,只需要新增一个ov2640.c,SCCB和platform层直接复用,工作量集中在不同Sensor的寄存器序列上。

5.2 从驱动到应用的演进方向

纯显示的驱动跑通只是第一步。OV7670虽然分辨率不高,但做简单的颜色识别、灰度统计、运动检测是足够的。在驱动稳定后,可以在帧缓冲区的数据基础上做一些图像处理算法。

比如识别红色物体,思路就是对RGB565格式的像素逐点解析:提取R、G、B分量(RGB565中bit15-11为R,bit10-5为G,bit4-0为B),设定阈值筛选符合颜色的像素点,再对二值化结果做连通域分析,算出目标的中心坐标和面积。这些算法在STM32F4上跑320x240分辨率可以做到实时。

我之前用OV7670做过一个简易的循迹小车视觉模块,就是在驱动层基础上加了灰度二值化和重心计算,在F103上勉强能跑10fps,做慢速循迹完全够用。如果追求更高性能,可以考虑换成K210这种带KPU的AI芯片,但前端的OV7670驱动思路是完全一致的,甚至可以直接复用底层代码。

做一个项目,驱动是敲门砖,真正花时间的是后续的图像处理。先把OV7670的驱动吃透,后面换再复杂的Sensor也只是寄存器配置的差异,不会是技术路线的差异。最后给一个小建议:源码拿到手别急着改功能,先把初始化时序、帧同步信号逐行看懂,用逻辑分析仪确认Sensor有数据输出后,再做上层功能开发。这样调试效率最高,也最不容易被奇怪的问题挡住大半天。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询