stm32 - 摄像头图像获取、显示

1  摄像头配置

       用i2c总线往摄像头寄存器中写寄存器;

      i2c总线为:一条时钟线,一条数据线,遵循i2c协议来写;

      摄像头的sccb接口对应i2c接口;两协议类似;

      其中涉及的主要内容是i2c协议读写数据的时序;开始信号、终止信号、设备地址;

      写入信号后可以再用i2c读取信号的内容,以确定的确写入了;

      用示波器测量摄像头的输入时钟(xclk)、输出像素时钟(pclk)、行同步信号(hs)、场同步信号(vs)、输出数据管脚;如果管脚和预期类似说明摄像头已经开始工作了;

      gpio模仿i2c也很简单,就是符合协议的控制电平跳变;

          

    


2 摄像头数据读取

单片机的DCMI口对接摄像头的输出口;

摄像头配置的输出时序为数字摄像头时序;

摄像头接口也stm32的DCMI接口对接;

DCMI接口配置时要小心其读取视频数据的中断函数是高电平有效还是低电平有效;

         DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;//DCMI_VSPolarity_High;
         DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;//DCMI_HSPolarity_Low;  

DCMI中的FIFO缓冲接收到的数据、重组数据;比如摄像头口是8位的,而DCMI的数据寄存器是32位的,FIFO将接受到的八位的数据缓存为32位的;而在液晶上显示的是rgb565的是16位的,在DMA传输时一次传输16为,数据才不会乱;这种情况下DMA传输的源数据宽度为32、目的数据宽度为16位;

DCMI有帧中断、行中断;其中断服务函数都指向DMA传输;

摄像头的原始数据是RGB RAW格式,这个原始数据的排列格式是 RGRG/GBGB排列的,我们叫做 Bayer pattern(这个最最常见)。





3 DMA传输视频数据到显存

DMA是从DCMI的数据寄存器(0x50050028)搬移数据到显存地址(液晶会自动显示该地址的内容);

DCMI中的FIFO缓冲接收到的数据、重组数据;比如摄像头口是8位的,而DCMI的数据寄存器是32位的,FIFO将接受到的八位的数据缓存为32位的;而在液晶上显示的是rgb565的是16位的,在DMA传输时一次传输16为,数据才不会乱;这种情况下DMA传输的源数据宽度为32、目的数据宽度为16位;一次传输16位(一个RGB)可以防止像素乱序;

我们在编程时一般都会明确指定一个传输数量,在完成一次数目传输后DMA_SxNDTR计数值就会自减,当达到零时就说明传输完成。
    /*行中断到来时、一行一行将数据传输到显存,行中断来了一定是新一行的数据,FSMC_LCD_ADDRESS + lcd_width*2*line_num保证为液晶屏的新一行的开始地址;一行图像的字节为 
img_width*2/4;*/

    OV2640_DMA_Config(FSMC_LCD_ADDRESS + lcd_width*2*line_num,img_width*2/4);  //  +(lcd_width*2*(lcd_height-line_num-1))
    DCMI_ClearITPendingBit(DCMI_IT_LINE); 

   ///液晶屏的分辨率
     uint16_t lcd_width=800, lcd_height=480;
   ///摄像头采集图像的大小
      uint16_t img_width=1280, img_height=800;






4 stm32时钟树

倍频器形状:

分频器形状;

选择器形状:




  • 11
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个基于STM32摄像头模块的图像反馈控制机械臂运动的代码示例: ```c #include "stm32f4xx.h" #include "ov7670.h" #include "servo.h" int main(void) { OV7670_Init(); // 初始化摄像头 Servo_Init(); // 初始化舵机控制器 while(1) { uint16_t *img_ptr = OV7670_CaptureImage(); // 获取摄像头拍摄到的图像 // 在这里添加图像识别算法,识别物体并计算机械臂需要运动的方向和距离 // 例如,下面的代码假设识别到的物体位于图像中心,根据物体在图像中心的偏移量来计算舵机需要转动的角度 int offset = img_width / 2 - object_x; int angle = offset * 0.1; // 假设每个像素对应0.1度的角度 // 控制舵机转动到指定角度 Servo_SetAngle(angle); // 将带有标记的图像显示在LCD上 OV7670_DisplayImage(img_ptr); } } ``` 这段代码中,我们首先通过`OV7670_Init()`函数初始化了摄像头模块,然后使用`Servo_Init()`函数初始化了舵机控制器。然后,使用`OV7670_CaptureImage()`函数获取摄像头拍摄到的图像,并将图像指针传递给图像识别算法进行处理。在这里,我们假设识别算法已经完成,并计算出了机械臂需要运动的方向和距离。 接着,我们根据识别结果计算出舵机需要转动的角度,并使用`Servo_SetAngle()`函数将舵机转动到指定角度。请注意,这里的`Servo_SetAngle()`函数是一个自定义函数,需要您根据自己的舵机控制器进行编写。 最后,使用`OV7670_DisplayImage()`函数将带有标记的图像显示在LCD上。请注意,这里的`OV7670_DisplayImage()`函数是一个自定义函数,需要您根据自己的硬件和显示模块进行编写。 需要注意的是,这只是一个简单的示例代码,实际的图像识别和机械臂控制算法会更加复杂。您需要根据自己的实际应用场景进行算法设计和代码实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值