stm32f4的数字摄像头接口(DCMI)使用

article/2025/9/20 15:50:16

DCMI简介

 

STM32F4DCMI接口包括如下信号

 

1,数据据输入(D[0:13]),接摄像头的数据输出。

2,水平同步(行同步)输入(HSYNC),接摄像头的HSYNC/HREF信号,用于确定一行数据的接收情况。

3,垂直同步(场同步)输入(VSYNC),接摄像头的VSYNC信号,用于确定一帧数据的接收情况。

4,像素时钟输入(PIXCLK),接摄像头的PCLK信号,同步时钟,数据接收同步信号。

 

DCMI接口的数据与PIXCLK(即PCLK)保持同步,并根据像素时钟的极性在像素时钟上升沿/下降沿发生变化。HSYNCHREF)信号指示行的开始/结束,VSYNC信号指示帧的开始/结束。

DCMI的使用

1、配置时钟,初始化IO口

	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 | GPIO_Pin_11; //PC6/7/8/9/11 复用功能输出GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6; //PE5/6  复用功能输出GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI); //PA4  DCMI_HSYNCGPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI); //PA6  DCMI_PCLKGPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI); //PB7  DCMI_VSYNCGPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI); //PC6  DCMI_D0GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI); //PC7  DCMI_D1GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_DCMI); //PC8  DCMI_D2GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_DCMI); //PC9  DCMI_D3GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_DCMI); //PC11 DCMI_D4GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI); //PB6  DCMI_D5GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_DCMI); //PE5  DCMI_D6GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_DCMI); //PE6  DCMI_D7

2、根据时序配置DCMI接口

DCMI_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_Rising; //PCLK 上升沿有效
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware; //硬件同步HSYNC,VSYNC
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_Low; //VSYNC 低电平有效
DCMI_Init(&DCMI_InitStructure);
DCMI_Cmd(ENABLE);	//DCMI使能
//中断视情况配置
DCMI_ITConfig(DCMI_IT_FRAME, ENABLE); //开启帧中断
NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			
NVIC_Init(&NVIC_InitStructure);
代码 DCMI 初始化结构体
1 /**
2 * @brief DCMI 初始化结构体
3 */
4 typedef struct
5 {
6 uint16_t DCMI_CaptureMode; /*选择连续模式或拍照模式 */
7 uint16_t DCMI_SynchroMode; /*选择硬件同步模式还是内嵌码模式 */
8 uint16_t DCMI_PCKPolarity; /*设置像素时钟的有效边沿*/
9 uint16_t DCMI_VSPolarity; /*设置 VSYNC 的有效电平*/
10 uint16_t DCMI_HSPolarity; /*设置 HSYNC 的有效边沿*/
11 uint16_t DCMI_CaptureRate; /*设置图像的采集间隔 */
12 uint16_t DCMI_ExtendedDataMode; /*设置数据线的宽度 */
13 } DCMI_InitTypeDef;

这些结构体成员说明如下,其中括号内的文字是对应参数在 STM32 标准库中定义的宏:
(1) DCMI_CaptureMode
本成员设置 DCMI的捕获模式,可以选择为连续摄像(DCMI_CaptureMode_Continuous)
或单张拍照 DCMI_CaptureMode_SnapShot。
(2) DCMI_SynchroMode
本成员设置 DCMI数据的同步模式,可以选择为硬件同步方式
(DCMI_SynchroMode_Hardware)或内嵌码方式(DCMI_SynchroMode_Embedded)。
(3) DCMI_PCKPolarity
本成员用于配置 DCMI接口像素时钟的有效边沿,即在该时钟边沿时,DCMI会对数
据线上的信号进行采样,它可以被设置为上升沿有效(DCMI_PCKPolarity_Rising)或下
降沿有效(DCMI_PCKPolarity_Falling)。
(4) DCMI_VSPolarity
本成员用于设置 VSYNC 的有效电平,当 VSYNC 信号线表示为有效电平时,表示新
的一帧数据传输完成,它可以被设置为高电平有效(DCMI_VSPolarity_High)或低电平
有效(DCMI_VSPolarity_Low)。
(5) DCMI_HSPolarity
类似地,本成员用于设置 HSYNC 的有效电平,当 HSYNC 信号线表示为有效电平时,
表示新的一行数据传输完成,它可以被设置为高电平有效(DCMI_HSPolarity_High)或
低电平有效(DCMI_HSPolarity_Low)。
(6) DCMI_CaptureRate
本成员可以用于设置 DCMI捕获数据的频率,可以设置为全采集、半采集或 1/4 采集
(DCMI_CaptureRate_All_Frame/ 1of2_Frame/ 1of4_Frame),在间隔采集的情况下,
STM32的 DCMI外设会直接按间隔丢弃数据。
(7) DCMI_ExtendedDataMode
本成员用于设置 DCMI的数据线宽度,可配置为 8/10/12及 14位数据线宽
(DCMI_ExtendedDataMode_8b/10b/12b/14b)。
配置完这些结构体成员后,我们调用库函数 DCMI_Init 即可把这些参数写入到 DCMI
的控制寄存器中,实现 DCMI的初始化。

