转帖玩转12864液晶:3串行驱动

    技术2022-05-20  49

    转自:http://blog.ednchina.com/tengjingshu/1394093/Message.aspx

    玩转12864液晶:3串行驱动

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

       

                                                                                   串行连接时序图

     

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

    函数名称:serial_write_byte

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

    入口参数: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表示数据从 MCULCD

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

              C固定为 0

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

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

     

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

    函数名称:LCD_write_byte

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

    入口参数:RWRSW_data

    出口参数:无

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

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

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

        一般模式:RW=0RS=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=0MCU写一个数据到液晶;

          {

              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最多可以提高416*16的空间供我们存放自定义字符。这四组点阵空间的地址为0000H0002H0004H0006H。通过写读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)

                   }

    }

     

     

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

     

     

    在主程序中调用:

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

     

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

    /*CGRAM中的自定义字符地址只能是0x00000x00020x00040x0006*/

    //显示自定义符地址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水平位址和垂直位址的排列。

     

    程序下载(C8051F320驱动12864液晶(ST7920))

     

     


    最新回复(0)