零知增强板-DCMI接口 OV2640 摄像头 串口输出/LCD显示

本文将演示在零知增强板上进行摄像头的显示和传输,零知增强板自带摄像头接口,可以直接接入OV2640\OV7670等相同接口的摄像头模块。

一、硬件连接:

本文使用OV2640模块: 该模块可以直接接入零知-增强板,不需要其他连线,如果要在LCD上显示,则按照之前的教程接入TFT屏的连线即可。

二、程序

(1)在LCD上直接显示图像,在工程代码camera.h中:


												
	#define JPEG_OUTPUT_MODE//注释掉此行代码,表示RGB565模式,不注释就是JPG模式					
						

注释掉该行代码,我们使用RGB565模式输出图像,然后直接显示到LCD上,lcd的接口驱动在前面帖子已有讲解,这里就直接拿来使用,关键代码如下: TFT屏初始化:


							
	LCDx_Init();
						

然后抓取图像,放置到LCD显存:


												
						
	camera.startCapture((uint32_t)&LCD_TYPE->LCD_RAM);
						
				

这样就可以直接显示到LCD图像了:

(2)抓取JPG格式图像,然后通过串口传输到PC显示: a、在camera.h中,定义


												
						
	#define JPEG_OUTPUT_MODE					
	

表示使用JPG格式输出图像,然后在程序中获取图像数据并处理:


										
	camera.startCapture((uint32_t)&jpeg_buf);											
			

图像存储到了jpeg_buf中了,然后我们把数据通过串口发送出去:


											
	//process the jpg data, send to Serial3
	  while(1)
	    {
	 
	        if(jpeg_data_ok==1) //
	        {
	            p=(uint8_t*)jpeg_buf;
	 
	            Serial.println("send one frame data...");
	 
	            for(i=0;i<jpeg_data_len*4;i++)       //
	            {
	 
	                Serial3.write(p[i]);
	            }
	 
	            jpeg_data_ok=2; //
	        }
	    }									
				

这里使用Serial3传输图像数据,波特率设置为 460800,这样可以有比较高的帧率。

b、上位机解析并显示:

在PC端,串口收到数据后,按照jpg图像格式解析并显示,以下为Qt平台的代码:


													
	while(1){
	 
	        while(!m_serial->bytesAvailable()){
	            QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
	        }
	 
	        if(!m_serial->isOpen()){
	            return;
	        }
	 
	        QByteArray str1;
	        QByteArray str2;
	        QByteArray str3;
	        QByteArray str4;
	 
	        bool start = false;
	 
	        str1 = m_serial->read(1);
	        if(str1.contains(start_flag.at(0))){
	            str2 = m_serial->read(1);
	            if(str2.contains(start_flag.at(1))){
	                str3 = m_serial->read(1);
	                if(str3.contains(start_flag.at(2))){
	                    str4 = m_serial->read(1);
	                    if(str4.contains(start_flag.at(3))){
	                        start = true;
	                    }
	                }
	            }
	        }
	 
	        if(start == false){
	            continue;
	        }
	 
	        QByteArray str;
	        str.append(str1);
	        str.append(str2);
	        str.append(str3);
	        str.append(str4);
	 
	//        if(str.contains(start_flag))
	        {
	            qDebug()<<"frame start,num="<<m_fram_num;
	 
	            m_frameBuff.clear();
	            m_frameBuff.append(str);
	 
	            while(1){
	                if(m_serial->bytesAvailable()){
	 
	                    if(!m_serial->isOpen()){
	                        return;
	                    }
	 
	                    QByteArray bytes = m_serial->read(1);
	 
	                    m_frameBuff.append(bytes);
	 
	                    if(bytes.contains(end_flag.at(0))){
	                        QByteArray byte2 = m_serial->read(1);
	 
	                        m_frameBuff.append(byte2);
	 
	                        if(byte2.contains(end_flag.at(1))){
	 
	                            break;
	                        }
	                    }
	 
	                }
	                QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
	            }
	 
	            qDebug()<<"frame read done"<<","<<m_frameBuff.size();
	            qDebug()<<"buff:"<<m_frameBuff.toHex();
	 
	            QString picname = QString("temp%1.jpg").arg(m_fram_num);
	 
	            m_fram_num++;
	 
	            QImage img = QImage::fromData(m_frameBuff);
	 
	            QPixmap pixmap = QPixmap::fromImage(img);
	 
	            if(ui->checkNormalSize->isChecked()){
	                //no scaled
	            }else{
	                pixmap = pixmap.scaled(ui->labelPIC->width(), ui->labelPIC->height(),Qt::KeepAspectRatio);
	            }
	 
	            ui->labelPIC->setPixmap(pixmap);											
				

也可以直接保存数据到本地,然后可以直接打开JPG格式图像。

简单说明:


															
	void begin(uint8_t device_id);
	 void setOutSize(uint16_t w, uint16_t h);
	 
	 void startCapture(uint32_t memaddr);
	 void setColorBarMode(uint8_t colorbar);
	 
	 void set_reg_value(uint8_t reg,uint8_t data);
	 uint8_t get_reg_value(uint8_t reg);					
						

上述代码中begin用于摄像头初始化,setOutSize设置输出的图像大小,这里为了简便,最大为800*600,如果需要更大的,需要在源码中改变初始化代码即可。 startCapture抓取图像数据,并设置存放的位置,如LCD的显存,内存等;setColorBarMode是测试模式,输出彩条;set_reg_value直接操作寄存器,设置某个寄存器的值。

完整代码


零知-平台工程代码: dcmi-camera.7z(点击下载)
上位机软件(可执行程序): 串口摄像头上位机调试.7z(点击下载)
上位机源码(Qt工程代码): camera-capture.7z(点击下载)