嵌入式-图形-实验报告(共12页)

上传人:2127513****773577... 文档编号:58337338 上传时间:2022-02-27 格式:DOC 页数:13 大小:55.50KB
收藏 版权申诉 举报 下载
嵌入式-图形-实验报告(共12页)_第1页
第1页 / 共13页
嵌入式-图形-实验报告(共12页)_第2页
第2页 / 共13页
嵌入式-图形-实验报告(共12页)_第3页
第3页 / 共13页
资源描述:

《嵌入式-图形-实验报告(共12页)》由会员分享,可在线阅读,更多相关《嵌入式-图形-实验报告(共12页)(13页珍藏版)》请在装配图网上搜索。

1、精选优质文档-倾情为你奉上图形用户接口1、 实验目的(1) 了解嵌入式系统图形界面的基本编程方法(2) 学习图形库的制作2、 实验原理(1) Frame Buffer 显示屏的整个显示区域,在系统内会有一段存储空间与之对应。通过改变该存储空间的内容达到改变显示信息的目的。该存储空间被称为Frame Buffer,或显存。显示屏上的每一点都与Frame Buffer里的某一位置对应。所以,解决显示屏的显示问题,首先要解决的是Frame Buffer的大小以及屏上的每一像素与Frame Buffer的映射关系。 影响空间大小的因素:由于Frame Buffer空间的计算大小是以屏幕的大小和显示模式

2、决定的,所以显示模式(单色或彩色)、显示屏的性能、显示的需要均会影响Frame Buffer空间的大小。另外显示屏还有单屏幕、双屏幕两种工作模式:单屏幕模式代表屏幕的显示范围是整个屏幕,只需一个Frame Buffer和一个通道;双屏幕模式则将整个屏幕划分为两个部分,这两个部分各自有Frame Buffer,且他们的地址无需连续,并同时具有两个各自独立的通道将Frame Buffer的数据传送到显示屏。显示操作及映射连续性:由于Frame Buffer通常就是从内存空间分配所得,并且他是有连续的字节空间组成,屏幕的显示操作通常是从左到右逐点像素扫描,从上到下逐行扫描,直到扫描到右下角,然后再折

3、返到左上角。又由于Frame Buffer里的数据是按地址递增的顺序被提取,所以屏幕上相邻的两像素被映射到Frame Buffer里是连续的,并且屏幕最左上角的像素对应Frame Buffer的第一空间单元,屏幕最右下角则对应最后一个单元空间。(2) Frame Buffer 与色彩 计算机反映自然界的颜色是通过RGB(Red-Green-Blue)值来表示的。如果要在屏幕某点显示某种颜色,则必须给出相应的RBG值。Frame Buffer是由所有像素的RGB值或RGB值的部分位所组成,本系统使用的16位/像素的模式下,Frame Buffer里的每个单元16位,每个单元代表一个像素的RGB值

4、,如下图D15D14D13D12D11D10D9D8D7D6D5D4D3D2D1D0RRRRRGGGGGGBBBBB有了以上的分析,就可以用下面的计算公式FrameBufferSize=Width * Height * Bitperpixel/8计算Frame Buffer的大小(以字节为单位)。(三)LCD控制器 在Frame Buffer与显示屏之间还需要一个中间件,该中间件负责从Frame Buffer里提取数据,进行处理,并传输到显示屏上。PXA270处理器内部集成LCDC,他提供了一个从PXA270处理器到显示屏的接口,LCDC的作用是将Frame Buffer里的数据传输到LCDC

5、的内部,然后经过处理,输出数据到LCD的输入引脚上。本实验系统使用的是16位TFT LCD,像素分辨率是640X480。(4) Frame Buffer 操作 Frame Buffer是一种驱动程序接口,这种接口将显示设备抽象为帧缓冲区。帧缓冲区为图像硬件设备提供了一种抽象化处理,它代表了一些视频硬件设备,允许应用软件通过定义明确的界面来访问图像硬件设备。于是,将帧缓冲区映射到进程地址空间之后,就可以直接进行读写和I/O控制等操作,而写操作可以立即显示在屏幕上。了解这个设备的参数可以通过FBIOGET_FSCREENINFO、FBIOGET_VSCREENINFO命令,从中可以获取显示器的色味

