硬件说明

STM32F4开发板

stm32f4系列的芯片处理的能力可以说非常强大了的,而且内部还自带有数字摄像头接口(DCMI),可以说stm32f407的核心板和不带FIFO的摄像头模块OV7670简直就是绝配!

我手上的这块张这个样子 (图片来源:某宝)

F4系列的DCMI接口内部结构框图如下图3所示,具体的配置使用方式可以参考以下这篇博文:《stm32f4的数字摄像头接口(DCMI)使用》

这位博主大大已经很详细地介绍了DCMI接口的具体使用方法和原理,更重要的是里面还有接口的配置函数,虽然不完全一样,但是非常具有参考意义!

TFT-LCD屏幕

LCD屏幕用的是原子哥的TFT-LCD 屏幕,去年学STM32F103的时候随便买的一块液晶屏幕,分辨率就是320*240,驱动IC是ILI9341(ID9341)。

长这个样子(图片来源:原子哥):

对应资料链接:https://leoeinstein.lanzous.com/iApMql9yzkj

资料有点大哈,因为这个资料有可能是最全的LCD驱动IC资料包了。(这句话很小米)

摄像头OV7670

OV7670摄像头模块的体积小、工作电压低,提供单片VGA摄像头和影像处理器的所有功能,因为我这个不带FIFO芯片,所有还特便宜,但是像素不算太高。(这个价钱也还是可以了)

通过SCCB总线控制,可以输出整帧、子采样、取窗口等方式的各种分辨率8位影响数据。该产品VGA图像最高达到30帧/秒。用户可以完全控制图像质量、数据格式和传输方式。

摄像头模块长这个样子(图片来源:某宝):

OV7670中文资料手册:
https://wenku.baidu.com/view/e60f19ea81c758f5f61f67df.html

硬件连接说明

开发板上有一个TFT-LCD的接口,你如果手上有这样的屏幕就可以直接插上去使用了,如果用的的原子哥的屏幕的话,就需要稍微外接一些线了。

我直接用杜邦线连的,有“亿点点”乱哈。

LCD与STM32

LCD MCU LCD MCU
CS PG12 RS PF12
WR/CLK PD5 RD PD4
RST RST D0 D0
D1 D1 D2 D3
D3 D3 D4 D4
D5 D5 D6 D6
D7 D7 D8 D8
D9 D9 D10 D10
D11 D11 D12 D12
D13 D13 D14 D14
D15 D15 GND GND
BL PB15 VCC3.3 3.3V
VCC3.3 3.3V GND GND
GND GND BL_VDD 5V
MISO MI MOSI MO
T_PEN PB1 MO -------
T_CS PC13 CLK PB0

OV7670与STM32

可以参考这篇博文:https://blog.csdn.net/LiangWF22/article/details/112676289

编程实现

编程要点、思路

一、摄像头配置
无FIFO的摄像头需要注意 时钟配置和窗口配置,否则不能出图像;

二、DCMI配置
DCMI需要配置成 DMA传输模式和使用行场中断进行图像数据采集,同时需要注意DCMI硬件同步的行场信号以及像素信号的上升沿和有效电平。

可以参考上面那篇《stm32f4的数字摄像头接口(DCMI)使用》博文。

具体代码

dcmi.c

