液晶画图功能应用.doc_第1页
液晶画图功能应用.doc_第2页
液晶画图功能应用.doc_第3页
液晶画图功能应用.doc_第4页
液晶画图功能应用.doc_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

12864学习(控制器ST7920)在学习12864其他功能前先学习一下12864的几个基本函数void delay(uint x)/延时函数x=x*12;while(x-)_nop_();/包含在intrins.h头文件_nop_();_nop_();void write_lcd_cmd(uchar cmd)/写命令RS=0;RW=0;EN=1;P0=cmd;/delay(1);EN=0;delay(1);void write_lcd_date(uchar date)/写数据函数RS=1;RW=0;EN=1;P0=date;/delay(1);EN=0;delay(1);void display_pos(uchar x,uchar y)/设置显示地址,用于显示中文字时设计显示地址uchar pos;switch(x)case 0:pos=0x80;break;/当x为0指向第一行case 1:pos=0x90;break;/当x为1指向第二行case 2:pos=0x88;break;/当x为2指向第三行case 3:pos=0x98;break;/当x为3指向第四行default:pos=0x80; /x为其它值时指向第一行pos=pos+y;write_lcd_cmd(pos);/*=函数功能:读取12864液晶繁忙标志BF位状态BF=1繁忙,BF=0不忙注意:与读取数据不同读取繁忙标志位是是属于写指令,要将RS置低=*/void read_lcd_bf()uchar BF=1;P0=0xff;doRS=0;RW=1;EN=0;EN=1;_nop_();BF=P0;BF=BF7;while(BF);12864显示图片要让一个点有显示就要让相应的点置高电平。要想知道如何控制一个点的高低电平就要知道它的地址是怎样排列的。我们看着12864液晶是连在一起的一块屏幕,就会想当然的认为它的地址也是一直地增的,但是你错了。12864是分为上下两个半屏的。12864液晶模块显示地址如图所示。注意:12864显示分为上下两屏,而不是一个整屏。什么意思呢?就是说它的地址是分成两大部分(既上下两大部分)。如图,上半屏的水平地址X是从0x800x87并且它的每个水平地址都包含了十六个点的显示区(如图红色标注)。下半屏水平地址是从0x880x8f,而上下半屏的纵坐标Y都是从031。这个是我定义的坐标关系简图坐标对应关系简图向12864 GDROM写如数据来绘图的过程:1、关闭绘图显示功能2、先打开扩充指令功能3、连续写入X坐标地址,和y坐标地址(说明书上是写着先写X在写y坐标,但是程序是却是先写Y再写X坐标,否则会出错。还有这里写地址使用写命令函数不是用写数据函数)4、向GDROM 中写入数据5、打开绘图显示功能/*=函数功能:清除GDROM的内容,如果不清除会出现花屏现象清除方法:向GDROM中写入0x00来清除内容=*/void clear_gcrom()uchar i,j,k,lcd_x,lcd_y;lcd_x=0x80;lcd_y=0x80;write_lcd_cmd(0x34);/打开扩充指令关闭绘图显示(绘图指令为扩充指令,并且在绘图期间必须关闭绘图显示功能)for(i=0;i2;i+)/分为上下两半屏清除显示for(j=0;j32;j+)write_lcd_cmd(lcd_y+j);write_lcd_cmd(lcd_x);for(k=0;k16;k+)write_lcd_date(0x00);lcd_x=0x88;/将x指向下半屏write_lcd_cmd(0x36);/打开绘图指令write_lcd_cmd(0x30);/操作恢复为常用指令/*=函数功能:向12864中写入一幅图片函数参数:*p为指向图片数据的指针lcd_x为水平显示位置,lcd_y为垂直显示位置,函数将12864屏分成上下两屏写入,上半屏LCD_x=0x80,下半屏lcd_x=0x88=*/void write_image(uchar *p)uchar i,j,k,lcd_x,lcd_y;lcd_x=0x80;lcd_y=0x80;write_lcd_cmd(0x34);/打开扩充功能for(i=0;i2;i+)/分为上下两屏for(j=0;j32;j+)write_lcd_cmd(lcd_y+j);write_lcd_cmd(lcd_x);for(k=0;k16;k+)/写入显示数据write_lcd_date(*p+);lcd_x=0x88;/将x地址指向下半屏write_lcd_cmd(0x36);/打开绘图功能write_lcd_cmd(0x30);/操作恢复为常用指令12864画图功能如果你想在液晶上显示几条线的话用上面的画图方法可以实现,但是要画一条任意直线,而且还要让直线可以变化的话用上面的方法肯定不是最好的方法,因为你每一条线的数据都要事先保存起来,再调用。先不说程序存储空间会不够用,更重要的是相当麻烦。你是不是也想只要一种方法只要给出直线的起始和终点坐标就可以画出一条直线来呢?在学习画直线之前我们先来往12864任意点上画一个点。画一点很简单只要将相应点置高电平就可以了。注意在12864液晶相应点上画一点,在向12864中画点时先要读取出该地址上的数据,再在读取到的数据中加入该点的数据,如果不先读取如果以前那个地址就有显示的数据时,可能就会破坏那个地址的显示/*=函数功能;读取12864数据注意:读取数据时是在RS=1、RW=1、EN=1期间进行的。读数据一定要在EN为高电平期间进行。还有就是不要想当然的认为读数据指令要将RS置低,恰恰相反要将RS置高。=*/uchar read_lcd_date()uchar date;P0=0xff;RS=1;RW=1;EN=0;EN=1;date=P0;_nop_();EN=0;return date;/*=函数功能:在12864液晶相应点上画一点,在向12864中画点时先要读取出该地址上的数据,再在读取到的数据中加入该点的数据,如果不先读取如果以前那个地址就有显示的数据时,可能就会破坏那个地址的显示参数功能说明:x为水平方向上的坐标,y为垂直方向的坐标,color为所画点的颜色,0画白点,1画黑点,2使相应位颜色取反read_H,read_L分别用来保存从12864中读取到数据的高低字节数据=*/void write_dian(uchar x,uchar y,uchar color)uchar x_locate,y_locate;uchar x_bit;uchar read_H,read_L;x_locate=x/16;/求出要显示点在具体的哪一个地址上x_bit=x%16;/求出要显示点在具体在地址的哪一位上if(y32)/说明在屏的上半屏y_locate=y;elsey_locate=y-32;x_locate=x_locate+8;/将x_locate指向下半屏write_lcd_cmd(0x34);/写扩充命令write_lcd_cmd(y_locate+0x80);/写垂直方向地址write_lcd_cmd(x_locate+0x80);/写水平方向的地址read_lcd_bf();read_lcd_date();/空读一次12864的数据(一定要空读一次否则会出错)至于为什么要空读我也不是很清楚read_H=read_lcd_date();/连续读取相应地址高低字节的数据read_L=read_lcd_date();if(x_bit8)/判断x地址数据是在高字节还是低字节,x_bit8在高字节/为什么在高字节,应为地址为从左到右switch(color)case 0:read_H&=(0x01(7-x_bit);break;case 1:read_H|=(0x01(7-x_bit);break;case 2:read_H=(0x01(7-x_bit);break;default:break;write_lcd_cmd(y_locate+0x80);write_lcd_cmd(x_locate+0x80);write_lcd_date(read_H);write_lcd_date(read_L);elseswitch(color)case 0:read_L&=(0x01(15-x_bit);break;case 1:read_L|=(0x01(15-x_bit);break;case 2:read_L=(0x01x1)/当X0在X1后面时将X1作为起始点temp=x0;x0=x1;x1=temp;for( ;x0y1)/当y0在X1后面时将y1作为起始点temp=y0;y0=y1;y1=temp;for( ;y0y1;y0+)write_dian(x,y0,color);到这里我相信你以经可以灵活的画出直线和垂线了吧。在画直线之前先来学习一下直线的基本画法原理。在这里使用Bresenham算法。下面是我找到得几种直线画法的原理。由直线的斜率确定选择在x方向或y方向上每次递增(减)1个单位,另一变量的递增(减)量为0或1,它取决于实际直线与最近光栅网格点的距离,这个距离的最大误差为0.5。假定直线斜率k在01之间。此时,只需考虑x方向每次递增1个单位,决定y方向每次递增0或1。 设 直线当前点为(xi,y) 直线当前光栅点为(xi,yi)则 下一个直线的点应为(xi+1,y+k) 下一个直线的光栅点 或为右光栅点(xi+1,yi)(y方向递增量0) 或为右上光栅点(xi+1,yi+1)(y方向递增量1)记直线与它垂直方向最近的下光栅点的误差为d,有:d=(y+k)yi,且 0d1 当d0.5:下一个象素应取右光栅点(xi+1,yi) 当d0.5:下一个象素应取右上光栅点(xi+1,yi+1)如果直线的(起)端点在整数点上,误差项d的初值:d00,x坐标每增加1,d的值相应递增直线的斜率值k,即:dd + k。一旦d1,就把它减去1,保证d的相对性,且在0-1之间。令e=d-0.5,关于d的判别式和初值可简化成: e的初值e0= -0.5,增量亦为k; e0时,取当前象素(xi,yi)的右上方象素(xi+1,yi+1); e=0时,可任取上、下光栅点显示。Bresenham算法的构思巧妙:它引入动态误差e,当x方向每次递增1个单位,可根据e的符号决定y方向每次递增 0 或 1。 e0,y方向递增1 x方向每次递增1个单位,e = e + k因为e是相对量,所以当e0时,表明e的计值将进入下一个参考点(上升一个光栅点),此时须:e = e - 1通过(0,0)的所求直线的斜率大于0.5,它与x=1直线的交点离y=1直线较近,离y=0直线较远,因此取光栅点(1,1)比(1,0)更逼近直线;如果斜率小于0.5,则反之;当斜率等于0.5,没有确定的选择标准,但本算法选择(1,1)1、浮点型的算法x=xsy=ysx = xe -xsy = ye -ys/initialize e to compensate for a nonzero interceptError =y/x-0.5/begin the main loopfor i=1 to x WritePixel (x, y, value) if (Error 0) then y=y+1 Error = Error -1 end if x=x+1 Error = Error +y/xnext ifinish2整数Bresenham算法 上述Bresenham算法在计算直线斜率和误差项时要用到浮点运算和除法,采用整数算术运算和避免除法可以加快算法的速度。 由于上述Bresenham算法中只用到误差项(初值Error =y/x-0.5)的符号因此只需作如下的简单变换: NError = 2*Error*x即可得到整数算法,这使本算法便于硬件(固件)实现。(程序)o /Bresenhams integer line resterization algorithm for the first octal./The line end points are (xs,ys) and (xe,ye) assumed not equal. All variables are assumed integer./initialize variablesx=xsy=ysx = xe -xsy = ye -ys/initialize e to compensate for a nonzero interceptNError =2*y-x /Error =y/x-0.5/begin the main loopfor i=1 to x WritePixel (x, y) if (NError =0) then y=y+1 NError = NError 2*x /Error = Error -1 end if x=x+1 NError = NError +2*y /Error = Error +y/xnext ifinish接下来就开使画任意角度的直线了。/*=函数功能:判断整数的正负及是否为零函数说明:当形参X大于零返回1,等于零返回零,小于零返回-1.=*/uchar pan_duan_fu_hao(uchar x)if(x0)return 1;/当x大于零返回1else if(x=0)return 0;/当x为零返回0elsereturn -1;/当x小于零返回-1/*=函数功能:画一条任意斜率的直线函数思想:利用Bresenham画法基础上自己稍加改进。既当直线dydx时将y坐标依次加一(相当于将y轴于x轴互换)。这里选择的是浮点型的画圆方法。会减慢运算速度。也可使用整形的运算方法运算速度更快参数说明:start_x,start_y,end_x,end_y,分别为直线起始坐标和终点坐标,color为直线颜色。length为画点时循环的次数,falg为dy与dx的大小的标志,当dydx时flag置1.=*/void write_line(uchar start_x,uchar start_y,uchar end_x,uchar end_y,uchar color)uint i,length;float temp,dx,dy;char incx,incy,flag;dx=end_x-start_x;/求开始x坐标和结束X坐标的距离dy=end_y-start_y;/求开始y坐标和结束y坐标的距离incx=pan_duan_fu_hao(dx);/判断整数的正负及是否为零incy=pan_duan_fu_hao(dy);if(incx=0)/当x轴没有增加时画

温馨提示

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

评论

0/150

提交评论