6、、分辨率等信息(vinfo.bits_per_pixel、vinfo.xres、vinfo.yres)。3、 实验内容(1) 实现基本画图功能 在Frame Buffer 基础上编写画点、画线的API函数,供应用程序调用,实现任意曲线的画线功能。(二)合理的软件结构 将调用设备驱动的基本API函数独立地构成一个函数库,为用户程序屏蔽底层硬件信息,直接提供一些简单的画图调用。函数库可以是独立编译后的“.o”文件或由归档管理器 ar 生成的库文件,或是将“.o”文件链接而承认那个的共享库“.so”。四、实验过程及相关程序(一)设备的初始化(LCD_INIT)Frame Buffer设备是/dev/

7、fb(它通常是/dev/fb0),对于该设备的初始化包括设备的打开,通过ioctl函数获得设备的相关信息,计算Frame Buffer缓冲区的大小以及使用mmap函数获取Frame Buffer缓冲区的首地址。具体程序如下:fd = open(/dev/fb0, O_RDWR);/打开设备 ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);/获取设备的相关信息 printf(%dx%d, %dbppn, vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );/打印相关信息 screensize = vinfo.xres * v

8、info.yres * vinfo.bits_per_pixel / 8; /计算缓冲区大小fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE,MAP_SHARED, fd, 0); /获取缓冲区首地址设备的初始化基本就结束了。(二)设备的关闭(LCD_END)设备关闭前获得的缓冲区应先被释放,接着关闭设备。具体程序如下:munmap(fbp,screensize); /缓冲区释放close(fd);/关闭设备(三)清屏操作(LCD_CLEAR)实验中的清屏操作,可通过memset(fbp,0,screensize)来实现,此时屏幕

9、为黑色。(4) 画图程序 1.画点程序(draw_point) 画点程序程序是整个画图实验的基础,其他的画图程序都是建立在画点程序上的。画点程序主要是解决两个问题:a、点的坐标;b、点的颜色。 点的位置的获取,我们只需要知道该点相对于缓冲区首地址的偏移量即可。例如要在(x,y)处显示一个点,可通过下面的方法获取其偏移量: offset = (x+y*vinfo.xres) * vinfo.bits_per_pixel/8;在这之前,我们最好先对x和y的范围进行一个判断,即x和y的值不满足LCD屏坐标范围时,则对改点不进行操作,方这便我们下面的编程。if(x639|y479)return;而对于

10、点得颜色,由于我们使用的LCD屏是16位色的,所以首先必须根据格式要求将RGB压缩到16位,再填充对应字节。相应的程序如下: color =(Red 11)|(Green8)&0xFF。到此为止,一个完整的画点程序就完成了。 其实,我们完全可以把画点的颜色也加入其中。在这里,我只列举了九种颜色,如果想要更多的颜色,可自行加入。int colour_choose(int num)int r,b,g;int col;switch(num)case 0:r=255;b=0;g=0;break; /redcase 1:r=255;b=255;g=0;break; /yellowcase 2:r=0;b

11、=255;g=0;break; /greencase 3:r=160;b=32;g=240;break; /purpiecase 4:r=184;b=143;g=143;break; /rosecase 5:r=0;b=0;g=255;break; /bluecase 6:r=25;b=15;g=80;break; /case 7:r=255;b=255;g=255;break; /writecase 8:r=0;b=0;g=0;break; /blackcol=(r11)|(g=y2)for(i=y2;i=y1;i-) draw_point(x1,i,m);else for(i=y1;i=x

12、2)for(i=x2;i=x1;i-) draw_point(y1,i,m);else for(i=x1;i 1 | j -1)j=(float)(x2-x1)/(float)(y2-y1); if(y1y2) for(i=y1;i=y2;i-) draw_point(int)(i-y1)*j+x1),i,m); else if(x1x2) for(i=x1;i=x2;i-) draw_point(i,(int)(i-x1)*j+y1),m); 3.画圆程序(draw_circle)画圆程序其实也是来自于画点程序,一个圆由1000个点组成,而这1000个点正好满足同一个圆方程,这样由于各个点间

