STM32
直播中

李涛

7年用户 1308经验值
私信 关注
[问答]

如何实验STM32F407摄像头拍照网络通信

如何实验STM32F407摄像头拍照网络通信

回帖(1)

张鸿青

2021-10-13 15:38:00
  应单片机课设要求,做了一个摄像头拍照网络通信C/S实时LCD显示。该工程基于原子STM32F4的摄像头与网络通信实验,在此基础上,将其整合。
1.预期功能:




  • 摄像头拍取的内容实时传输至LCD进行显示
  • 通过网络通信C/S方式将STM32摄像头拍取的照片传输到电脑端
  • 在PC端开发可视化界面接受摄像头数据并更新显示

2.实施步骤:




  • 1.参考STM32原子摄像头实验与网络通信实验例程,主要需要了解以下知识。


    • 1.1摄像头的数据如何传输至STM32中?
    • 1.2摄像头照片的传输数据格式是如何组成的?
    • 1.3LCD如何显示图片?
    • 1.4如何通过STM32与外界建立CS服务关系?
    • 1.5STM32如何通过网络向外界进行发送基本的数据?


  • 2.整合两个实验工程,实现照片实时显示至LCD上,并同时通过CS服务端发送摄像头获取的数据。
  • 3.socket编程实现数据包的接收与重组,在了解数据格式的基础上编写照片解码程序,编写PC端可视化界面。

3.设计思路:

以下为实施步骤中对应的设计思路与问题解答:



  • 1.1 STM32F4自带有一个一个数字摄像头( DCMI)接口,该接口是通过与摄像头的帧同步、行同步进行传输数据,并将接收到的数据放到一个32位的数据寄存器(DCMI_DR)中,然后通过DMA进行数据传输。
  • 1.2 摄像头OV2640可以支持两种照片数据格式输出:RGB565或JPEG格式。设置分辨率后,假定为640*320,以RGB格式输出时,则传输时序会参考行同步信号、帧同步信号、像素时钟进行传输,一幅图片即为一帧,其中一帧由640行组成,一行有320个像素,每个像素由两个字节组成(RGB565 5+6+5=16 bit=2byte),一个PCLK时钟传输一个字节,这便为传输时序。当以JPEG格式传输时,摄像头内部会自动先对照片进行压缩,随后以同种方式进行传输数据,只是其中PCLK的数目大大减少,且不连续。输出的JPEG输出以0XFF、0XD8开头,以0XFF、0XD9结束。在0XFF,0XD8之前,或者 0XFF,0XD9 之后,会有不定数量的0存在,我们一般选择忽略即可。
  • 1.3 LCD在内存中构建了一个映射缓冲区,当往该缓冲区写数据时,硬件会自动将该数据解析后显示在LCD上。LCD与图片类似,都是以一个像素为单位进行显示,一般格式为RGB565进行显示,所以当DCMI接收到摄像头传输的数据后,通过DMA将数据直接写入LCD的缓冲区地址便可实现图片的显示。
  • 1.4 STM32通过LWIP小型的协议栈以TCP/IP协议的格式实现C/S端网络通信。程序每次初始化时,会通过DHCP获取IP地址,并且设定固定端口,当作为Client时,还需用户用按键指定Server端的IP与port,设定完毕后,开发板会不断的尝试向Server端发起连接。
  • 1.5当通信双方建立连接后,不断互相进行侦听,STM32采用回调函数的方式进行发送信息,设定一个u8类型的数据,将其各位作为标志位,当有数据需要发送时,置其最高位,采用定时器的方式不断对变量lwip_localtime增加,在main函数中进入while循环,采用轮询的方式,相当于一个软定时器,每xms秒调用一次相关的处理函数。
  • 2.1 摄像头实验与网络通信实验两个工程整合后,进行编译时提示RAM不足,困扰了许求,后来发现是因为摄像头实验中申请的照片缓冲区太大约有100K,而网络通信实验中的也申请了很大的发送缓冲区与接收缓冲区,将这两个变量改小后,程序编译通过。
  • 2.2网络通信C/S建立完成,开始尝试发送少量数据,发现PC端接收没问题。但当发送大量照片数据包时,发现其实际的总接收量每次总是1912byte,考虑是否发送数据量过大,发送端无法自己分片,只能发送MTU数量大小,因此在发送数据前增加了一个数据分片发送程序,随后数据量发送正常,一次发送后的总接收量可以大于1912byte,甚至可达20K。
  • 2.3数据发送量解决后,但接收的数据不正确,对数据仔细观察后,前几个数据包数据都正确,但后面的数据包就开始出现丢包重的现象,同时数据包到达的顺序也有些不对,写该文档时在想,是否我的数据发送缓冲区定义的稍小了,但我每次发送数据时有限量分片的,所以该问题暂时还无法解决,最后我们决定用串口进行代替网络通信发送数据。
  • 3.Sokert编程在接收端其实也是有些问题,当发送数据量过大时,PC端接收数据时一次也只能接收到部分数据,因此在接收端还需要编写数据包重组程序。
    最后我们计划使用串口来接收数据,我们采用python语言进行编写接收程序与图片解码程序。使用串口接收库读取接收到的数据,判断如果为JPEG格式图片的包头则创建文件,接收数据,以二进制的方式将数据写人文件,直到检测到结束标志,关闭储存文件。PC端的可视化软件采用MFC编程,使用定时器的事件,循环读取文件夹中的指定照片并显示,于是便实现类似与视频的效果。由于可视化界面与图片解码是两个进程,无法进行直接的数据共享,因此我们采用文件的方式进行数据传输,所以每次python脚本接收到照片后需要写入硬盘,随后MFC软件需要从硬盘中读取该照片,这期间设计到两次的硬盘的读写,所以效率较低,速度较慢,从而导致最后视频显示器的帧率较低。

