作者:蓝色星宇
转自:http://www.cnblogs.com/glguan/archive/2012/02/08/2343034.html
在硬件平台:STM32 +SSD1963+4.3TFT(TP)+TFcard 实现了将显示数据存储为bmp文件的应用。
TFT应用为RGB565格式的16位色显示480*272分辨率,bmp文件RGB565格式的位图很多软件打不开,大部分是只支持RGB555的。因此做了两种类型 的代码。bmp文件存储在TF卡,以下代码已通过调试。
#define LCD_READ_BUFFER_SIZE 2048//1024
#define FILE_HEADER_SIZE 0x36//0x3E//0x36
#define RGB565_FILE_HEADER_SIZE 0x46//0x3E//0x36
uint8_t LCDReadDataBuffer[LCD_READ_BUFFER_SIZE];//[WAVEFRAMEBUFFERSIZE+1];
const char bmpname[21][11]={"DSO01.bmp","DSO02.bmp","DSO03.bmp","DSO04.bmp","DSO05.bmp","DSO06.bmp","DSO07.bmp","DSO08.bmp","DSO09.bmp","DSO10.bmp","DSO11.bmp","DSO12.bmp","DSO13.bmp","DSO14.bmp","DSO15.bmp","DSO16.bmp","DSO17.bmp","DSO18.bmp","DSO19.bmp","DSO20.bmp","DSO21.bmp"};
#ifdef RGB565_FILE
const char BmpHeaderRGB565[RGB565_FILE_HEADER_SIZE]={
//file header
0x42,0x4D, //0x00~0x01,type"BM"
0x48,0xFC,0x03,0x00, //0x02~0x05,file size:16bit:480x2(RGB565)x272+0x36+2(result need Divisible by 4)
0x00,0x00,0x00,0x00, //0x06~0x09,reserved 0x00
0x46,0x00,0x00,0x00, //0x0A~0x0D,bmp data offset
0x38,0x00,0x00,0x00, //0x0E~0x11,bmp header size
0xE0,0x01,0x00,0x00, //0x12~0x15,width:480
0x10,0x01,0x00,0x00, //0x16~0x19,height:272
0x01,0x00, //0x1A~0x1B,planes:always"1"
//information header
0x10,0x00, //0x1C~0x1D,bits per pixel:16bits;
0x03,0x00,0x00,0x00, //0x1E~0x21,compression:no
0x02,0xFC,0x03,0x00, //0x22~0x25,bmp data size:480*2(R5G6B5)*272+2(result need Divisible by 4)
0x00,0x00,0x00,0x00, //0x26~0x29,HResolution
0x00,0x00,0x00,0x00, //0x2A~0x2D,VResolution
0x00,0x00,0x00,0x00, //0x2E~0x31,colors
0x00,0x00,0x00,0x00, //0x32~0x35,important
//Palettte: RGB565
///*
0x00,0xF8,0x00, //0x36~0x38,Blue mask:& 0xF800)>>8
0x00,0xE0,0x07, //0x39~0x3B,Green mask:& 0x07E0)>>3
0x00,0x00,0x1F, //0x3C~0x3E,Red mask:& 0x001F)<<3;
0x00,0x00,0x00, //0x3F~0x41,Alpha
0x00,0x00,0x00,0x00, //0x42~0x45,reserved
//*/
};
#else //RGB555 bmp file
const char BmpHeader[FILE_HEADER_SIZE]={
//file header
0x42,0x4D, //0x00~0x01,type"BM"
0x38,0xFC,0x03,0x00, //0x02~0x05,file size:16bit:480x2(RGB565)x272+0x36+2(result need Divisible by 4)
0x00,0x00,0x00,0x00, //0x06~0x09,reserved 0x00
0x36,0x00,0x00,0x00, //0x0A~0x0D,bmp data offset
0x28,0x00,0x00,0x00, //0x0E~0x11,bmp header size
0xE0,0x01,0x00,0x00, //0x12~0x15,width:480
0x10,0x01,0x00,0x00, //0x16~0x19,height:272
0x01,0x00, //0x1A~0x1B,planes:always"1"
//information header
0x10,0x00, //0x1C~0x1D,bits per pixel:16bits;
0x00,0x00,0x00,0x00, //0x1E~0x21,compression:no
0x02,0xFC,0x03,0x00, //0x22~0x25,bmp data size:480*2(R5G6B5)*272+2(result need Divisible by 4)
0x00,0x00,0x00,0x00, //0x26~0x29,HResolution
0x00,0x00,0x00,0x00, //0x2A~0x2D,VResolution
0x00,0x00,0x00,0x00, //0x2E~0x31,colors
0x00,0x00,0x00,0x00, //0x32~0x35,important
//Palettte: RGB555 :no
};
#endif
void LCDReadLine(u16 x,u16 y)
{
u32 i;
u16 colordata;
//u8 Rdata,Gdata;
u8 Bdata;
LcdSetArea(x,y,FRAMEBUFFER_COL-1,y);
WriteCommand(0x2E);
for(i = 0; i <FRAMEBUFFER_COL; i++)
{
colordata=ReadData();//LSB first
#ifdef RGB565_FILE
LCDReadDataBuffer[i*2]=(uint8_t)colordata;//LSB first
LCDReadDataBuffer[i*2+1]=(uint8_t)(colordata>>8);//LSB first
#else//RGB565==>RGB555
//Rdata=(uint8_t)(colordata>>11);//mask:0xF800
//Gdata=(uint8_t)((colordata&0x07E0)>>5);//mask:0x07E0
Bdata=(uint8_t)(colordata&0x001F);//mask:0x001F
LCDReadDataBuffer[i*2]=(uint8_t)(((colordata>>1)&0x03E0)|Bdata);//LSB first
LCDReadDataBuffer[i*2+1]=(uint8_t)(colordata>>9);//LSB first
#endif
}
}
/*******************************************************************************
LcdSaveBmp: 保存当前屏幕显示图像为BMP格式 输入:文件编号 返回值:0x00=成功
*******************************************************************************/
u8 LCDSaveBmp(u8 FileNum)
{
FIL bmpfile;
UINT bw;
FATFS fs;
FRESULT res;
u16 x=0, y=0;
u8 fileend[]={0x00,0x00,0x00,0x00};
// u8 testbuffer[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
// u8 i, j, k;
if(FileNum>20) //max filenum:21
{
FileNum=0x00;
}
//open file to write
res = f_mount(0, &fs);
res = f_open(&bmpfile, bmpname[FileNum], FA_OPEN_EXISTING | FA_WRITE); //open picture file
if(res != FR_OK)
{
res = f_open(&bmpfile, bmpname[FileNum], FA_CREATE_ALWAYS| FA_WRITE); //open picture file
}
if(res != FR_OK)
{
return res;
}
//header//FILE_HEADER_SIZE//BmpHeader
// f_write(fil, &c, 1, &bw); /* Write a byte to the file */
#ifdef RGB565_FILE
res = f_write(&bmpfile,BmpHeaderRGB565,RGB565_FILE_HEADER_SIZE,&bw);
if( res != FR_OK )
{
return res;
}
#else
res = f_write(&bmpfile,BmpHeader,FILE_HEADER_SIZE,&bw);
if( res != FR_OK )
{
return res;
}
#endif
//
// 0x0036; //data RGB555
// 0x0046; //data RGB565
for(y=0; y<272; y++)
{
x=0;
//LCDReadBuffer(x,y,480*2);//line 480*2//480*RGB
LCDReadLine(x,(271-y));//read data to LCDReadDataBuffer
res = f_write(&bmpfile,LCDReadDataBuffer,480*2,&bw);
if( res != FR_OK )
{
return res;
}
}
f_write(&bmpfile,fileend, 2, &bw); /* Write bytes to the file */
//read test
// res = f_lseek(&bmpfile, bmpfile.fsize); /* Move to end of the file to append data */
// res = f_lseek(&bmpfile, 0);/* Put file header */
/*
f_close(&bmpfile);
f_open(&bmpfile, bmpname[FileNum], FA_OPEN_EXISTING | FA_READ);
f_read(&bmpfile,LCDReadDataBuffer,LCD_READ_BUFFER_SIZE,&bw);
*/
//close open file
f_close(&bmpfile);
f_mount(0, NULL);
return FR_OK;
}