13、隔非常小,所有看上去就是一个完整的圆了。相应的程序如下:void draw_circle(int R,int x0,int y0,int m) int x,y,i;for(i=0;i1000;i+) x=R*sin(2*PI/1000*i)+x0; y=R*cos(2*PI/1000*i)+y0; draw_point(x,y,m); 画实心圆可以由上面的画圆程序得到,我们可以用一个for循环将圆的半径由0递增到所需要的实心圆半径R,这样一个半径为R的实心圆就能得到了。不过我们上面已经提到了,所画的圆其实是由1000个点组成的,说白了,它其实并不是一个真正的圆,这样,当我们将大量的圆和在一起组

14、成一个实心圆时,实心圆内部会出现很多中心对称的黑色点,这其实就是由于一些点断断续续没有被着色到而造成的。有一个改进的方法就是,我们先选定实心圆的范围,再一个一个判断屏幕上的点是否落在这个范围之内,如果是,则对其着色,反之则放弃着色。不过这必须对屏幕上所有的点都进行判断,工作量大,所以本程序还有待提高。相应的程序如下:void draw_shi_circle(int R,int x0,int y0,int m) int x,y;for(x=0;x=vinfo.xres;x+)for(y=0;yvinfo.yres;y+)if(x-x0)*(x-x0)+(y-y0)*(y-y0)=R*R)draw

15、_point(x,y,m); 4.画旋转五角星程序(draw_star)画五角心其实就是先求出五角星五个角所相对应的坐标值,再把这些点连接起来。而让五角星旋转的话,我们只要让这五个点沿着一个角度偏移就可以了,期间再延迟一段时间并刷一下屏即可。相应的程序如下:void draw_star(int l, int x0, int y0) float x1, y1; float x2, y2; float x3, y3; float x4, y4; float x5, y5; int i; for(i=0;i=0;j-)for(i=0;i640;i+)y=j*sin(PI*i/80)+240;draw

16、_point(i,y,m);usleep(10000);lcd_clear(); 6.画正十二边形(draw_dodecagon)这个程序是实现画正十二边形,由于我准备能在屏幕上模拟一个钟表,这个十二边形的每个顶点正好是12个整点值。相应程序如下:void draw_dodecagon(int x0,int y0,int R,int m)int x12,y12;int i=0;for (i=0;i12;i+)xi = x0 + R*cos(i*PI/6);yi = y0 + R*sin(i*PI/6);for (i=0;i11;i+)draw_line(xi,yi,xi+1,yi+1,m);d

17、raw_line(x11,y11,x0,y0,m); 7画钟表程序(draw_clock) 其实这个程序本身并不烦,我先在屏幕上画了一个实心圆,用于做钟表的表盘。然后再调用划线函数,画三条直线,不过三条直线的长度各不相同,分别做时针、分针和秒针,并且它们都延时一段时间然后移动到下一个位置。同时,它们原来的位置会被和表盘相同颜色的直线盖住。这样,我们就会看到一个时钟显示在屏幕上。具体程序如下:void draw_clockline(int x0,int y0)int clock_x_miao,clock_y_miao,clock_x_fen,clock_y_fen,clock_x_shi,clo

18、ck_y_shi,i;int l=180;for(i=0;i3600;i+)clock_x_fen=x0+l*sin(i*PI/1800)/1.2;clock_y_fen=y0-l*cos(i*PI/1800)/1.2;clock_x_shi=x0+l*sin(i*PI/)/1.5;clock_y_shi=y0-l*cos(i*PI/)/1.5;clock_x_miao=x0+l*sin(i*PI/30);clock_y_miao=y0-l*cos(i*PI/30);draw_line(x0,y0,clock_x_shi,clock_y_shi);draw_line(x0,y0,clock_x

19、_miao,clock_y_miao);draw_line(x0,y0,clock_x_fen,clock_y_fen);usleep();draw_line_one(x0,y0,clock_x_miao,clock_y_miao);draw_line_one(x0,y0,clock_x_fen,clock_y_fen);draw_line_one(x0,y0,clock_x_shi,clock_y_shi);void draw_clock()draw_shi_circle(190,320,240);draw_dodecagon(320,240,200);由于这个程序是一个死循环,所以最好在后

