基于C语言实现的单片机传输的VGA图像数据生成bmp文件
参考硬件:stm32(但其实是个能带动ov7725有串口的单片机就行)、ov7725,上位机(电脑) 实现原理:ov7725通常输出QVGA/VGA的240*320图像,一个像素点由RBG565(16bits)表示,但常用的电脑bmp像素由BGR888构成(又称bmp24),这需要小小的进行一下像素点的数据处理,然后就是编写电脑串口和bmp文件头实现串口数据接收以及自动生成bmp 建议搜索查阅:因为有点想偷懒,把编写时涉及到的知识点罗列一下(当初在csdn一个个查的,都可以查到很好的解说昂),不再详细解说,见谅
- c语言实现rgb565转bmp24(实现像素点的格式变化)
- c语言调用windows自带库编写串口(实现串口在c语言里的调用,可以存到想存的数组里,不然你把数据用串口助手传到txt里面还真不好弄,他那个是utf8格式)
- c语言生成bmp文件(教你打造bmp文件头,bmp24的文件头最简单了,所以建议先做好数据处理)
- 其他
下面是程序代码,需要更改的地方我用中文表达出来了
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <winnt.h>
#include "rgb2bmp.h"
int main()
{
int cnt;
DWORD dwLength;
unsigned short recvBuf[76800];
DWORD dwactlen;
char psendbuf[32] = "test\n";
char ch;
DCB myDCB;
HANDLE m_hComm;
m_hComm = CreateFile(
"COM3:",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (m_hComm == (HANDLE)-1)
{
printf("打开串口失败");
return 0;
}
if (!GetCommState(m_hComm, &myDCB))
{
printf("GetCommState error");
return FALSE;
}
myDCB.BaudRate = CBR_115200;
myDCB.fBinary = TRUE;
myDCB.fParity = NOPARITY;
myDCB.fOutxCtsFlow = FALSE;
myDCB.fOutxDsrFlow = FALSE;
myDCB.fDtrControl = DTR_CONTROL_DISABLE;
myDCB.fDsrSensitivity = FALSE;
myDCB.fTXContinueOnXoff = TRUE;
myDCB.fOutX = FALSE;
myDCB.fInX = FALSE;
myDCB.fErrorChar = FALSE;
myDCB.fNull = FALSE;
myDCB.fRtsControl = RTS_CONTROL_DISABLE;
myDCB.fAbortOnError = FALSE;
myDCB.ByteSize = 8;
myDCB.Parity = NOPARITY;
myDCB.StopBits = ONESTOPBIT;
if (!SetCommState(m_hComm, &myDCB))
{
printf("SetCommState error");
return FALSE;
}
SetupComm(m_hComm, 1024, 1024);
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR);
COMMTIMEOUTS TimeOuts;
TimeOuts.ReadIntervalTimeout = 1000;
TimeOuts.ReadTotalTimeoutMultiplier = 500;
TimeOuts.ReadTotalTimeoutConstant = 5000;
TimeOuts.WriteTotalTimeoutMultiplier = 500;
TimeOuts.WriteTotalTimeoutConstant = 2000;
SetCommTimeouts(m_hComm, &TimeOuts);
ReadFile(m_hComm, recvBuf, 76800*2, &dwLength, NULL);
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR);
CloseHandle(m_hComm);
int nWidth=320;
int nHeight=240;
char* newFile="C:\\Users\\17001\\Desktop\\rgb_new8.bmp";
long nData=nWidth*nHeight;
long total =nWidth*nHeight*3;
unsigned char* pVisit=(unsigned char*)malloc(total*sizeof(char));
unsigned char* tmp=pVisit;
unsigned short* rgb_buffer=(unsigned short*)recvBuf;
long i=0;
unsigned char R,G,B;
while(i<nData)
{
B = *rgb_buffer&0x1f;
G = (*rgb_buffer>>5)&0x3f;
R = (*rgb_buffer>>11)&0x1f;
B = B<<3;
G = G<<2;
R = R<<3;
*pVisit=B;pVisit++;
*pVisit=G;pVisit++;
*pVisit=R;pVisit++;
rgb_buffer++;
i++;
}
printf("read over.nData%ldn",nData);
/*写阶段*/
FILE *result = fopen(newFile,"wb") ;
if (result == NULL)
{
printf("open new file failed.n");
return -1;
}
RGB2BMP(tmp,nWidth,nHeight,result);
fclose(result);
return 0;
}
以下是头文件,负责生成bmp
#include <stdio.h>
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef struct
{ long imageSize;
long blank;
long startPosition;
}BmpHead;
typedef struct
{
long Length;
long width;
long height;
WORD colorPlane;
WORD bitColor;
long zipFormat;
long realSize;
long xPels;
long yPels;
long colorUse;
long colorImportant;
}InfoHead;
typedef struct
{ BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
}RGBMixPlate;
int RGB2BMP(unsigned char *rgb_buffer,int nWidth,int nHeight,FILE*fp1)
{
BmpHead m_BMPHeader;
char bfType[2]={'B','M'};
m_BMPHeader.imageSize=3*nWidth*nHeight+54;
m_BMPHeader.blank=0;
m_BMPHeader.startPosition=54;
fwrite(bfType,1,sizeof(bfType),fp1);
fwrite(&m_BMPHeader.imageSize,1,sizeof(m_BMPHeader.imageSize),fp1);
fwrite(&m_BMPHeader.blank,1,sizeof(m_BMPHeader.blank),fp1);
fwrite(&m_BMPHeader.startPosition,1,sizeof(m_BMPHeader.startPosition),fp1);
InfoHead m_BMPInfoHeader;
m_BMPInfoHeader.Length=40;
m_BMPInfoHeader.width=nWidth;
m_BMPInfoHeader.height=nHeight;
m_BMPInfoHeader.colorPlane=1;
m_BMPInfoHeader.bitColor=24;
m_BMPInfoHeader.zipFormat=0;
m_BMPInfoHeader.realSize=3*nWidth*nHeight;
m_BMPInfoHeader.xPels=0;
m_BMPInfoHeader.yPels=0;
m_BMPInfoHeader.colorUse=0;
m_BMPInfoHeader.colorImportant=0;
fwrite(&m_BMPInfoHeader.Length,1,sizeof(m_BMPInfoHeader.Length),fp1);
fwrite(&m_BMPInfoHeader.width,1,sizeof(m_BMPInfoHeader.width),fp1);
fwrite(&m_BMPInfoHeader.height,1,sizeof(m_BMPInfoHeader.height),fp1);
fwrite(&m_BMPInfoHeader.colorPlane,1,sizeof(m_BMPInfoHeader.colorPlane),fp1);
fwrite(&m_BMPInfoHeader.bitColor,1,sizeof(m_BMPInfoHeader.bitColor),fp1);
fwrite(&m_BMPInfoHeader.zipFormat,1,sizeof(m_BMPInfoHeader.zipFormat),fp1);
fwrite(&m_BMPInfoHeader.realSize,1,sizeof(m_BMPInfoHeader.realSize),fp1);
fwrite(&m_BMPInfoHeader.xPels,1,sizeof(m_BMPInfoHeader.xPels),fp1);
fwrite(&m_BMPInfoHeader.yPels,1,sizeof(m_BMPInfoHeader.yPels),fp1);
fwrite(&m_BMPInfoHeader.colorUse,1,sizeof(m_BMPInfoHeader.colorUse),fp1);
fwrite(&m_BMPInfoHeader.colorImportant,1,sizeof(m_BMPInfoHeader.colorImportant),fp1);
fwrite(rgb_buffer,3*nWidth*nHeight,1,fp1);
return 0;
}
注意:按道理来说满足我的硬件条件的相似情况,头文件不用改,c文件大部分不需要改动 有时生成的图片会出现色差,经过串口对比,可能是传输过程中少了一个字节导致像素点错位,解决方法是exe窗口跳出后,单片机稍微等待几秒再发送数据
实验现象:
结语:书写不够正确之处敬请指正,希望学习之路相互交流
|