微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 12864各种子程序,神程序

12864各种子程序,神程序

时间:10-02 整理:3721RD 点击:

玩转12864液晶显示图片,画点,画任意直线

通过上一篇的实验,相信大家都掌握了显示字符的基本用法。
下面我们来看一下12864液晶更高级的用法。
首先是它的绘图功能。
让我们先来显示一整副的图片吧,也就是128x64大小。
在使用绘图功能时,先要打开扩充指令集,然后再打开绘图功能。接着就是送数据显示了。这里我们首先要弄明白ST7920的显示坐标关系。其显示坐标如下。

file:///C:/Users/lenovo/AppData/Local/Temp/msohtml1/01/clip_image001.jpg

从图中可以看出,X方向共有8个字(16个字节)Y方向共有0~31 行 分为上下两个屏。
弄懂了之后我们就可以依照此坐标来显示一整屏的图片了。
随便用一个图片的提取转换软件,讲一副126X64大小的图片转换成字节数据,总共字节大小为128*64/8 = 1024个字节。

下面我们来看看这个显示整屏图像的函数
void v_Lcd12864DrawPicture_f( unsigned char code *pPicture )
{
    unsigned char i, j, k ;
    for( i = 0 ; i < 2 ; i++ )//分上下两屏写
    {
        for( j = 0 ; j < 32 ; j++ )//行
        {
           v_Lcd12864SendCmd_f( 0x80 + j ) ;//写Y坐标(第几行上写)
            if( i == 0)                   //写X坐标 (判断在那一屏上)
            {
               v_Lcd12864SendCmd_f( 0x80 ) ;
            }
            else
            {
               v_Lcd12864SendCmd_f( 0x88 ) ;
            }
            for( k = 0 ;k < 16 ; k++ )      //写一整行数据(一行共16个字节,合八个字符)
            {
               v_Lcd12864SendData_f( *pPicture++ ) ;
            }
        }
    }
    v_Lcd12864SendCmd_f( 0x30 ) ;//基本功能设置
}

看看效果图片如下:显示一个人的图像

file:///C:/Users/lenovo/AppData/Local/Temp/msohtml1/01/clip_image002.jpg

下面来看看如何在任意一个位置显示或者是擦除一个点

对于12864这种二值显示屏来说,其显示状态无外乎显示和不显示一个点这两种状态。而在任意位置画点,是我们随心所欲的画线,画圆,画矩形的等GUI函数的基础。
为了让这个位置有一个参考点,我们有必要定义一个坐标系
在这里,我定义的坐标系如下
0,0------------------------------------127,0
|                                                         |
|                                                         |
|                                                         |
|                                                         |
0,63----------------------------------127,63

0,0代表屏幕的左上角,127,63代表屏幕的右下角。
对于屏幕上面任意一个点,如果我们想要点亮它,必须先读出此点的状态,然后再修改该点,最后送出去,即 读----修改----写。按照这个步骤,然后再运用C语言中的位操作运算符 可以很方便的完成画点的函数。
由于画点函数涉及到读ST7920内部RAM的操作,因此,我们必须先要完成这个读数据的函数
具体实现过程如下:
unsigned char u8_Lcd12864ReadByte_f( void )
{
    unsigned char byReturnValue ;
    v_Lcd12864CheckBusy_f() ;
    io_LCD12864_DATAPORT = 0xff ;
    SET_DATA
    SET_READ
    CLR_EN
    SET_EN
    byReturnValue = io_LCD12864_DATAPORT ;
    CLR_EN

    return byReturnValue ;   
}

然后是画点的函数,其实现过程如下:

