3dmark压力测试99%:玩转12864液晶:3串行驱动 -- 在路上

来源:百度文库 编辑:偶看新闻 时间:2024/04/27 19:10:20

标签: 12864  液晶  C8051F  ST7920  

玩转12864液晶:3串行驱动

 玩转12864液晶:3串行驱动

        驱动芯片是ST7920的12864液晶电路连接有两种,并行方式和串行方式。通常使用并行方式,但有时候为了节省I/O线,可以使用串行方式,串行方式的传输字节的速率会比并行的慢。

   

                                                                               串行连接时序图

 

/***********************************************************

函数名称:serial_write_byte

函数功能:负责串行写8个bit位

入口参数:dat 8bit

出口参数:无

备 注:

***********************************************************/

void serial_write_byte(unsigned char dat)

{

    unsigned char i;

              for(i=0;i<8;i++)

              {

                     if(dat&0x80)

                            LCD_SID = 1;

                     else

                            LCD_SID = 0;

                     LCD_SCLK = 0;                 //一个时钟周期

                     delay_1us();

                     LCD_SCLK = 1;

                     delay_1us();

                     LCD_SCLK = 0;

                     dat = dat << 1;

                     LCD_SID = 0; //

              }

}

 

串行数据传送共分三个字节完成 

第一字节 串口控制—格式 11111ABC

          A为数据传送方向控制 H表示数据从LCD 到 MCU L表示数据从 MCU到LCD

          B为数据类型选择 H表示数据是显示数据 L表示数据是控制指令

          C固定为 0

第二字节 (并行)8 位数据的高4 位—格式 DDDD0000

第三字节 (并行)8 位数据的低4 位—格式 0000DDDD

 

/***********************************************************

函数名称:LCD_write_byte

函数功能:写一个字节的数据到12864液晶,包括指令或数据

入口参数:RW、RS、W_data

出口参数:无

备 注:RW=1,从液晶读数据到MCU;RW=0,写一个数据到液晶;

   (一般RW都设为0,即只向液晶写数据,不读数据)

          RS=1,写入的是数据;RS=0,写入的是指令;

    一般模式:RW=0,RS=1;写数据

       RW="0",RS=0;写指令

***********************************************************/

void LCD_write_byte(unsigned char RW, unsigned char RS, unsigned char W_data)

{

    unsigned int H_data,L_data,S_ID = 0xf8;  //11111RWRS0

    if(RW == 0)                        //RW=0,MCU写一个数据到液晶;

      {

          S_ID &=~ 0x04;

      }

    else                    //RW=1,从液晶读数据到MCU

      {

         S_ID |= 0X04;

      }

    if(RS == 0)                      //RS=1,写入的是数据

      {

         S_ID &=~ 0x02;

      }

    else                      //RS=0,写入的是指令;

      {

         S_ID |= 0X02;

      }

    H_data = W_data;

    H_data &= 0xf0;           //屏蔽低4位的数据

    L_data = W_data;          //xxxx0000格式

    L_data &= 0x0f;           //屏蔽高4位的数据

    L_data <<= 4;             //xxxx0000格式

    LCD_CS = 1;

    serial_write_byte(S_ID);    //发送S_ID

    serial_write_byte(H_data);  //发送H_data

    serial_write_byte(L_data);  //发送L_data

    LCD_CS = 0;

}

 

 

      接着对12864进行初始化

/***********************************************************

函数名称:LCD_init

函数功能:12864液晶初始化

入口参数:dat 8bit

出口参数:无

备 注:

***********************************************************/

void LCD_Init(void)

{

  delay_1us();

  LCD_write_byte(0,0,0x30);     //功能设置 8位数据,基本指令

  delay_1us();

  LCD_write_byte(0,0,0x04);     //点设定:显示字符/光标从左到右移位,DDRAM地址加1

  delay_1us();

  LCD_write_byte(0,0,0x0C);  //显示设定:开显示,显示光标,当前显示位反白闪动

  delay_1us();

  LCD_write_byte(0,0,0x01);  //写指令:清除显示, 清DDRAM

  delay_1us();

  LCD_write_byte(0,0,0x02);  //写指令:DDRAM地址归位

  delay_1us();

  LCD_write_byte(0,0,0x80);  //写指令:设置DDRAM地址,把显示地址设为0X80,即为第一行的首位

  delay_1us();

}

 

   这个初始化话的过程可能与ST7920手册上的初始化流程不一样,至于为什么我也不知道,这个初始化参考了网上的程序,实验验证了行得通。

 