DCMI的DMA传输

DCMI接收到的数据,存储在DCMI_DR寄存器(32位)里面,我们采用8位数据宽度,所以每4个像素时钟,才会捕获完32位数据,第一个字节存放在LSB位置,第四个字节存放在MSB位置,如下图所示:

DCMI支持DMA传输,当DCMI_CR寄存器中的CAPTURE位置1时,激活DMA接口。摄像头接口每次在其寄存器(DCMI_DR)中收到一个完整的32位数据块时,都将发一个DMA请求,由DMA将DCMI_DR寄存器的值搬运到目的地址。

/*** @brief  配置 DCMI/DMA 以捕获摄像头数据* @param  DMA_Memory0BaseAddr:本次传输的目的首地址* @param DMA_BufferSize:本次传输的数据量(单位为字,即4字节)*/
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 = (u32)&DCMI->DR;//外设地址为:DCMI->DRDMA_InitStructure.DMA_Memory0BaseAddr = DMA_Memory0BaseAddr;//DMA传输的目的地址(传入的参数)	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_Enable;//数据地址,自增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){}
}

传输设置

//DCMI,启动传输
void DCMI_Start(void)
{  DMA_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
} 

 


http://chatgpt.dhexx.cn/article/HNqvLQD2.shtml

相关文章

Java开发技术

1、基础技术 数据结构与算法 逻辑结构:数据对象中的数据元素之间的逻辑关系 1.集合结构:集合结构中的数据元素除了同属一个集合外,没有其他关系。 2.线性结构:线性结构中的数据元素之间是一对一的关系。 3.树形结构:树…

JAVA 中的代码生成包 CGLIB (Code Generation Library)

JAVA 中的代码生成包 CGLIB (Code Generation Library) CGLIB 是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为 JDK 的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代…

Java开发实战讲解!java开发CPU最低要求

前言 本人是底层 211 本科,刚毕业,⽆科研经历,但是有些项⽬经历。 在国内监控行业某头部企业做过一段时间的实习。 想着投下字节,可以积累⼀下⾯试经验和为金九银十面招做准备。投了简历之后,过了一段时 间,HR 就打电话跟我约时间, 说明一下,我投的是北京 office。…

Java面试题技术类一

前端技术导航大全 1、面向对象编程的三大特性是什么? 2、String 和StringBuffer的区别 3、说出ArrayList,Vector, LinkedList的存储性能和特性 4、Collection 和 Collections的区别 5、HashMap和Hashtable的区别 6、final, finally, finalize的区别 7、Overload和Overri…

Java专项练习(三)

JAVA选择题 401、下列类定义代码,当用来声明对象car,并用Car carnew Car();实例化后,可以通过car对象直接赋值的字段是()402、以下哪个不是Collection的子接口?403、下列说法正确的是( )404、下面的程序将来…

Java学习汇总

6/28日已更新,错误已修改~~~有错误的地方,欢迎大家留言! 目录 一、Java基础篇 1.接口和抽象类的区别 2.重载和重写的区别 3.和equals的区别 4.异常处理机制 5.HashMap原理 6.想要线程安全的HashMap怎么办? 7.ConcurrentHa…

java面经整理

面试问题 一、Java基础1.jdk1.7到jdk1.8HashMap发生了什么变化(底层)?2.jdk1.7到jdk1.8虚拟机发生了什么变化3.String、StringBuilder、StringBuffer4.ArrayList和LinkedList有什么区别?5.ConcurrentHashMap的扩容机制6.接口和抽象…

获得阿里Java开发P7岗“农村穷苦”小伙就得安于现状?

前言 相信大家看到这个标题其实就已经可以联想到我大概是个什么样的情况了,很多人都在生活中或者是网络上甚至是家庭中都大致听过这样的话,“你这样的出生,达到现在这样的生活已经很不错了,还是别为了不切实际的梦想去冒险了&…