void v_Lcd12864DrawPoint_f( unsigned char X, unsigned char Y, unsigned charColor )
{
    unsigned char Row , Tier , Tier_bit    ;
    unsigned char ReadOldH, ReadOldL ;
    v_Lcd12864SendCmd_f( 0x34 ) ;
    v_Lcd12864SendCmd_f( 0x36 ) ;
    Tier = X >> 4 ;   
    Tier_bit = X & 0x0f ;
    if( Y < 32 )
    {
        Row = Y ;
    }
    else
    {
        Row = Y - 32 ;
        Tier += 8 ;
    }
    v_Lcd12864SendCmd_f( Row + 0x80 ) ;
    v_Lcd12864SendCmd_f( Tier + 0x80 ) ;
    u8_Lcd12864ReadByte_f() ;
    ReadOldH = u8_Lcd12864ReadByte_f() ;
    ReadOldL = u8_Lcd12864ReadByte_f() ;
    v_Lcd12864SendCmd_f( Row + 0x80 )    ;
    v_Lcd12864SendCmd_f( Tier + 0x80 ) ;
    if( Tier_bit < 8 )
    {
        switch( Color)
        {
            case 0 :ReadOldH &=( ~( 0x01 << ( 7 - Tier_bit ))) ; break ;
            case 1 :ReadOldH |= ( 0x01 << ( 7 - Tier_bit )) ; break ;
            case 2 :ReadOldH ^= ( 0x01 << ( 7 - Tier_bit ))    ; break ;
            default :break ;   
        }
        v_Lcd12864SendData_f( ReadOldH ) ;
        v_Lcd12864SendData_f( ReadOldL ) ;
    }
    else
    {
        switch(Color)
        {
            case 0 :ReadOldL &= (~( 0x01 << ( 15 - Tier_bit ))) ; break ;
            case 1 :ReadOldL |= ( 0x01 << ( 15 - Tier_bit ))    ; break ;
            case 2 :ReadOldL ^= ( 0x01 << ( 15 - Tier_bit )) ; break ;
            default :break ;
        }
        v_Lcd12864SendData_f( ReadOldH ) ;
        v_Lcd12864SendData_f( ReadOldL ) ;
    }
    v_Lcd12864SendCmd_f( 0x30 )    ;
}

有了画点的函数之后,一切似乎都变得简单了,因为点是一切复杂图形的最基本的组成单位。
下面我们就在这个画点函数的基础上,实现画水平线和垂直线的两个函数。
画水平线:
void v_Lcd12864DrawLineX_f( unsigned char X0, unsigned char X1, unsigned charY, unsigned char Color )
{    unsigned char Temp ;
    if( X0 > X1 )
    {
        Temp = X1 ;
        X1 = X0 ;
        X0 = Temp ;
    }
    for( ; X0 <= X1 ; X0++ )
    v_Lcd12864DrawPoint_f( X0, Y, Color ) ;   
}
画垂直线:
void v_Lcd12864DrawLineY_f( unsigned char X, unsigned char Y0, unsigned charY1, unsigned char Color )
{
    unsigned char Temp ;
    if( Y0 > Y1 )
    {
        Temp = Y1 ;
        Y1 = Y0 ;
        Y0 = Temp ;
    }
    for(; Y0 <= Y1 ; Y0++)
    v_Lcd12864DrawPoint_f( X, Y0, Color)    ;
}

下面我们就用以上两个画线函数,在液晶屏上面画一个表格出来
v_Lcd12864DrawLineX_f( 0, 127 , 0, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 7, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 15, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 23, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 31, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 39, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 47, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 55, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 0, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 15, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 31, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 47, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 63, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 79, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 95, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 111, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 127, 0 , 63, 1 ) ;

看看显示效果

file:///C:/Users/lenovo/AppData/Local/Temp/msohtml1/01/clip_image003.jpg
怎么样,你的实现了吗?
只能画水平线和垂直线似乎太简单和单调点了。
要是能在任意两点间画一条直线就好了,那样我们就可以做很多事情了。
下面就让我们去实现它!
在这里我们采用Bresenham画线算法,关于这个算法,网上有很多资料,请大家以它为关键字到网上去搜索,在这里就不啰嗦了。
下面是算法的具体实现过程:
void v_Lcd12864DrawLine_f( unsigned char StartX, unsigned char StartY, unsignedchar EndX, unsigned char EndY, unsigned char Color )
{
    int t, distance;      /*根据屏幕大小改变变量类型(如改为int型)*/
    int x = 0 , y = 0 , delta_x, delta_y ;
    char incx, incy ;

    delta_x = EndX - StartX ;
    delta_y = EndY - StartY ;

    if( delta_x > 0 )
    {
        incx = 1;
    }
    else if( delta_x == 0 )
    {
        v_Lcd12864DrawLineY_f( StartX,StartY, EndY, Color ) ;
        return ;
    }
    else
    {
        incx = -1 ;
    }
    if( delta_y > 0 )
    {
        incy = 1 ;
    }
    else if(delta_y == 0 )
    {
        v_Lcd12864DrawLineX_f( StartX, EndX,StartY, Color ) ;   
        return ;
    }
    else
    {
        incy = -1 ;
    }

    delta_x = ABS( delta_x );   
    delta_y = ABS( delta_y );
    if( delta_x > delta_y )
    {
        distance = delta_x ;
    }
    else
    {
        distance = delta_y ;
    }
    v_Lcd12864DrawPoint_f( StartX, StartY, Color );   
    /* Draw Line*/
    for( t = 0 ; t <= distance+1 ; t++ )
    {
        v_Lcd12864DrawPoint_f( StartX,StartY, Color ) ;
        x += delta_x ;
        y += delta_y ;
        if( x > distance )
        {
            x -=distance ;
            StartX +=incx ;
        }
        if( y > distance )
        {
            y -=distance ;
            StartY +=incy ;
        }
    }
}