LCD12864的一些内部存储器

CGROMCharacter Generator ROM,内置8192个中文汉字(16*16),也就是说能显示4行每行8个汉字。这些汉字通过GB中文字型码表寻址。存储器只读不写。

HCGROMHalf CGROM,半宽字型产生只读存储器,里面存储了供我们调用的英文,数字以及符号共128个字符ASCII字符库(8*16)。同样只读不写。

CGRAMCharacter Generator RAM,字形产生随机存储器,12864允许我们自己自定义字符,CGRAM最多可以提高4组16*16的空间供我们存放自定义字符。这四组点阵空间的地址为0000H、0002H、0004H、0006H。通过写读CGRAM,实现特殊字符图形的显示。要注意的是,数据掉电消失,所以要显示自定义的字符,每次MCU上电都需要写一次CGRAM空间。

GDRAMGraphicDynamic RAM,动态图形随机存储器,用以存储供显示的图形。

 

DDRAMData DisplayRAM,数据显示随机存储器,即用来存放将被显示的字符数据。
ICON RAM(IRAM),图标随机存储器,用以存储将被显示的图标数据。

 

 

(1)显示中文字库汉字(CGROM)和英文字库(HCGROM)

     首先确定汉字显示坐标,中文字库的汉字都是16*16点阵的,所以128*64的液晶能分为四行,每行能显示8个汉字。

 

 

/***********************************************************

函数名称:LCD_setxy 

函数功能:设置显示汉字位置    X(1~16),Y(1~4)

入口参数:X(1~16),Y(1~4) 

出口参数:无

备 注:                x坐标

Line1 |  80H  81H  82H  83H  84H  85H  86H  87H

Line2 |  90H  91H  92H  93H  94H  95H  96H  97H

Line3 |  88H  89H  8AH  8BH  8CH  8DH  8EH  8FH

Line4 |  98H  99H  9AH  9BH  9CH  9DH  9EH  9FH

***********************************************************/

void LCD_setxy(unsigned char x,unsigned char y)

{

       switch(y)

       {

              case 1:

                     LCD_write_byte(0,0,0X7F+x);break;              //Line1

              case 2:

                     LCD_write_byte(0,0,0X8F+x);break;              //Line2

              case 3:

                     LCD_write_byte(0,0,0X87+x);break;              //Line3

              case 4:

                     LCD_write_byte(0,0,0X97+x);break;              //Line4

              default:break;

       }

}

 

 

     中文占用两个标准字符,编码方式按照GB中文字型码表,具体可以参考12864手册的附录,其实程序中也不需要自己对显示汉字先编码,直接把汉字赋值到字符串数组中即可,c编译器直接把汉字转化为汉字对应的GB码(16位)。英文和标点占用一个字节,编码方式按照ASCII码表,在程序中也不需要写ASCII吗,而是直接把英文和标点赋值到字符串里面即可。

 

(代码02H~7FH)

 

/***********************************************************

函数名称:LCD_WriteStr

函数功能:在指定位置显示字符串

入口参数:dis_addr_x————汉字显示X坐标(1~16)

          dis_addr_y————汉字显示Y坐标(1~4)

                str———————————显示字符串 中文占两个标准字符,英文和标点占一个字符

出口参数:无

备 注:

***********************************************************/

void LCD_WriteStr(unsigned char dis_addr_x,unsigned char dis_addr_y,char* str)

{

    unsigned char LCD_temp;

    LCD_setxy(dis_addr_x,dis_addr_y);

    LCD_temp=*str;

    while(LCD_temp != 0x00)           //显示字符串子程序,字符码为0时退出

    {

        LCD_write_byte(0,1,LCD_temp);

        LCD_temp=*(++str);

    } 

}

 

(2)显示自定义字形 (CGRAM)

 

/****************************************************************

函数名称:LCD_CharCGRAM

函数功能:写自定义字形16x16点阵数据

入口参数:CGRAMAdd——(0~3)CGRAM地址bit5~bit4

          *s—————————16x16点阵数据数组

出口参数:无

备 注:

格式说明:                                              *

//*     RS  RW  DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0  *

//*     0   0   0   1   0   AC5 AC4 AC3 AC2 AC1      *

//*     设定CGRAM位址到地址计数器AC                *

//*     确保CGRAM有效(扩展指令SR=0)              *

***********************************************************/

void LCD_CharCGRAM(unsigned char CGRAMAdd,unsigned char code *s)