20、台操作。但是如果把程序送到后台时,键盘输入就会不起作用。因此,我并没有把这段程序放到动态库之中。但是,在之前的调试中,这个程序能够显示,并且达到了我想要的效果。 8.主函数(main)由于我们所需要的画图程序以及设备驱动程序等都已经在子函数中给出了,所以主函数的任务就是调用子函数来实现相应的功能。在这里,为了能够将子函数的功能一一显示出来,我在这里用了一个switch的结构,我们在键盘上输入0-5之间的任意数字,主函数就做出相应的选择,LCD屏上也会出现相应的图形,当输入数字为9时,程序结束。当输入完成0-5之间的选择后,此时,我们就可以输入相应图形的信息,比如画圆时,我们就输入圆的半径和圆心

21、得位置,划线则输入直线的两个端点。最后,我们再输入0-8之间的一个数,完成颜色的选择。这样,整个程序就完成了。我们可以实现图形形状可选,所在位置可选,颜色可选等功能。功能相对比较强大。相应的程序如下:int main()int c=0;int x1=0,x2=0,y1=0,y2=0,r=0,m=0;lcd_init();while(c!=9)scanf(%d,&c);switch(c)case 0:lcd_clear();printf(Draw the line :);scanf(%d %d %d %d %d,&x1,&y1,&x2,&y2,&m);draw_line(x1,y1,x2,y2,

22、m);break;case 1:lcd_clear();printf(Draw the line :);scanf(%d %d %d %d %d,&x1,&y1,&x2,&y2,&m);draw_line(x1,y1,x2,y2,m);break;case 2:lcd_clear();printf(Draw the circle :);scanf(%d %d %d %d ,&r,&x1,&y1,&m);draw_circle(r,x1,y1,m);break;case 3:lcd_clear();printf(Draw the solid_circle :);scanf(%d %d %d %d

23、 ,&r,&x1,&y1,&m);draw_shi_circle(r,x1,y1,m);break;case 4:lcd_clear();printf(Draw the zhenxianbo :);scanf(%d %d,&x1,&m);draw_zhenxian(x1,m);break;case 5:lcd_clear();printf(Draw the dodecagon :);scanf(%d %d %d %d ,&x1,&y1,&r,&m);draw_dodecagon(x1,y1,r,m);break;default:printf(Wrongn); (5)显示一幅图片图片有jpg、b