老规矩,我们用这个函数随便画任意斜率的几条直线看看。
v_Lcd12864DrawLine_f( 0, 0, 127, 63, 1 ) ;
v_Lcd12864DrawLine_f( 0, 63, 127, 0 , 1 ) ;
v_Lcd12864DrawLine_f( 12, 0, 127, 63, 1 ) ;
v_Lcd12864DrawLine_f( 52, 63, 127, 0 , 1 ) ;
v_Lcd12864DrawLine_f( 32, 63, 98, 0, 1 ) ;
v_Lcd12864DrawLine_f( 67, 0, 127, 63 , 1 ) ;

下面是具体的效果图:
file:///C:/Users/lenovo/AppData/Local/Temp/msohtml1/01/clip_image005.jpg

要能画波形,有一点是至关重要重要的,那就是打点,所谓打点,就是能在指定的X,Y的坐标处打上一个小黑点,12864液晶的操作就像大多数16位以上的处理器一样是字节或字或双字操作的,不像51和彩色液晶一样的位操作,所以要在12864上打点,就必须用“与或”的方式。下面把打点的函数贴上,这是以前做温度波形显示的时候做的

/****************打点******************/
void point(uchar x,uchar y)
{
uchar y1,hang,lie,msb_data,lsb_data,temp=0x01;
if(y1!=y)
{
msb_data=0;
lsb_data=0;
}
y1=y;
if(y<32)
{
hang=0x80+y;
lie=0x80;
}
if(y>31)
{
hang=0x80+y-32;
lie=0x88;
}
if(y>63)//return;
{
  lcm_com(0x80);
  _nop_();
  hanzi("温度超出显示范围");
  while(1)
   flash();
}

lie=lie+x/16;

if(x%16==0)
{
  msb_data=0;
  lsb_data=0;
}  

if(x%16<8)
{
  msb_data=msb_data|(temp<<(7-x%16));
  lsb_data=0x00|lsb_data;
}//保留以前的数据,把第x个点亮
if(x%16==8)
{
  msb_data=msb_data|0x00;
  lsb_data=lsb_data|0x80;
}
if(x%16>8)    大于24小于32
{
  msb_data=msb_data|0x00;
  lsb_data=lsb_data|(temp<<(15-x%16));
}
lcm_com(0x34);//扩充指令集
lcm_com(hang);
lcm_com(lie);
lcm_dat(msb_data);
lcm_dat(lsb_data);
lcm_com(0x36);//绘图显示开
}
打点完成之后波形就相应的出来了,比如说要记录一个波形随时间变化,x坐标随着时间自动增加,x增加一个单位时相应y的值就得确定,在送个打点函数,波形就出来了。这是一种实时波形

还有一种波形,比如正弦,余弦,等等数学波形,可以添加math.h这个头文件。然后里面相应的函数得到x,y的关系,就能画出这个波形了,下面把正弦波的函数贴出来

/**********正弦波*********/
void fsin()
{
float x,y;
uchar x1,y1;
for(x=0;x<(4*3.1415);x+=0.1)
  {
   y=sin(x);
   x1=10*x;
   y1=31-(10*y+0.5);
   point(x1,y1);
  }
}

y1=31-(10*y+0.5);这条语句是对y值进行四舍五入!