{   unsigned char i;

    LCD_write_byte(0,0,0x34);                 //扩充指令集

    LCD_write_byte(0,0,0x02);                 //SR=0 激活CGRAM

    LCD_write_byte(0,0,0x30);                 //恢复为基本指令集

    LCD_write_byte(0,0,(CGRAMAdd<<4)|0x40);    //设置CGRAM地址

    for(i=0;i<16;i++)                                                       //写点阵数据

            { 

                  LCD_write_byte(0,0,((CGRAMAdd<<4)+i)|0x40);   //在相应CGRAM地址上写点阵数据

           LCD_write_byte(0,1,s[2*i]);               //先写高位(D15~d8)

                     LCD_write_byte(0,1,s[2*i+1]);                   //再写低位(D7~D0)

               }

}

 

 

        要注意的是CGRAM的B5~B4为所要存放自定义字型的地址,而CGRAM的B3~B0为点阵数据,先写高位点阵数据(8bit),再写低点阵数据(8bit)(MSB在前,LSB在后)。在字模提取软件v2.1中要设置“横向取模”,不选中“字节倒序”。

 

 

在主程序中调用:

LCD_CharCGRAM(3,CHAR1CGRAMTAB);      //装入自定义字符字符点阵

 

//3为CGRAM地址(B5-B4),对应的编码地址为0x0006

/*CGRAM中的自定义字符地址只能是0x0000、0x0002、0x0004、0x0006*/

//显示自定义符地址0x06

          LCD_setxy(2,2);

          LCD_write_byte(0,1,0x00);

          LCD_write_byte(0,1,0x06);

 

 

(3)显示自定义字形 (GDRAM)

     绘图显示RAM提供128*64个点阵。写入绘图RAM(GDRAM)的步骤如下:

①关闭绘图显示功能;

②(扩展扩展指令集)设置GDRAM垂直Y位置Y——(0~31);

③(扩展扩展指令集)设置GDRAM水平X位置X——(0~15);

④将D15~D8数据写入GDRAM中;

⑤将D15~D8数据写入GDRAM中;

⑥打开绘图显示功能。

 

要注意的是有些12864液晶的手册上写的是先设置水平地址,再设置垂直地址,这是不对的。一切以ST7920手册上为准。先写Y,再写X。

 

 

字模软件横向取模,不字节倒序。

 

/***********************************************************

函数名称:LCD_ImgDisplay

函数功能:全屏显示128*64个象素的图形

入口参数:unsigned char code *img 要显示的图形

出口参数:无

备 注:

//*液晶屏坐标说明:                                          *

//*_______________________________________________    *

//*     |(0,0)                                   (7,0) |       *

//*     |                                            |       *

//*     |                                            |       *

//*     |(0,31)                                  (7,31)|       *

//*     |(8,0)                                   (15,0)|       *

//*     |                                            |       *

//*     |                                            |       *

//*     |(8,31)                                 (15,31)|       *

//*     |________________________________________|       *

//                                                          *

******************************************************************/ 

void LCD_ImgDisplay(unsigned char code *img)  

{  

    unsigned char i,j;  

    LCD_Graph_Mode_Set(Graph_Mode_OFF);   //先关闭图形显示功能   

    for(j=0;j<32;j++)               //垂直坐标Y     

       {

          for(i=0;i<8;i++)                   //水平坐标X

          {                  

                  LCD_write_byte(0,0,0x80+j);   //(扩展扩展指令集)设置GDRAM垂直Y位置

                  LCD_write_byte(0,0,0x80+i);   //(扩展扩展指令集)设置GDRAM水平X位置         

            LCD_write_byte(0,1,img[j*16+i*2]);      //放入数据高字节   

            LCD_write_byte(0,1,img[j*16+i*2+1]);    //放入数据低字节   

         }  

     }

       for(j=32;j<64;j++)                  //垂直坐标Y

    {

           for(i=0;i<8;i++)              //水平坐标X

          {                         

       

                  LCD_write_byte(0,0,0x80+j-32); 

                  LCD_write_byte(0,0,0x88+i);      

            LCD_write_byte(0,1,img[j*16+i*2]);  

            LCD_write_byte(0,1,img[j*16+i*2+1]);  

         }  

     }             

    LCD_Graph_Mode_Set(Graph_Mode_ON);  //最后打开图形显示功能    

}

 

 

 

每一块12864都分为两个半屏,上下两半或者左右两半,我是用的12864是分为上下两半的,注意GDRAM水平位址和垂直位址的排列。