24、mp、tiff等格式,本实验中采用bmp格式的图片作为显示样本。采用bmp格式图片的原因如下:这种格式的图片包含的图像信息较丰富,几乎不进行压缩。图像信息包含三个方面:文件信息头、位图信息头、RGB颜色阵列。文件信息头和位图信息头分别占用了14、40个字节,RGB颜色阵列从第55个字节开始。因此只需要从第55个字节开始读取图片的颜色信息,并将其存储于内存空间中,再将存储的信息显示在显示屏上即可。但是有一个需要注意的地方是,图片也分成16位色和24位色的。对于这两种图片,显示的时候必须分开考虑。我们可以先通过一个函数来读取图片的信息,再进行下一步操作。具体程序如下:int show_bmp( c

25、har *bmpfile ) FILE *fp; int rc; int ciBitCount, ciWidth, ciHeight; int line_x, line_y; long int location = 0, BytesPerLine = 0; char tmp1024*10; fp = fopen(./hhh.bmp, rb ); if (fp = NULL) return( -1 ); rc = fread( &FileHead, sizeof(BITMAPFILEHEADER),1, fp ); if ( rc != 1) printf(read header error!n

26、); fclose( fp ); return( -2 ); if (memcmp(FileHead.cfType, BM, 2) != 0) printf(its not a BMP filen); fclose( fp ); return( -3 ); rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp ); if ( rc != 1) printf(read infoheader error!n); fclose( fp ); return( -4 ); ciWidth = (int) chartolong( Inf

27、oHead.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; printf(width=%d, height=%d, bitCount=%d, offset=%dn, ciWid

28、th, ciHeight, ciBitCount, (int)chartolong(FileHead.cfoffBits, 4); line_x = 0;line_y = 0;while(!feof(fp)PIXEL pix;unsigned short int tmp;rc = fread( (char *)&pix, 1, sizeof(unsigned short int), fp );if (rc != sizeof(unsigned short int) ) break; location = line_x * bits_per_pixel / 8 + (ciHeight - lin

29、e_y - 1) * xres * bits_per_pixel / 8;tmp=pix.red11 | pix.green6 | pix.blue;*(unsigned short int*)(fbp + location) = tmp; location = (line_x+line_y*vinfo.xres) * vinfo.bits_per_pixel/8; tmp =(r 11)|(g8)&0xFF;line_x+;if (line_x = ciWidth )line_x = 0;line_y+;if(line_y=ciHeight-1)break; fclose( fp ); re

30、turn( 0 );long chartolong( char * string, int length ) long number; if (length = 4) memset( &number, 0x00, sizeof(long) ); memcpy( &number, string, length ); return( number );这段源程序是从网上找的,然后再进修改,最终能把图片显示在液晶屏上。(五)将基本API函数独立的构成函数库1. 静态库的制作将所有的画图子程序放在一起(draw.c),将初始化程序、清屏程序和关闭设备程序放在一起(init.c),再执行以下操作:arm

31、-linux-gcc -c draw.carm-linux-gcc -c draw.c生成相应的.o文件,然后ar cq libjingtai.a draw.o init.o生成我们所需要的静态库,然后arm-linux-gcc -o main mian.c -ljingtai -L ./ -lm2. 动态库的制作 和静态库一样,先把程序拆成三部分(main.c、draw.c、init.c),再执行下列操作:arm-linux-gcc -o libff-1.0.so -shared draw.c init.c 生成一个名为 ff-1.0的动态库arm-linux-gcc -o main mai

32、n.c -lff-1.0 -L ./这样就可以生成一个可执行文件main。我们也可以通过ln -s libff-1.0.so libff.so 这个操作进行链接,以后我们访问libff.so就相当于访问我们生成的动态库。生成完动态库后,我们就可以打开试验箱了。但是在试验箱上运行时,直接执行它会报错,缺少 libgcc.so,所以我们必须找到这个链接,并且修改为可执行。有一点要注意,这个链接必须是arm的,而不是80386的。把这个链接加进去后,我们要把库的路径提供给可执行文件。export LD_LIBRARY_PATH=./。这样整个文件就可以执行了。(6) 实验总结 这个实验主要是考察我们

33、对Frame Buffer的理解与运用以及对API函数的建立。通过该实验,掌握了嵌入式系统图形界面编程的基本方法,了解了库函数的生成方法以及主函数在调用库函数时的注意事项。在本次实验中,也体会到了由于算法效率不高而带来的各种问题。合理的算法能节省大量的时间。虽然在这个实验上我们看不出什么效果,但是在以后开发大的项目的时候,合理的算法就至关重要了。这也告诉我们,在编程的时候不能一味盲目的去完成任务,而应该多考虑一下实现这个目的的方案,选择最好的,再去实施。 在最后阶段,我也熟悉到了bmp图片信息的构成方式以及在读取这些信息并显示在开发板显示屏上时应注意的地方。如果时间允许的话,我们完全可以加入多张图片,最后制作成一个小的PPT。这需要后期再进一步的研究。(七)参考文献 1、PXA-270 嵌入式系统 实验指导用书 南京大学电子科学与工程系 2、微处理器与嵌入式系统方元 彭成磊 编著 3、C程序设计(第三版) 谭浩强 编著 清华大学出版社专心-专注-专业

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!