在网上找了很久都没带字库12864画点波形显示程序,全是不带字库的,于是自己动手修改了一个。

只是在前一个驱动程序上加了俩子函数。

#include <reg52.h>
#include <intrins.h>
#include <math.h>
//------------定义接口-------------//
sbit RS=P2^5 ;
sbit RW=P2^6 ;
sbit E=P2^7 ;
sbit RES=P2^1 ;
#define Lcd_Bus P1
// P1 接 LCM
#define uchar unsigned char
#define FIRST_ADDR 0
//定义字符/汉字显示起始位置
/*------------------检查忙位-----------------------------*/
void chk_busy()
{
    RS=0 ;
    RW=1 ;
    E=1 ;
    Lcd_Bus=0xff ;
    while((Lcd_Bus&0x80)==0x80);
    E=0 ;
}
/*------------------延时子程序-----------------------------*/
void delay(unsigned int t)
{
    unsigned int i,j ;
    for(i=0;i<t;i++)
    for(j=0;j<10;j++);
}

/*------------------写命令到LCD------------------------------*/
void write_com(unsigned char cmdcode)
{
    chk_busy();
    RS=0 ;
    RW=0 ;
    E=1 ;
    Lcd_Bus=cmdcode ;
    delay(5);
    //------------------在数据写入的时候加入适当的延时
    E=0 ;
    delay(5);
}

/*-------------------写数据到LCD----------------------------*/
void write_data(unsigned char Dispdata)
{
    chk_busy();
    RS=1 ;
    RW=0 ;
    E=1 ;
    Lcd_Bus=Dispdata ;
    delay(5);
    //------------------在数据写入的时候加入适当的延时
    E=0 ;
    delay(5);
}
/*------------------初始化LCD屏--------------------------*/
void lcdreset()
{
    delay(2000);
    write_com(0x30);
    delay(10);
    //选择基本指令集
    write_com(0x30);
    //选择8bit数据流
    delay(5);
    write_com(0x0c);
    //开显示(无游标、不反白)
    delay(10);
    write_com(0x01);
    //清除显示,并且设定地址指针为00H
    delay(500);
    write_com(0x06);
    //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位
    delay(0);
}
/*------------------显示字符串--------------------------*/
void hzkdis(unsigned char code*s)
{
    while(*s>0)
    {
        write_data(*s);
        s++;
        delay(50);
    }
}
/*------------------首屏显示--------------------------*/
void ceshi()
{
    write_com(0x01);
    //清除显示,并且设定地址指针为00H
    delay(5);
   
    write_com(0x80);
    //第一行(如果是地址是:80H,即LCD的第一行的第一个位置显示)
    hzkdis("中国计量学院");
   
    write_com(0x90);
    //第二行(如果是地址是:90H,即LCD的第二行的第一个位置显示)
    hzkdis("光电学院");
   
    write_com(0x88);
    //第三行(如果是地址是:88H,即LCD的第二行的第一个位置显示)
    hzkdis("06光信2");
   
    write_com(0x98);
    //第四行(如果是地址是:98H,即LCD的第二行的第一个位置显示)
    hzkdis("测试程序");
}
//------------------清整个GDRAM空间----------------------------
void clrgdram()
{
    unsigned char x,y ;
    for(y=0;y<64;y++)
    for(x=0;x<16;x++)
    {
        write_com(0x34);
        write_com(y+0x80);
        //行地址
        write_com(x+0x80);
        //列地址
        write_com(0x30);
        write_data(0x00);
        write_data(0x00);
    }
}
//------------------------------------------------------------
void clrscreen()
{
    write_com(0x01);
    delay(10);
}
unsigned char ReadByte(void)
{
    unsigned char byReturnValue ;
    chk_busy();
    Lcd_Bus=0xff ;
    RS=1 ;
    RW=1 ;
    E=0 ;
    E=1 ;
    byReturnValue=Lcd_Bus ;
    E=0 ;
   
    return byReturnValue ;
}