4.具体实现

4.1 LCD显示

通过源代码分析以及上面的解答,该功能很容易实现,通过DMA直接传输摄像头的数据便可。
4.2 照片数据发送至电脑端

前面已经说过,实际上工程最后采用了串口进行数据发送,发送代码可参考原子本身的摄像头实验,分析后便可知串口发送数据如下:


for (i=0;i);}接收端我用python写了一个脚本进行数据的接收及照片的解码,运行后会将照片存在当前文件夹下:



#!/usr/bin/python2.7#-*- encoding: UTF-8 -*-import serialimport sysimport timeimport osdef getFileName():    global i    i = i + 1     return "photo" + str(i) + ".jpeg"def receiveData():    ser = serial.Serial('COM5',115200)    try:        while (True):            start_1st = ser.read()            if ord(start_1st) == 0xFF:                start_2st = ser.read()                if ord(start_2st) == 0xD8:                    fileName = getFileName()                    print fileName                    fjpg = open(fileName,"wb")                    fjpg.write(start_1st)                    fjpg.write(start_2st)                    while (True):                        data = ser.read()                        fjpg.write(data)                        if ord(data) == 0xFF:                            end_1st = ser.read()                            fjpg.write(end_1st)                            if ord(end_1st) == 0xD9:                                fjpg.close()                                print("recieve data finish")                                break                else:                    print("no 2st start code")            else:                print("no 1st start code")    except KeyboardInterrupt:        print "Interrupted by user, shutting down"        sys.exit(0)global ii = 0if __name__ == "__main__":    receiveData()3.PC端开发可视化界面显示照片并更新

1.PC端采用MFC进行编程,照片使用Picture Control控件显示。
2.当需要实时更新Picture Contro中的图片,想让它变成类似于一个视频帧时,可以设置MFC中的定时器事件,这个定时时间关系到帧率,每次读取固定文件夹目录下的照片并显示,同时使用python脚本更新图片,便可实现该功能。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分