stm32f407提取摄像头数据

最近做的一个项目需要对摄像头采集到的数据进行简单的处理,我们用的MCU是Cortex-M4 F407系列的。关于STM32F4xx的视频处理,ST的官方给的例程是在显示屏上直接显示摄像头采集到的数据。经过了一番探索……根据官方的英文手册、网友们的无私分享和对各个例程的研究。今天终于搞定了将数据采集下来。
   官方给的例程中,是通过DMA将数据直接输入到屏幕中的。DMA简单地说就是各个设备间自动倒腾内存的东西,转移数据的时候并不需要CPU干涉,减少了CPU的负担。由于所有的数据都不经过CPU进行干涉,如何获取其中的数据也是倒腾了一阵子。下面讲讲主要代码的配置:
  在摄像头DCMI的配置中首先根据摄像头将各个管脚设置成需要的,这个例程里都有,不贴了。
  要一帧一帧处理数据完了再获取数据,摄像头配置中DCMI_CaptureMode要配置成快照模式:DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_SnapShot,这样每完成一帧图像的获取,摄像头就停止捕获数据了,要想它再次捕获数据只需要执行DCMI_CaptureCmd(ENABLE)就可以了。
  然后是摄像头的中断配置(DCMI_ITConfig),在中断配置中,官方的例程是配置的垂直同步DCMI_ITConfig(DCMI_IT_VSYNC, ENABLE),通过垂直同步进行的中断中,获得的数据是整帧画面的数据,我们的板子的RAM就只有192k,呵呵,一帧图像放不进去,所以没有使用垂直同步中断,用的是列数据中断DCMI_ITConfig(DCMI_IT_LINE, ENABLE)。列数据中断,也就是说摄像头每采集到一列数据,就在它的列中断位(DCMI_IT_LINE位)上置1。我们这个摄像头采集的数据是240*320像素的16位色图像。也就是说每次摄像头产生列中断的时候都会采集到320个16位的数据。在每次列中断发生时都在列中断的中断服务中对数据进行处理就ok啦。
  在官方给的例程文件中stm32f4xx_it.c是用来放各个中断服务的文件。摄像头的中断服务在void DCMI_IRQHandler(void)函数里面,我们这用到的列中断,所以对其中的if (DCMI_GetITStatus(DCMI_IT_LINE) != RESET) 进行添加代码即可,最后不要忘了清除摄像头的列中断标志DCMI_ClearITPendingBit(DCMI_IT_LINE)。
  为了能够更有效的利用CPU的资源,当然不要丢了DMA这神器。下面进行DMA的配置。官方例程中需要改的的地方是DMA_InitStructure.DMA_Memory0BaseAddr = FSMC_LCD_ADDRESS这个地方,FSMC_LCD_ADDRESS是LCD屏幕的地址,我们这里要把数据取下来,得弄个数组存放数据。这里我弄了个全局的数组变量uint16_t fps[320],每个像素16位数据RGB--5:6:5,每列320个数据。所以DMA_Memory0BaseAddr参数就是这么配置DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)fps。DMA_MemoryInc要设置成DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable。这是目的地址写入后自增指针的配置。这样数据才能往fps数组里排着写入。
  设置的理论基本说完了。下面上代码


DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_SnapShot;//快照模式
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;//硬件时钟
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Falling;//下降沿
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;//垂直极性
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_High;//水平极性
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;//捕获率
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;//8位数据模式
DCMI_Init(&DCMI_InitStructure);//初始化上面的摄像头配置


DCMI_ITConfig(DCMI_IT_LINE, ENABLE);//列中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//中断抢占组1
NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;//摄像头中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//先占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//从优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//开启中断控制通道
NVIC_Init(&NVIC_InitStructure);//初始化上面的中断配置


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);//使能DMA2时钟
DMA_DeInit(DMA2_Stream1);//复位DMA2_Stream1数据流的配置
DMA_InitStructure.DMA_Channel = DMA_Channel_1;//DMA流通道
DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;//外设内存地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)fps;//内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//数据方向从外设到内存
DMA_InitStructure.DMA_BufferSize = 320;//每次转移320数据,每个数据的位数根据目的地设置定
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不改变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址在每次写入后自增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//外设每单位长度_Word是32位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//内存每单位长度_HalfWord是16位
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;//FIFO水平阈值
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//内存单通道
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设单通道
DMA_Init(DMA2_Stream1, &DMA_InitStructure);//初始化上面的DMA配置


void DCMI_IRQHandler(void)//摄像头的中断服务
{      
if (DCMI_GetITStatus(DCMI_IT_VSYNC) != RESET)//垂直中断的配置 需要DCMI_ITConfig(DCMI_IT_VSYNC, ENABLE);
{  
DCMI_ClearITPendingBit(DCMI_IT_VSYNC);  
}
if (DCMI_GetITStatus(DCMI_IT_LINE) != RESET)//列中断的配置 需要DCMI_ITConfig(DCMI_IT_LINE, ENABLE);
{
DCMI_ClearITPendingBit(DCMI_IT_LINE);
}
if (DCMI_GetITStatus(DCMI_IT_FRAME) != RESET)//帧中断的配置 需要DCMI_ITConfig(DCMI_IT_FRAME, ENABLE);
{
DCMI_ClearITPendingBit(DCMI_IT_FRAME);
}
if (DCMI_GetITStatus(DCMI_IT_ERR) != RESET)//错误中断的配置 需要DCMI_ITConfig(DCMI_IT_ERR, ENABLE);
{
DCMI_ClearITPendingBit(DCMI_IT_ERR);
}
}
  • 9
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于使用STM32F407微控制器实现摄像头循迹功能,您可以按照以下步骤进行操作: 1. 硬件准备:准备一个适配STM32F407摄像头模块,例如OV7670摄像头模块。 2. 连接摄像头模块:将摄像头模块与STM32F407进行连接。具体的连接方式可以参考摄像头模块的数据手册,通常需要连接摄像头数据线(如SCL、SDA)、控制线(如VSYNC、HREF、PCLK)以及电源线。 3. 初始化摄像头:使用STM32F407的GPIO和I2C等接口,编写代码初始化摄像头模块。这包括设置摄像头的寄存器配置、初始化I2C通信等。 4. 采集图像数据:使用STM32F407DMA或者直接读取方式,从摄像头模块读取图像数据。可以通过设置相应的寄存器来控制图像的采集分辨率、帧率等参数。 5. 图像处理:将采集到的图像数据进行处理,例如图像预处理、边缘检测、色彩识别等。可以使用一些图像处理算法来提取所需的循迹信息。 6. 循迹算法:根据处理后的图像数据,编写算法实现循迹功能。可以使用图像处理结果中的边缘信息或者颜色信息来判断循迹方向,然后控制机器人或车辆进行相应的动作。 需要注意的是,以上步骤只是一个大致的指导,具体的实现方式会根据摄像头模块和实际需求而有所差异。您可以参考相关的资料和示例代码来进行具体的开发。希望对您有所帮助!如果您还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值