//增加画点子程序
void DrawPoint(unsigned char X,unsigned char Y,unsigned char Color)
{
    unsigned char Row,Tier,Tier_bit ;
    unsigned char ReadOldH,ReadOldL ;
    write_com(0x34);
    write_com(0x36);
    Tier=X>>4 ;
    Tier_bit=X&0x0f ;
    if(Y<32)
    {
        Row=Y ;
    }
    else
    {
        Row=Y-32 ;
        Tier+=8 ;
    }
    write_com(Row+0x80);
    write_com(Tier+0x80);
    ReadByte();
    ReadOldH=ReadByte();
    ReadOldL=ReadByte();
    write_com(Row+0x80);
    write_com(Tier+0x80);
    if(Tier_bit<8)
    {
        switch(Color)
        {
            case 0 :
           ReadOldH&=(~(0x01<<(7-Tier_bit)));
            break ;
            case 1 :
           ReadOldH|=(0x01<<(7-Tier_bit));
            break ;
            case 2 :
            ReadOldH^=(0x01<<(7-Tier_bit));
            break ;
            default :
            break ;
        }
        write_data(ReadOldH);
        write_data(ReadOldL);
    }
    else
    {
        switch(Color)
        {
            case 0 :
            ReadOldL&=(~(0x01<<(15-Tier_bit)));
            break ;
            case 1 :
           ReadOldL|=(0x01<<(15-Tier_bit));
            break ;
            case 2 :
           ReadOldL^=(0x01<<(15-Tier_bit));
            break ;
            default :
            break ;
        }
        write_data(ReadOldH);
        write_data(ReadOldL);
    }
    write_com(0x30);
}
void main(void)
{
    uchar i,j,colour=1 ;
    // uint ADzhi;
    RW=0 ;
    lcdreset();
    ceshi();
    clrgdram();
    delay(5000);
    clrscreen();
    for(i=4;i<124;i++)
    {
         j=35-27*sin((i-4)*3.14/30);
        //正弦波显示
         DrawPoint(i,j,colour);
        
    }
    delay(5000);
    while(1);
   
}

LCD点阵12864画温度曲线

默认分类 2007-08-17 18:54:58 阅读454 评论1 字号:大中小

#include<reg51.h>
#include"LCD12864.h"
#include"zimo.h"
#include"LCD1602.h"
void hua_zuobiao(void);//画坐标
void delay1ms(uint k);//延时间
void TLC2543(void);//2543读数据子函数
void count_ad(void);//1602的显示
uchar code shuzi[]={0x00,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};//0--8
uchar code number[]={"0123456789"};
uchar      tab1[]={"  wendu=+49.99c"};//  9 10. 12 13
uchar code tab2[]={"  made of suwei "};
unsigned long int ad;
///////////////////TLC2543
sbit clk=P1^3;//时钟
sbit cs=P1^2;//1变0时TLC2543复位
sbit adtain=P1^1;//数据输入
sbit adtaout=P1^0;//数据输出
////////////////
void main(void)
{uchar x,y;//x页 y列
uchar i;
uint j;
uchar wendu=30,dp;//温度//曲线的点
///////////1602
init_1602();
gotoxy(1,0);
for(i=0;i<16;i++)write_LCD_data(tab1);
gotoxy(2,0);
for(i=0;i<16;i++)write_LCD_data(tab2);
///////////////12864LCD
initi_LCD();//
hua_zuobiao();//画坐标图
y=12;//从12列开始
while(1)
{ TLC2543();//2543读数据子函数
   count_ad();//lcd1602的更新显示
   delay1ms(1);
   j++;
   if(j>50){j=0;
     wendu=ad/100;//取温度的前2位
      x=(wendu-1)/8;
        x=6-x;
      dp=(wendu-1)%8+1;
   if(y<64){  set_adr(x,y);
           wdata(shuzi[dp],1,0);
      }
    else {   set_adr(x,y-64);
             wdata(shuzi[dp],0,1);
      }
   y++;//列
   if(y==128){y=12;//
        clear();//清屏
        hua_zuobiao();//画坐标图
        }
   }
}
}

////////////
/*i=0;
initi_LCD();
hua_zuobiao();//画坐标
set_adr(3,12);
y=3;c=13;
while(1)
  {i++;
   c++;
   if(i==8){i=0;
      y=y-1;
   if(y==0)y=7;
   temp=0xb8+y;
   wcode(temp,1,1);
   }
   if(c==64) set_adr(temp,0);
   if(c>=127)while(1);
   if(c>=64) wdata(shuzhi,0,1);
   else wdata(shuzhi,1,0);
   delay1ms(100);
  }
}*/
   /////////////