#include "sys.h"
#include "dcmi.h" u8 ov_frame=0;                         //帧率
u32 datanum=0;
u32 HSYNC=0;
u32 VSYNC=0;
DCMI_InitTypeDef DCMI_InitStructure;//DCMI 初始化
void DCMI_DMA_Init(void)
{ DMA_InitTypeDef  DMA_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能 DMA_DeInit(DMA2_Stream1);while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE){}//等待DMA2_Stream1可配置 DMA_InitStructure.DMA_Channel = DMA_Channel_1;  //通道1 DCMI通道 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&DCMI->DR;//外设地址为:DCMI->DR  摄像头DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&LCD->LCD_RAM;//DMA 存储器0地址 lcdDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//外设到存储器模式 搬运数据:摄像头->lcdDMA_InitStructure.DMA_BufferSize = 10;//数据传输量 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//存储器增量模式 关闭DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//外设数据长度:32位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord ;//存储器数据长度 16bit DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 使用循环模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; //FIFO模式        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;//使用全FIFO DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//外设突发单次传输DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//存储器突发单次传输DMA_Init(DMA2_Stream1, &DMA_InitStructure);//初始化DMA StreamDMA_ITConfig(DMA2_Stream1,DMA_IT_TC,ENABLE);NVIC_InitStructure.NVIC_IRQChannel=  DMA2_Stream1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器、} void DMA2_Stream1_IRQHandler(void)
{        if(DMA_GetFlagStatus(DMA2_Stream1,DMA_FLAG_TCIF1)==SET)//DMA2_Steam1,传输完成标志{  DMA_ClearFlag(DMA2_Stream1,DMA_FLAG_TCIF1);//清除传输完成中断datanum++;}
}
//DCMI初始化
void DCMI_Initxx(void)
{GPIO_InitTypeDef  GPIO_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOA B C E 时钟RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI,ENABLE);//使能DCMI时钟//PA4/6初始化设置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_6;//PA4/6   复用功能输出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能输出GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_6;// PB6/7   复用功能输出GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;//PC6/7/8/9 复用功能输出GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6;//PE 4/5/6  复用功能输出 GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化  GPIO_PinAFConfig(GPIOA,GPIO_PinSource4,GPIO_AF_DCMI); //PA4,AF13  DCMI_HSYNCGPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_DCMI); //PA6,AF13  DCMI_PCLK  GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_DCMI); //PB7,AF13  DCMI_VSYNC GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_DCMI); //PC6,AF13  DCMI_D0  GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_DCMI); //PC7,AF13  DCMI_D1 GPIO_PinAFConfig(GPIOC,GPIO_PinSource8,GPIO_AF_DCMI); //PC8,AF13  DCMI_D2GPIO_PinAFConfig(GPIOC,GPIO_PinSource9,GPIO_AF_DCMI); //PC9,AF13  DCMI_D3GPIO_PinAFConfig(GPIOE,GPIO_PinSource4,GPIO_AF_DCMI);//PE4,AF13 DCMI_D4 GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_DCMI); //PB6,AF13  DCMI_D5 GPIO_PinAFConfig(GPIOE,GPIO_PinSource5,GPIO_AF_DCMI); //PE5,AF13  DCMI_D6GPIO_PinAFConfig(GPIOE,GPIO_PinSource6,GPIO_AF_DCMI); //PE6,AF13  DCMI_D7DCMI_DeInit();//清除原来的设置 DCMI_InitStructure.DCMI_CaptureMode=DCMI_CaptureMode_Continuous;//连续模式DCMI_InitStructure.DCMI_CaptureRate=DCMI_CaptureRate_All_Frame;//全帧捕获DCMI_InitStructure.DCMI_ExtendedDataMode= DCMI_ExtendedDataMode_8b;//8位数据格式  DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;//HSYNC 低电平有效DCMI_InitStructure.DCMI_PCKPolarity= DCMI_PCKPolarity_Falling;//PCLK 上升沿有效DCMI_InitStructure.DCMI_SynchroMode= DCMI_SynchroMode_Hardware;//硬件同步HSYNC,VSYNCDCMI_InitStructure.DCMI_VSPolarity=DCMI_VSPolarity_High;//VSYNC 低电平有效DCMI_Init(&DCMI_InitStructure);DCMI_ITConfig(DCMI_IT_FRAME,ENABLE);//开启帧中断 DCMI_ITConfig(DCMI_IT_LINE,ENABLE); //开启行中断DCMI_ITConfig(DCMI_IT_VSYNC,ENABLE); //开启场中断 DCMI_Cmd(ENABLE);   //DCMI使能NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级1NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;      //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //IRQ通道使能NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器、
}
//DCMI,启动传输
void DCMI_Start(void)
{ LCD_Scan_Dir(U2D_L2R);    //U2D_L2R      //扫描方式从上到下,从左到右,一般模式 LCD_Set_Window(0,0,320,240); //LCD设置显示窗口,如果改变了分辨率,这里需要更改LCD_SetCursor(0,0); //设置光标 LCD_WriteRAM_Prepare();    //开始写入GRAMDMA_Cmd(DMA2_Stream1, ENABLE);//开启DMA2,Stream1 DCMI_CaptureCmd(ENABLE);//DCMI捕获使能
}
//DCMI,关闭传输
void DCMI_Stop(void)
{ DCMI_CaptureCmd(DISABLE);//DCMI捕获使关闭  while(DCMI->CR&0X01);        //等待传输结束    DMA_Cmd(DMA2_Stream1,DISABLE);//关闭DMA2,Stream1
}
//DCMI中断服务函数
void DCMI_IRQHandler(void)
{if(DCMI_GetITStatus(DCMI_IT_LINE)==SET)//捕获到行{DCMI_ClearITPendingBit(DCMI_IT_LINE);//清除中断    ov_frame++;}} 

//以下两个函数,供usmart调用,用于调试代码//DCMI设置显示窗口
//sx,sy;LCD的起始坐标
//width,height:LCD显示范围.
void DCMI_Set_Window(u16 sx,u16 sy,u16 width,u16 height)
{DCMI_Stop(); LCD_Clear(WHITE);LCD_Set_Window(sx,sy,width,height);//    OV7670_OutSize_Set(width,height);LCD_SetCursor(0,0);  LCD_WriteRAM_Prepare();       //开始写入GRAMDMA_Cmd(DMA2_Stream1,ENABLE); //开启DMA2,Stream1 DCMI_CaptureCmd(ENABLE);//DCMI捕获使能 }

摄像头初始化函数如下:

u8 OV7670_Init(void)
{u16 i=0;//设置IO           GPIO_InitTypeDef  GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//GPIOG9,15初始化设置pow和resetGPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_8;//PG9,8推挽输出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //推挽输出GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化OV7670_PWDN=0;   //POWER ONdelay_ms(100);OV7670_RST=0;  //复位OV7670delay_ms(100);OV7670_RST=1;  //结束复位 SCCB_Init();             //初始化SCCB 的IO口SCCB_WR_Reg(0X12, 0x80);  //软复位OV7670delay_ms(50); //初始化 OV7670,采用QVGA分辨率(320*240)  for(i=0;i<sizeof(ov7670_init_reg_tbl)/sizeof(ov7670_init_reg_tbl[0]);i++){SCCB_WR_Reg(ov7670_init_reg_tbl[i][0],ov7670_init_reg_tbl[i][1]);} //OV7670_Window_Set(PIC_START_X,PIC_START_Y,PIC_WIDTH,PIC_HEIGHT);OV7670_Light_Mode(0);OV7670_Color_Saturation(2);OV7670_Brightness(1);OV7670_Contrast(2);//My_DCMI_Init();//DCMI_DMA_Init((uint32_t)&camera_buffer+54,(sizeof(camera_buffer)-54)/4,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Enable);//DCMI DMA return 0x00;     //ok
}

实现效果

这仅仅是显示RGB数据,如果要上云的话,需要将RGB数据转化为BMP数据,然后再上传到物联网平台上,在后面的博文里将会介绍到。

工程链接

链接1:https://download.csdn.net/download/LiangWF22/15020550

链接2:https://leoeinstein.lanzoum.com/icY0x0b627tg
2021年2月3日 星期三

基于STM32F407的摄像头(不带FIFO的OV7670)图像采集及LCD显示实验-笔记整理相关推荐

  1. 用20块的摄像头(不带fifo的OV7670)做WiFi实时传图小车

    博客地址 用20块的摄像头(不带fifo的OV7670)做WiFi实时传图小车 – Infinite's Blog 零.导读 在这篇文章中,你将看到如下内容: OV7670 QVGA配置的注意事项: ...

  2. 【正点原子FPGA连载】 第三十章双目OV5640摄像头LCD显示实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

    1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670 3)全套实验源码+手册+视频下载地址: h ...

  3. 基于51单片机的双机串口通信排队叫号系统(LCD显示)设计

    基于51单片机的双机串口通信排队叫号系统(LCD显示)设计 1 开发环境 视频讲解 2 功能说明介绍 3 仿真图 4 程序 5 原理图 6 视频讲解 7 设计报告 7.1 设计目的 7.2 设计要求及 ...

  4. 基于战舰V3的LCD显示实验详解和剖析

    基于STM32的4.3寸TFTLCD的使用 在这里,我们只剖析NT35510部分的代码. LCD显示方向设置函数 代码示例 //设置LCD显示方向 //dir:0,竖屏:1,横屏 void LCD_D ...

  5. STM32F103C8T6+带FIFO的OV7670的输出测试图像实例代码

    一.工程文件链接及说明 Keil5工程文件: 链接:https://pan.baidu.com/s/13wCMPQU0DgbJ57sSiR16NQ?pwd=7670 提取码:7670 工程文件中,主要 ...

  6. OV7670带FIFO入坑指南

    本文针对带FIFO的OV7670摄像头模块进行说明. 对于新手入坑OV7670摄像头的小白来说,入坑之路漫漫,最坑爹的是不知道入口在哪里~~下面就来简单的说一下我这几天的实验心得. 什么是带FIFO的 ...

  7. 【正点原子FPGA连载】第四十一章OV5640摄像头RGB-LCD显示实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1

    1)实验平台:正点原子新起点V2开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609758951113 2)全套实验源码+手册+视频下载地址:ht ...

  8. 【正点原子FPGA连载】 第三十四章双目OV5640摄像头RGB-LCD显示实验 摘自【正点原子】DFZU2EG/4EV MPSoC 之FPGA开发指南V1.0

    1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670 3)全套实验源码+手册+视频下载地址: h ...

  9. 【正点原子FPGA连载】第四十四章MT9V034摄像头HDMI显示实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1

    1)实验平台:正点原子新起点V2开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609758951113 2)全套实验源码+手册+视频下载地址:ht ...

