LCD调试
1、 首先,驱动的移植。
涉及函数mx2fb.c , mxcfb_modedb.c, 修改一点设置情况,具体可参看 毋杰的“LCD的调试笔记”。然后编译内核,用secureCRT下载到开发板上,开机后先是白屏,一会左上角会显示一个小企鹅的logo 。
测试:在secureCRT窗口下,敲入命令 cp xxx.bin /dev/fb0 , 即可显示图片。(xxx.bin是所要显示图片的二进制文件,可以用Img2Lcd软件转换)
参考:linux_user_guide
2、 其次,应用程序编写。
框架:
int main(int argc,char *argv[])
{ int fbfd = 0;
long int screensize = 0;
/*打开设备文件*/
fbfd = open("/dev/fb0", O_RDWR);
if (fbfd < 0)
{ printf("Unable to open /dev/fb0\n");
return(1);
}
/*取得屏幕相关参数*/
ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo);
ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo);
vinfo.bits_per_pixel = 16; vinfo.yoffset = 0;
ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo);
/*计算屏幕缓冲区大小*/
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
/*通过mmap函数映射屏幕缓冲区到用户地址空间*/ fb_mem=(char*)mmap(0,screensize,PROT_READ|PROT_WRITE,MAP_SHARED, fbfd, 0);
if(fb_mem==NULL){
printf("mmap failed\n");
close(fbfd);
return -1;
}
/*下面可通过fbmem指针读写显示设备缓冲区*/
memset (fb_mem, 0x0, screensize);
printf(" show_bmp \n");
paint_Bmp24(width,height,gImage_flower24);
munmap(fb_mem,screensize); /*可用munmap函数删除显存区的数据*/
close(fbfd); /*关闭设备*/
return 0;
}
显示图片
A) 将图像文件转换成c数组(Img2Lcd软件),程序里直接调用。
16位真彩色 :Color= red<<11 |green<<6 | blue; //565格式
注意图片的尺寸和格式,24位真彩色或者16位真彩色的程序不同,而且24位真彩色的图片转换成16位的数组,显示的图片会出现水晕的模糊感觉。
24位真彩色 :
for (y = 0; y < height; y++)
for (x = 0; x < width; x++)
{
/* 从bmp文件中读出的图像数据连续的三个字节中第一个字节为蓝色分量 */
/* 第二个字节为绿色分量 第三个字节为红色分量 */
b = pDIBData[p] ; g = pDIBData[p + 1] ; r = pDIBData[p + 2];
/* RGB24转换为RGB565 */
/* 红色r占5为屏蔽低三位 绿色g占6为屏蔽低两位 蓝色b占5为屏蔽低三位 */
r = r & (~(0x07)); g = g & (~(0x03)); b = b & (~(0x7));
R = (unsigned short)r << 8;
G = (unsigned short)g << 3;
B = (unsigned short)b >> 3;
color = R | G | B;
/* ** 计算偏移量,最先读出的三个字节对应的是图像中的左下角的那个像素
** 最后三个字节对应图像 右上 角 的那个像素*/
location = x * (vinfo.bits_per_pixel / 8) + y * finfo.line_length;
*((unsigned short int*)(fb_mem + location)) = color;
p = p+3;
}
B) 程序中将.bmp图片文件解码,然后读入到lcd缓冲区中。
了解bmp图片的格式,文件头文件信息等。
//14byte
typedef struct
{
char cfType[2]; /* 文件类型, 必须为 "BM" (0x4D42)*/
char cfSize[4]; /* 文件的大小(字节) */
char cfReserved[4]; /* 保留, 必须为 0 */
char cfoffBits[4]; /* 位图阵列相对于文件头的偏移量(字节)*/
}__attribute__((packed)) BITMAPFILEHEADER; /* 文件头结构 */
//40byte
typedef struct
{
char ciSize[4]; /* size of BITMAPINFOHEADER */
char ciWidth[4]; /* 位图宽度(像素) */
char ciHeight[4]; /* 位图高度(像素) */
char ciPlanes[2]; /* 目标设备的位平面数, 必须置为1 */
char ciBitCount[2]; /* 每个像素的位数, 1,4,8或24 */
char ciCompress[4]; /* 位图阵列的压缩方法,0=不压缩 */
char ciSizeImage[4]; /* 图像大小(字节) */
char ciXPelsPerMeter[4];/* 目标设备水平每米像素个数 */
char ciYPelsPerMeter[4];/* 目标设备垂直每米像素个数 */
char ciClrUsed[4]; /* 位图实际使用的颜色表的颜色数 */
char ciClrImportant[4]; /* 重要颜色索引的个数 */
}__attribute__((packed)) BITMAPINFOHEADER; /* 位图信息头结构 */
步骤:
fp = fopen( bmpfile, "rb" );
fread( &FileHead, sizeof(BITMAPFILEHEADER),1, fp );
memcmp(FileHead.cfType, "BM", 2)
fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp );
ciWidth = (int) chartolong( InfoHead.ciWidth, 4 );
ciHeight = (int) chartolong( InfoHead.ciHeight, 4 );
ciBitCount = (int) chartolong( InfoHead.ciBitCount, 4 );
fseek(fp, (int)chartolong(FileHead.cfoffBits, 4), SEEK_SET);
BytesPerLine = (ciWidth * ciBitCount + 31) / 32 * 4;
pDIBData = (unsigned char *) malloc(ciWidth*ciHeight*3);
fread( pDIBData, ciWidth*ciHeight*3, 1, fp );
for (line_y = 0; line_y < ciHeight; line_y++)
for (line_x = 0; line_x < ciWidth; line_x++)
{
/* 从bmp文件中读出的图像数据连续的三个字节中第一个字节为蓝色分量 */
/* 第二个字节为绿色分量 第三个字节为红色分量 */
b = pDIBData[p] ; g = pDIBData[p + 1] ; r = pDIBData[p + 2];
/* RGB24转换为RGB565 */
/* 红色r占5为屏蔽低三位 绿色g占6为屏蔽低两位 蓝色b占5为屏蔽低三位 */
r = r & (~(0x07)); g = g & (~(0x03)); b = b & (~(0x7));
R = (unsigned short)r << 8;
G = (unsigned short)g << 3;
B = (unsigned short)b >> 3;
color = R | G | B;
/* 计算偏移量,最先读出的三个字节对应的是图像中的左下角的那个像素, 最后三个字节对应图像 右上 角 的那个像素 */
location = line_x * (vinfo.bits_per_pixel / 8) + (ciHeight - line_y - 1) * finfo.line_length;
*((unsigned short int*)(fb_mem + location)) = color;
p = p+3;
}
free(pDIBData);
调试中出现的问题及解决:
1、 图片本来是24位真彩色的,可是程序中按照16位真彩色来进行解码和读取,将.bmp图片解码显示时导致部分失真,显示结果似水晕的感觉;将图片转化为c数组,程序中调用的时候,只能显示部分图片,整体拉伸并且重叠。故首先确定好图片的格式和参数很重要。
2、 16位真彩色和24位真彩色的文件格式还是不一样的,计算color值时要注意。
16位: fread( (char *)&pix, 1, sizeof(unsigned short int), fp )
*(fb_mem + location) = pix.red<<11 | pix.green<<6 | pix.blue; //color
24位:fread( pDIBData, 3, 1, fp )
b = *pDIBData ; g = *(pDIBData + 1) ; r = *(pDIBData + 2);
r = r & (~(0x07)); g = g & (~(0x03)); b = b & (~(0x7));
R = (unsigned short)r << 8;
G = (unsigned short)g << 3;
B = (unsigned short)b >> 3;
color = R | G | B;
3、 了解了framebuffer的结构和读取程序的整体框架,图片的显示,主要就是对fb_mem进行存储操作,对fb_mem[]赋值就好。
4、 read( pDIBData, 3, 1, fp );这样每次读一个像素,图片显示的时候比较慢,可以看出刷屏的动作。若要使刷屏动作变快,则只需一次将图片像素信息全读出来,即fread( pDIBData, ciWidth*ciHeight*3, 1, fp ); 但是这样所需要的缓存明显变大好多。