// }
//}
////1602的显示
void count_ad(void)
{uchar i;
uint temp;
temp=ad;
tab1[13]=number[temp%10];temp=temp/10;
tab1[12]=number[temp%10];temp=temp/10;
tab1[10]=number[temp%10];temp=temp/10;
tab1[9]= number[temp%10];
gotoxy(1,0);
for(i=0;i<16;i++)write_LCD_data(tab1);
}
//////////////////////////////////
void TLC2543(void)//2543读数据子函数
{uchar i;//输入数据为0x00//0x10为第一通道
ad=0;
clk=0;
cs=0;
for(i=0;i<12;i++)
{if(adtaout==1)ad=ad|0x01;//读出数据
  adtain=0;//写入数据
  clk=1;
  clk=0;
  ad<<=1;//左移一位
  }
  cs=1;
  ad>>=1;//数据存在ad里
  ad=(ad*1000)/819;//temp=(ad*5000)/4095;
}
///////////////////////////
void hua_zuobiao(void)//画坐标
{uchar j;
uint i;
  for(j=0;j<8;j++)//页码
   {set_adr(j,0);
  for(i=1;i<=64;i++){wdata(zuobiao[i+j*128],1,0);
         wdata(zuobiao[63+i+j*128],0,1);
        }
}
}
////////////////////////
void delay1ms(uint k)//延时间
{k=k*125;
while(--k);
}
////////////

  调用子程序

   #include<reg51.h>
#define _LCD12864_h
#define uchar unsigned char
#define uint unsigned int
void delay(uint k);//延时
void wcode(uchar com,uchar cs1,uchar cs2);//写指令
void wdata(uchar da,uchar cs1,uchar cs2);//写数据
void set_startline(uchar i);//起始行
void set_adr(uchar x,uchar y);//页值设置,起始列值函数
void clear(void);///clear清屏
void initi_LCD(void);//初始化LCD
//////////单片机与液晶显示的引脚连接/////////
//sbit RST=P2^2;
sbit CS2=P2^0;
sbit CS1=P2^1;
sbit  RS=P2^2;//或DI
sbit  RW=P2^3;
sbit   E=P2^4;
//P0口为数据口
//////////////////////////////
void initi_LCD(void)//初始化LCD
{ wcode(0x3f,1,1);//显示开//0x3e关
  set_startline(0);//起始行第0行
  clear();//清屏
}
///////////////////////
void delay (uint k)//延时
{
while(k--);
}

////////复位///////////
/*void reset()
{
RST=0;
delay(200);
RST=1;
delay(200);
}
*/
////////write code写指令///////
void wcode(uchar com,uchar cs1,uchar cs2)//写指令
{
CS1=cs1;
CS2=cs2;
RW=0;
RS=0;
P0=com;
E=0;
delay(10);
E=1;
delay(10);
E=0;
}
/////////write data写数据///////////////
void wdata(uchar da,uchar cs1,uchar cs2)//写数据
{
CS1=cs1;
CS2=cs2;
RW=0;
RS=1;
P0=da;
E=0;
delay(10);
E=1;
delay(10);
E=0;
}
////////////set start设置起始行/////////////
void set_startline(uchar i)//起始行。11A5A4A3A2A1A0  共有64行
{       //液晶显示器的最底层为第0行
i=0xc0+i;//此算法为把最顶层做为第一层
wcode(i,1,1);
}
///////////////////////////////
void set_adr(uchar x,uchar y)//页值设置,起始列值函数
{
x=x+0xb8;//行//页地址设置。10111A2A1A0 DDRAM的8行为一页,A0~A2为页码,LCD为64行8页
y=y+0x40;//列地址设置。01A5A4A3A2A1A0 两半屏分别有64列,A0~A5送入列地址计数器,
          //作为列(Y)地址指针。每读写一次其自动加一,指向下一列DDRAM单元
wcode(x,1,1);
wcode(y,1,1);
}
///////////clear清屏///////////////
void clear(void)///clear清屏
{
uchar i,loop;
for(i=0;i<8;i++)///循环页写0/////////
  {
   set_adr(i,0);//页码//行
   for(loop=0;loop<64;loop++)wdata(0x00,1,1);//列//左右屏幕同时写//
  }
}


 调用子程序

  #include<reg51.h>