最新文章

  1. linux下mysql的root密码忘记解决方法
  2. ♥看二本学渣如何进腾讯 分享面试经验、职场感悟、硬核知识、大厂内推♥
  3. JIPB:白洋组综述根系微生物组群落构建及其对植物适应性的贡献
  4. 非系统表空间损坏,rman备份恢复
  5. LiveVideoStackCon深圳 - 洞察多媒体技术生态趋势与机会
  6. ecm工作原理 usb_“好玩具”来了!往你的USB端口里藏入一个小开发板...
  7. 内核移植出现:Kernel panic - not syncing: No init found.
  8. 【Siddhi 5】Siddhi 自定义函数@Extension使用
  9. 查询所有_学会DSUM函数,轻松搞定所有的数据查询与数据求和
  10. Opera的一个神奇功能
  11. Python深度学习基于PyTorch (附完整PPT下载)
  12. C语言笔记 清屏(循环时不一闪一闪的) 光标移动到任意位置 带注释(详细)
  13. [论文笔记]JED:Towards Real-Time Multi-Object Tracking
  14. sin2x麦克劳林公式_sinx泰勒公式展开
  15. Navicat导入Excel提示无法打开Excel文件
  16. 最全的IMSI获取手机号段、归属地java代码
  17. SWING实现类似微信的泡泡聊天界面
  18. matlab增强图像饱和度,matlab增强图像饱和度
  19. GS1011无线模块的使用简介。
  20. 伟大的牛逼之前都是傻逼式的坚持

热门文章

  1. libreoffice安装教程_win10怎么安装libreoffice6.4_win10系统libreoffice6.4安装教程
  2. 关于EFI系统分区(ESP)你应该知道的3件事
  3. MAL-Gold Nanoparticle/Au nanoparticles纳米金颗粒/金纳米粒子|50nm浓度:0.5mg/ml
  4. 基于虚拟相机的人脸识别 (视频) - Face recognition based on virtual camera
  5. seo关键词排名点击优化软件
  6. AK F.*ing leetcode 流浪计划之线段树
  7. 简单抽样技术——简单随机样本方差是总体方差的无偏估计
  8. html下拉自动加载更多,H5页面下拉加载更多(实用版)
  9. 计算机硬件维护的注意事项有哪些,计算机的硬件维护注意事项
  10. 关于EDP触摸屏使用笔记