Java基础 常见数据结构与算法 项目总结

Java基础 1 Java基础必知必会 1.1 Java语言有哪些特点? 面向对象(封装,继承,多态);平台无关性,平台无关性的具体表现在于,Java 是“一次编写,到处运行(Wri…

Java面试知识点概览(持续更新)

Java 基础 说说自定义注解的场景及实现 利用自定义注解,结合SpringAOP可以完成权限控制、日志记录、统一异常处理、数字签名、数据加解密等功能。 实现场景(API接口数据加解密) 1)自定义一个注解,在需要加解密的方法上添加该注…

java开发工程师面试总结

面试中常被问到的问题 介绍jvmjvm内存模型程序计数器虚拟机栈本地方法栈方法区堆 垃圾回收判断对象是否存活引用计数算法可达性分析算法 垃圾收集算法复制算法标记清除算法,标记整理算法 垃圾收集器新生代收集器SerialParNewParallel Scavenge 老年代收集器Serial O…

Java面试经验总结

目录 Java面试知识点基础常识前端基础知识Java基础知识1、**并行与并发**2、**线程与进程**3、**HashMap和HashTable区别**4、**new对象创建过程原理(在JVM),从执行的角度(其他角度待续)**4、**Volatile和Synchronized**5、**线程创建的几种方法**6、**垃…

java怎么写api接口,绝对干货

正文 下文中截图来源于朋友一个pdf版本的面经,把所以知识点的答案整理了下来,耗费他至少1个月时间,在本文最后部分把这个pdf分享给大家,觉得有用的麻烦点赞关注走一波,谢谢!!!面经中有他的知识点的答案,如下图示例,非常详细(文末有领取方式)!!! 1.数据结构与算…

Java开发校招面经

面试 当前面经欠缺:docker,k8s容器,spark,flink,hbase,hive,java网络编程(netty) 一,JAVA 重写和重载 重写:方法签名要完全相同(方…

数据结构:链表逆序输出

数据结构&#xff08;一&#xff09;&#xff1a;链表逆序输出 题目描述&#xff1a;创建一个链表&#xff0c;并将链表逆序输出&#xff0c;链表中以输入0作为结束 关键代码详解&#xff1a; 附&#xff1a;全部代码 #include<stdio.h> #include<stdlib.h> #…

链表逆序 java_链表逆序(JAVA实现)

题目:将一个有链表头的单向单链表逆序 分析: 链表为空或只有一个元素直接返回; 设置两个前后相邻的指针p,q,使得p指向的节点为q指向的节点的后继; 重复步骤2,直到q为空; 调整链表头和链表尾; 图解: 以链表A->B->C->D为例,逆序此链表。 0.初始状态 …

2-6 链表逆序及其C++实现

更多系列博文请点击&#xff1a;0-数据结构与算法链接目录 2-6 链表逆序 我只介绍两种常用方法吧&#xff0c;非递归方法 和 递归 方法 我觉得够用就行 1、非递归方法&#xff1a; 将第二个元素后面的元素依次插入到头结点后面&#xff0c; 最后再把原始第一个元素放到原…

c语言 数据结构 双向循环链表逆序

双链循环链表排序&#xff1a; 原链表&#xff1a; 1 2 3 4 5 6 7 8 9 10 逆序后&#xff1a;10 9 8 7 6 5 4 3 2 1 思路&#xff1a; 把最后一个节点删除&#xff0c; 插到head下面去 数据 1 不用管&#xff0c; 把后面的数据往 1 前面怼&#xff0c; 1自然就是最后一个了…

C语言实现链表的逆序的几种方式

文章目录 通过头插法实现的通过双指针实现链表的逆序通过栈来实现的通过递归来实现 通过头插法实现的 1、通过头插法&#xff08;两条链表&#xff09;来实现的。通过遍历原来的链表&#xff0c;将遍历得到的每一个节点都插入到新链表的头结点&#xff0c;然后遍历新链表&…

C语言单向链表的逆序输出

最近在学习链表&#xff0c;看到书上说可以采取每次在链表头部插入新增节点的方法&#xff0c;将链表逆序&#xff0c;也就是建立的链表节点内容与数据的输入顺序相反。我便来了兴趣&#xff0c;想着试试看&#xff0c;结果没搞懂&#xff0c;于是开始百度。看了几遍博客后终于…