#define _zimo_h
#define uchar unsigned char
#define uint unsignedint/////////////////////////////////////////////////////////////////////////
// 汉字字模表                                                         //
// 汉字库: 宋体16.dot 纵向取模下高位,数据排列:从左到右从上到下        //
//字节倒置
uchar code zuobiao[]={
/*--  调入了一幅图像:C:\Documents and Settings\Administrator\桌面\温度坐标.bmp --*/
/*--  宽度x高度=128x64  --*/
0x00,0x00,0x00,0x70,0x50,0xD0,0x00,0xF0,0x10,0xF0,0x00,0xFF,0x40,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0xC1,0x01,0xC1,0x00,0xC1,0x41,0xC1,0x00,0xFF,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0x01,0x07,0x00,0x07,0x04,0x07,0x00,0xFF,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x15,0x15,0x1F,0x00,0x1F,0x11,0x1F,0x00,0xFF,0x04,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x74,0x54,0x5C,0x00,0x7C,0x44,0x7C,0x00,0xFF,0x10,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0xF0,0x10,0xF0,0x00,0xFF,0x40,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x01,0x01,0x00,0xFF,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x44,0x7C,0x00,0x01,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0x01,0x01,0x7D,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x75,0x55,
0x5D,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x55,0x55,0x7D,0x01,0x01,0x01,0x01,0x01,
0x01,0x01,0x1D,0x11,0x7D,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x5D,0x55,0x75,0x01,
0x01,0x01,0x01,0x01,0x01,0x01,0x7D,0x55,0x75,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0x05,0x05,0x7D,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x7D,0x55,0x7D,0x01,0x01,0x01,
0x01,0x01,0x01,0x01,0x1D,0x15,0x7D,0x01,0x01,0x01,0x01,0x01,0x01,0x7D,0x01,0x7D,
0x45,0x7D,0x01,0x01,0x01,0x01,0x01,0x01,0x7D,0x01,0x01,0x7D,0x01,0x01,0x01,0x01,


};

  调用子程序

  #include <reg51.h>
#define  _lcd1602_h
#define uint unsigned int
#define uchar unsigned char
void delayus(uint k);//延时
void write_LCD_command(uchar command);//命令写入LCD
void write_LCD_data(uchar LCDdata);//数据写入LCD
void init_1602(void);//初始化LCD
void clear_LCD();//LCD清屏
void gotoxy(uchar x,uchar y);//光标在x行y列
sbit rs=P2^5;//指令寄存器的选择
sbit rw=P2^6;//数据写入/读出lcd
sbit en=P2^7;//始能端
//////////////////////////////////////////////////1
void write_LCD_command(uchar command)//命令写入LCD
{
rw=0;//写入LCM
rs=0;//指令寄存器
en=1;//始能端
P3=command;//写命令
delayus(20);//延时40*20us
en=0;//关闭始能端
rw=1;//读取LCM                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
}
void write_LCD_data(uchar LCDdata)//数据写入LCD//2
{
rw=0;
rs=1;
en=1;
P3=LCDdata;
delayus(1);//40us
en=0;
rw=1;
}
void init_1602(void)//初始化LCD/////.....3
{
   write_LCD_command(0x38);// 0x38 单行显示//8位传输
    write_LCD_command(0x0c);// 0x0C 屏幕开启//光标不出现//不闪烁
    //write_LCD_command(0x0e);// 0x0C 屏幕开启//光标出现//不闪烁
    //write_LCD_command(0x0f);// 0x0C 屏幕开启//光标出现 //闪烁
//write_LCD_command(0x0d);// 0x0C 屏幕开启//光标不出现 //闪烁
}
void clear_LCD()//LCD清屏......4
{
write_LCD_command(0x01);//0x01 LCD清屏
write_LCD_command(0x02);//0x02 光标回到左上角
}

voidgotoxy(uchar x,uchar y)//光标在x行y列.7
{
if(x==1)  
  write_LCD_command(128+y);//128=0b1000,0000
else
     write_LCD_command(192+y);//192=0b1100,0000
}

voiddelayus(uint k)//延时......8
{
k=10*k;//40us
while(k--);
}

              


Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top