zoukankan      html  css  js  c++  java
  • 【原理】从零编写ILI9341驱动全过程(基于Arduino)

    最近在淘宝入手了一块ILI9341彩色屏幕,支持320x240分辨率。之前一直很好奇这类单片机驱动的彩色屏幕的原理,就打算自己写一个驱动,从电流层面操控ILI9341屏幕。话不多说,我们开始吧( ̄▽ ̄)~*

    1.ILI9341芯片和ILI9341驱动板

    首先这里要明确两个概念,ILI9341芯片和ILI9341驱动板。

    ILI9341芯片是ilitek发布的液晶驱动芯片,是这个样子的:

    而淘宝上的ILI9341驱动板是把ILI9341芯片、屏幕和针脚焊接在一起的电路板,它可能是这个样子的:

    也可能是这个样子的:

     还可能是这个样子的:

    没错,不同的厂家可以制造不同形状,不同接口的ILI9341驱动板,但他们上面都有ILI9341芯片,所以我们可以用相同的方法操作它。

    2.如何操作它呢?

    这是ILI9341驱动板的背面,我在上面做了些标注,应该会方便理解些。我们只要控制这些针脚的通电与否(高电平与低电平),就能够获得操控这块屏幕的“完整权限”!那这些针脚的定义是什么呢?我们一个一个看:

    左上角有五个最重要的针脚,分别是LCD_RST、LCD_CS、LCD_RS、LCD_WR和LCD_RD:(直接用文字写不能冒号对齐,没办法,开个代码框( ̄▽ ̄)~*)

    LCD_RST : 即LCD Reset,用于在通电之后复位,初始化整个模块。
    
    LCD_CS  : 即LCD Chip Select,用于多个芯片之间的片选操作。由于这块驱动板只有一个可用的芯片,所以一般该针脚不通电。
    
    LCD_RS  : 又称D/CX信号线,用于切换写命令(Command)和写数据(Data),当对显示屏写命令(Command)时,应该让针脚不通电,当对显示屏写数据(Data)时,应该让针脚通电。
    
    LCD_WR  : 写使能。当LCD_WR不通电,并且LCD_RD通电时,数据传输方向为写入。
    
    LCD_RD  : 读使能。

    左下角的针脚负责供电,不细讲。

    右上角的LCD_D0到LCD_D7是数据脚,通过控制它的通电与否来传输8个比特,也就是8个0或1。这种方式可以传输一个最小值0,最大值255的数字,我们用它来传输所有命令和数据。

    右下角的SD_SS,SD_DI,SD_D0,SD_SCK适用于控制SD卡读写的,不属于ILI9341的范畴,我们先不讨论。

    那么,如何操作它呢?这张图能够很清楚的说明:(下面用拉低代表示不通电,拉高表示通电,这样术语会更加标准)

     

    • 单片机开机,ILI9341驱动板接收到电流,开始进入待命状态
    • 拉低LCD_CS片选信号,选择对ILI9341芯片发送命令
    • 通过拉高拉低LCD_D0到LCD_D7数据脚,来表示二进制数据
    • 拉低拉高LCD_RS针脚来告诉机器这是一个命令,还是一个数据
    • 拉低LCD_WR,进行写使能(可以理解为按下回车键,把LCD_D0到D7的数据发送出去)

    这就是发送一个命令或者数据的方法。二进制,十进制和十六进制的转换和表达先直接略过,如果要展开,那可能可以出一本书了( • ̀ω•́ )✧,关于LCD_D0到D7脚应该发送什么,ILITEK在设计ILI9341时就已经规定好了,中文文档在此:

    接下来,就是,愉快的,编码时间啦( • ̀ω•́ )✧!!!

    3.兼容性设定

    不知刚才你有没有注意到数据脚是从LCD_D2开始的?那是因为Arduino Uno开发板的第0和1脚是USB针脚,不能被使用,只能从第2个针脚开始设计:

    那我们在编程时要用到LCD_D0和LCD_D1时,就必须写成8和9。另外不同机器脚位也不一样,所以我用宏定义来简化程序:

    #define LCD_D0   8
    #define LCD_D1   9
    #define LCD_D2   2
    #define LCD_D3   3
    #define LCD_D4   4
    #define LCD_D5   5
    #define LCD_D6   6
    #define LCD_D7   7
    #define LCD_RD   A0
    #define LCD_WR   A1
    #define LCD_RS   A2
    #define LCD_CS   A3
    #define LCD_RST  A4

    这样即解决了LCD_D0和LCD_D1脚的问题,还搞定的不同开发板的兼容性问题。由于#define是在预编译阶段生成的,所以不会影响代码运行的速度。

    4.发送命令和数据

    调用这块屏幕的方法很明确,就是写入2进制数字。通过设计厂商提供的命令表发送相应的2进制命令和数据,实现操控。这样做的好处是无论你使用的是什么机器,什么驱动板,只要实现了LcdWriteCommand()和LcdWriteData()两个函数,就可以实现对屏幕的完全控制。

    你当然可以用最直接的办法去控制引脚,比如digitalWrite():

    void LcdWriteCommand(unsigned char d){
      //Write Command Mode On
      digitalWrite(LCD_RS,LOW);
      //Write Datas to LCD_D0 to LCD_D7
      digitalWrite(LCD_D0,d%2);
      d = d >> 1;
      digitalWrite(LCD_D1,d%2);
      d = d >> 1;
      digitalWrite(LCD_D2,d%2);
      d = d >> 1;
      digitalWrite(LCD_D3,d%2);
      d = d >> 1;
      digitalWrite(LCD_D4,d%2);
      d = d >> 1;
      digitalWrite(LCD_D5,d%2);
      d = d >> 1;
      digitalWrite(LCD_D6,d%2);
      d = d >> 1;
      digitalWrite(LCD_D7,d%2);
      d = d >> 1;
      //Enable Datas
      digitalWrite(LCD_WR,LOW);
      digitalWrite(LCD_WR,HIGH);
    }
    
    void LcdWriteData(unsigned char d){
      //Write Data Mode On
      digitalWrite(LCD_RS,HIGH);
      //Write Datas to LCD_D0 to LCD_D7
      digitalWrite(LCD_D0,d%2);
      d = d >> 1;
      digitalWrite(LCD_D1,d%2);
      d = d >> 1;
      digitalWrite(LCD_D2,d%2);
      d = d >> 1;
      digitalWrite(LCD_D3,d%2);
      d = d >> 1;
      digitalWrite(LCD_D4,d%2);
      d = d >> 1;
      digitalWrite(LCD_D5,d%2);
      d = d >> 1;
      digitalWrite(LCD_D6,d%2);
      d = d >> 1;
      digitalWrite(LCD_D7,d%2);
      d = d >> 1;
      //Enable Datas
      digitalWrite(LCD_WR,LOW);
      digitalWrite(LCD_WR,HIGH);
    }

    但是这样做的话,速度嘛。。。看看这个,你就不会想用digitalWrite了:

     单片机中,速度为王,我们还是直接改Register吧:

    void LcdWriteCommand(unsigned char d){
      //Write Command Mode On
      fastDigitalWriteLOW(LCD_RS);
      //Write Datas to LCD_D0 to LCD_D7
      PORTD = (PORTD & B00000011) | ((d) & B11111100); 
      PORTB = (PORTB & B11111100) | ((d) & B00000011); 
      //Enable Datas
      fastDigitalWriteLOW(LCD_WR);
      fastDigitalWriteHIGH(LCD_WR);
    }
    
    void LcdWriteData(unsigned char d){
      //Write Command Mode On
      fastDigitalWriteHIGH(LCD_RS);
      //Write Datas to LCD_D0 to LCD_D7
      PORTD = (PORTD & B00000011) | ((d) & B11111100);
      PORTB = (PORTB & B11111100) | ((d) & B00000011);
      //Enable Datas
      fastDigitalWriteLOW(LCD_WR);
      fastDigitalWriteHIGH(LCD_WR);
    }

    这段代码中,我用了宏定义来实现fastDigitalWriteHIGH()和fastDigitalWriteLOW(),这两个定义能避免函数的栈调用。其实用内联函数来写也可以实现:

    inline void fastDigitalWriteHIGH(int Pin){
      *(portOutputRegister(digitalPinToPort(Pin)))|=digitalPinToBitMask(Pin);
      return;
    }

    但我就是喜欢宏定义,而且宏定义行数少些。

    另外你可能会疑惑:什么是PORTB和PORTD?

    PORTB其实就是针脚8-13,PORTD其实就是针脚0-7:

     假如你有一个这样的二进制数:

    00000100

    把他转换成十进制:

    4     

    再把它赋值给PORTD

    PORTD = 4;

    你就会发现针脚2通电了(图中连接到左边第一个红色灯泡):

     这就是PORTD的真正意义,它使用一个从0到255的数,记录针脚0到7的通电情况。

    那我们为什么不用digitalWrite(),而是要用PORTB和PORTD呢?因为快啊( ̄▽ ̄)~*

    5.Enjoy!

    我们刚刚实现了LcdWriteCommand()和LcdWriteData()两个函数,现在,我们就可以实现对屏幕的完全控制了!

    首先,先运行一段初始化命令:

      //Initialize Data Pins
      pinMode(LCD_D0,OUTPUT);
      pinMode(LCD_D1,OUTPUT);
      pinMode(LCD_D2,OUTPUT);
      pinMode(LCD_D3,OUTPUT);
      pinMode(LCD_D4,OUTPUT);
      pinMode(LCD_D5,OUTPUT);
      pinMode(LCD_D6,OUTPUT);
      pinMode(LCD_D7,OUTPUT);
    
      //Initialize Command Pins
      pinMode(LCD_RD,OUTPUT);
      pinMode(LCD_WR,OUTPUT);
      pinMode(LCD_RS,OUTPUT);
      pinMode(LCD_CS,OUTPUT);
      pinMode(LCD_RST,OUTPUT);
      digitalWrite(LCD_CS,LOW);
      digitalWrite(LCD_RD,HIGH);
      digitalWrite(LCD_WR,LOW);
    
      //Reset
      digitalWrite(LCD_RST,HIGH);
      delay(5);
      digitalWrite(LCD_RST,LOW);
      delay(15);
      digitalWrite(LCD_RST,HIGH);
      delay(15);
    
      LcdWriteCommand(0xCB);
      LcdWriteData(0x39);
      LcdWriteData(0x2C);
      LcdWriteData(0x00);
      LcdWriteData(0x34);
      LcdWriteData(0x02);
    
      LcdWriteCommand(0xCF);
      LcdWriteData(0x00);
      LcdWriteData(0XC1);
      LcdWriteData(0X30);
    
      LcdWriteCommand(0xE8);
      LcdWriteData(0x85);
      LcdWriteData(0x00);
      LcdWriteData(0x78);
    
      LcdWriteCommand(0xEA);
      LcdWriteData(0x00);
      LcdWriteData(0x00);
     
      LcdWriteCommand(0xED);
      LcdWriteData(0x64);
      LcdWriteData(0x03);
      LcdWriteData(0X12);
      LcdWriteData(0X81);
    
      LcdWriteCommand(0xF7);
      LcdWriteData(0x20);
      
      LcdWriteCommand(0xC0);    //Power control 
      LcdWriteData(0x23);   //VRH[5:0] 
     
      LcdWriteCommand(0xC1);    //Power control 
      LcdWriteData(0x10);   //SAP[2:0];BT[3:0] 
    
      LcdWriteCommand(0xC5);    //VCM control 
      LcdWriteData(0x3e);   //Contrast
      LcdWriteData(0x28); 
     
      LcdWriteCommand(0xC7);    //VCM control2 
      LcdWriteData(0x86);   //--
     
      LcdWriteCommand(0x36);    // Memory Access Control 
      LcdWriteData(0x48);   
    
      LcdWriteCommand(0x3A);
      LcdWriteData(0x55);
    
      LcdWriteCommand(0xB1);
      LcdWriteData(0x00);
      LcdWriteData(0x18);
     
      LcdWriteCommand(0xB6);    // Display Function Control 
      LcdWriteData(0x08);
      LcdWriteData(0x82);
      LcdWriteData(0x27);
    
      LcdWriteCommand(0x11);    //Exit Sleep 
      delay(120);
            
      LcdWriteCommand(0x29);    //Display on 
      LcdWriteCommand(0x2c);

    这么多!不要怕,原样复制过去运行就好。这段命令是按照ILITEK设计文档中的规则发送的,用于初始化屏幕。运行完这段命令之后,我们就可以开始发自己的命令了。

    我们试着来清一下屏。清屏就是指定一块区域,然后给屏幕每一个像素点的颜色为白色,这样就好了。

    首先定义我们要写入的区域,这里就是从(0,0)写入到(239,319):

    int x1 = 0;
    int x2 = 239;
    int y1 = 0;
    int y2 = 319;

    接着通知屏幕我们要写入的区域的X坐标的起始、终止位置(命令0x2a):

    LcdWriteCommand(0x2a);

    然后发送X坐标的起始位置(x1),和X坐标的终止位置(x2)。我们的机器一次只能发送八位数字,但八位数字最大只能表示255,所以我们要分两次发送,先发送前八位,再发送后八位:

    LcdWriteData(x1>>8);
    LcdWriteData(x1);
    LcdWriteData(x2>>8);
    LcdWriteData(x2);

    Y坐标也是一样,只是把通知命令改成0x2b:

    LcdWriteCommand(0x2b);
    LcdWriteData(y1>>8);
    LcdWriteData(y1);
    LcdWriteData(y2>>8);
    LcdWriteData(y2);

    接着,我们发送开始写入的命令(0x2c),告诉屏幕我要开始发送像素了:

    LcdWriteCommand(0x2c);

    最后,发送所有像素的颜色数据(Data)。里面的RGB()宏定义是我在上一篇文章实现的。另外,因为是数据,所以我们要使用LcdWriteData():

    #define RGB(r,g,b) ((b&31)+((g&63)<<5)+((r&31)<<11))
    
    for(int i=y1;i<=y2;i++){
      for(int j=x1;j<=x2;j++){
        LcdWriteData(RGB(31,63,31)>>8);
        LcdWriteData(RGB(31,63,31));
      }
    }

    保存,下载。

    刷屏完整代码:

    // Breakout/Arduino UNO pin usage:
    // LCD Data Bit :   7   6   5   4   3   2   1   0
    // Uno dig. pin :   7   6   5   4   3   2   9   8
    // Uno port/pin : PD7 PD6 PD5 PD4 PD3 PD2 PB1 PB0
    // Mega dig. pin:  29  28  27  26  25  24  23  22
    #define LCD_D0   8
    #define LCD_D1   9
    #define LCD_D2   2
    #define LCD_D3   3
    #define LCD_D4   4
    #define LCD_D5   5
    #define LCD_D6   6
    #define LCD_D7   7
    #define LCD_RD   A0
    #define LCD_WR   A1
    #define LCD_RS   A2
    #define LCD_CS   A3
    #define LCD_RST  A4
    #define fastDigitalWriteHIGH(Pin) *(portOutputRegister(digitalPinToPort(Pin)))|=digitalPinToBitMask(Pin)  //Faster digitalWrite(Pin,HIGH);
    #define fastDigitalWriteLOW(Pin) *(portOutputRegister(digitalPinToPort(Pin)))&=~digitalPinToBitMask(Pin)  //Faster digitalWrite(Pin,LOW);
    #define RGB(r,g,b) ((b&31)+((g&63)<<5)+((r&31)<<11))
    
    void LcdWriteCommand(unsigned char d){
      //Write Command Mode On
      fastDigitalWriteLOW(LCD_RS);
      //Write Datas to LCD_D0 to LCD_D7
      PORTD = (PORTD & B00000011) | ((d) & B11111100); 
      PORTB = (PORTB & B11111100) | ((d) & B00000011); 
      //Enable Datas
      fastDigitalWriteLOW(LCD_WR);
      fastDigitalWriteHIGH(LCD_WR);
    }
    
    void LcdWriteData(unsigned char d){
      //Write Command Mode On
      fastDigitalWriteHIGH(LCD_RS);
      //Write Datas to LCD_D0 to LCD_D7
      PORTD = (PORTD & B00000011) | ((d) & B11111100);
      PORTB = (PORTB & B11111100) | ((d) & B00000011);
      //Enable Datas
      fastDigitalWriteLOW(LCD_WR);
      fastDigitalWriteHIGH(LCD_WR);
    }
    
    void setup(){
      //Initialize Data Pins
      pinMode(LCD_D0,OUTPUT);
      pinMode(LCD_D1,OUTPUT);
      pinMode(LCD_D2,OUTPUT);
      pinMode(LCD_D3,OUTPUT);
      pinMode(LCD_D4,OUTPUT);
      pinMode(LCD_D5,OUTPUT);
      pinMode(LCD_D6,OUTPUT);
      pinMode(LCD_D7,OUTPUT);
    
      //Initialize Command Pins
      pinMode(LCD_RD,OUTPUT);
      pinMode(LCD_WR,OUTPUT);
      pinMode(LCD_RS,OUTPUT);
      pinMode(LCD_CS,OUTPUT);
      pinMode(LCD_RST,OUTPUT);
      digitalWrite(LCD_CS,LOW);
      digitalWrite(LCD_RD,HIGH);
      digitalWrite(LCD_WR,LOW);
    
      //Reset
      digitalWrite(LCD_RST,HIGH);
      delay(5);
      digitalWrite(LCD_RST,LOW);
      delay(15);
      digitalWrite(LCD_RST,HIGH);
      delay(15);
    
      LcdWriteCommand(0xCB);
      LcdWriteData(0x39);
      LcdWriteData(0x2C);
      LcdWriteData(0x00);
      LcdWriteData(0x34);
      LcdWriteData(0x02);
    
      LcdWriteCommand(0xCF);
      LcdWriteData(0x00);
      LcdWriteData(0XC1);
      LcdWriteData(0X30);
    
      LcdWriteCommand(0xE8);
      LcdWriteData(0x85);
      LcdWriteData(0x00);
      LcdWriteData(0x78);
    
      LcdWriteCommand(0xEA);
      LcdWriteData(0x00);
      LcdWriteData(0x00);
     
      LcdWriteCommand(0xED);
      LcdWriteData(0x64);
      LcdWriteData(0x03);
      LcdWriteData(0X12);
      LcdWriteData(0X81);
    
      LcdWriteCommand(0xF7);
      LcdWriteData(0x20);
      
      LcdWriteCommand(0xC0);    //Power control 
      LcdWriteData(0x23);   //VRH[5:0] 
     
      LcdWriteCommand(0xC1);    //Power control 
      LcdWriteData(0x10);   //SAP[2:0];BT[3:0] 
    
      LcdWriteCommand(0xC5);    //VCM control 
      LcdWriteData(0x3e);   //Contrast
      LcdWriteData(0x28); 
     
      LcdWriteCommand(0xC7);    //VCM control2 
      LcdWriteData(0x86);   //--
     
      LcdWriteCommand(0x36);    // Memory Access Control 
      LcdWriteData(0x48);   
    
      LcdWriteCommand(0x3A);
      LcdWriteData(0x55);
    
      LcdWriteCommand(0xB1);
      LcdWriteData(0x00);
      LcdWriteData(0x18);
     
      LcdWriteCommand(0xB6);    // Display Function Control 
      LcdWriteData(0x08);
      LcdWriteData(0x82);
      LcdWriteData(0x27);
    
      LcdWriteCommand(0x11);    //Exit Sleep 
      delay(120);
            
      LcdWriteCommand(0x29);    //Display on 
      LcdWriteCommand(0x2c);
    
      //Set Writing Area
      int x1 = 0;
      int x2 = 239;
      int y1 = 0;
      int y2 = 319;
      LcdWriteCommand(0x2a);
      LcdWriteData(x1>>8);
      LcdWriteData(x1);
      LcdWriteData(x2>>8);
      LcdWriteData(x2);
      LcdWriteCommand(0x2b);
      LcdWriteData(y1>>8);
      LcdWriteData(y1);
      LcdWriteData(y2>>8);
      LcdWriteData(y2);
    
      //Start Writing
      LcdWriteCommand(0x2c);
      for(int i=y1;i<=y2;i++){
        for(int j=x1;j<=x2;j++){
          LcdWriteData(RGB(31,63,31)>>8);
          LcdWriteData(RGB(31,63,31));
        }
      }
    }
    
    void loop(){
      
    }

    接下来的路线就很简单了,把指定区域的命令(0x2a,0x2b,0x2c)分装成LcdOpenWindow()函数,再实现LcdFill()函数,一个完整的ILI9341驱动就完成了:

    #define LCD_D0   8
    #define LCD_D1   9
    #define LCD_D2   2
    #define LCD_D3   3
    #define LCD_D4   4
    #define LCD_D5   5
    #define LCD_D6   6
    #define LCD_D7   7
    #define LCD_RD   A0
    #define LCD_WR   A1
    #define LCD_RS   A2
    #define LCD_CS   A3
    #define LCD_RST  A4
    #define fastDigitalWriteHIGH(Pin) *(portOutputRegister(digitalPinToPort(Pin)))|=digitalPinToBitMask(Pin)  //Faster digitalWrite(Pin,HIGH);
    #define fastDigitalWriteLOW(Pin) *(portOutputRegister(digitalPinToPort(Pin)))&=~digitalPinToBitMask(Pin)  //Faster digitalWrite(Pin,LOW);
    #define RGB(r,g,b) ((b&31)+((g&63)<<5)+((r&31)<<11))
    
    void LcdWriteCommand(unsigned char d){
      //Write Command Mode On
      fastDigitalWriteLOW(LCD_RS);
      //Write Datas to LCD_D0 to LCD_D7
      PORTD = (PORTD & B00000011) | ((d) & B11111100); 
      PORTB = (PORTB & B11111100) | ((d) & B00000011); 
      //Enable Datas
      fastDigitalWriteLOW(LCD_WR);
      fastDigitalWriteHIGH(LCD_WR);
    }
    
    void LcdWriteData(unsigned char d){
      //Write Command Mode On
      fastDigitalWriteHIGH(LCD_RS);
      //Write Datas to LCD_D0 to LCD_D7
      PORTD = (PORTD & B00000011) | ((d) & B11111100);
      PORTB = (PORTB & B11111100) | ((d) & B00000011);
      //Enable Datas
      fastDigitalWriteLOW(LCD_WR);
      fastDigitalWriteHIGH(LCD_WR);
    }
    
    void LcdInit(void){
      //Initialize Data Pins
      pinMode(LCD_D0,OUTPUT);
      pinMode(LCD_D1,OUTPUT);
      pinMode(LCD_D2,OUTPUT);
      pinMode(LCD_D3,OUTPUT);
      pinMode(LCD_D4,OUTPUT);
      pinMode(LCD_D5,OUTPUT);
      pinMode(LCD_D6,OUTPUT);
      pinMode(LCD_D7,OUTPUT);
    
      //Initialize Command Pins
      pinMode(LCD_RD,OUTPUT);
      pinMode(LCD_WR,OUTPUT);
      pinMode(LCD_RS,OUTPUT);
      pinMode(LCD_CS,OUTPUT);
      pinMode(LCD_RST,OUTPUT);
      digitalWrite(LCD_CS,LOW);
      digitalWrite(LCD_RD,HIGH);
      digitalWrite(LCD_WR,LOW);
    
      //Reset
      digitalWrite(LCD_RST,HIGH);
      delay(5);
      digitalWrite(LCD_RST,LOW);
      delay(15);
      digitalWrite(LCD_RST,HIGH);
      delay(15);
    
      LcdWriteCommand(0xCB);
      LcdWriteData(0x39);
      LcdWriteData(0x2C);
      LcdWriteData(0x00);
      LcdWriteData(0x34);
      LcdWriteData(0x02);
    
      LcdWriteCommand(0xCF);
      LcdWriteData(0x00);
      LcdWriteData(0XC1);
      LcdWriteData(0X30);
    
      LcdWriteCommand(0xE8);
      LcdWriteData(0x85);
      LcdWriteData(0x00);
      LcdWriteData(0x78);
    
      LcdWriteCommand(0xEA);
      LcdWriteData(0x00);
      LcdWriteData(0x00);
     
      LcdWriteCommand(0xED);
      LcdWriteData(0x64);
      LcdWriteData(0x03);
      LcdWriteData(0X12);
      LcdWriteData(0X81);
    
      LcdWriteCommand(0xF7);
      LcdWriteData(0x20);
      
      LcdWriteCommand(0xC0);    //Power control 
      LcdWriteData(0x23);   //VRH[5:0] 
     
      LcdWriteCommand(0xC1);    //Power control 
      LcdWriteData(0x10);   //SAP[2:0];BT[3:0] 
    
      LcdWriteCommand(0xC5);    //VCM control 
      LcdWriteData(0x3e);   //Contrast
      LcdWriteData(0x28); 
     
      LcdWriteCommand(0xC7);    //VCM control2 
      LcdWriteData(0x86);   //--
     
      LcdWriteCommand(0x36);    // Memory Access Control 
      LcdWriteData(0x48);   
    
      LcdWriteCommand(0x3A);
      LcdWriteData(0x55);
    
      LcdWriteCommand(0xB1);
      LcdWriteData(0x00);
      LcdWriteData(0x18);
     
      LcdWriteCommand(0xB6);    // Display Function Control 
      LcdWriteData(0x08);
      LcdWriteData(0x82);
      LcdWriteData(0x27);
    
      LcdWriteCommand(0x11);    //Exit Sleep 
      delay(120);
            
      LcdWriteCommand(0x29);    //Display on 
      LcdWriteCommand(0x2c);
    }
    
    void LcdOpenWindow(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2){
      LcdWriteCommand(0x2a);
      LcdWriteData(x1>>8);
      LcdWriteData(x1);
      LcdWriteData(x2>>8);
      LcdWriteData(x2);
      LcdWriteCommand(0x2b);
      LcdWriteData(y1>>8);
      LcdWriteData(y1);
      LcdWriteData(y2>>8);
      LcdWriteData(y2);
      LcdWriteCommand(0x2c);
    }
    
    void LcdFill(int x,int y,int width,int height,unsigned int color)
    {
      LcdOpenWindow(x,y,x+width-1,y+height-1);
      for(int i=y;i<y+height;i++){
        for(int j=x;j<x+width;j++){
          LcdWriteData(color>>8);
          LcdWriteData(color);
        }
      }
    }
    
    void setup(){
      LcdInit();
      LcdFill(0,0,239,319,RGB(31,63,31));
      LcdFill(10,10,100,100,RGB(31,0,0));
      LcdFill(20,20,110,110,RGB(0,63,0));
      LcdFill(30,30,120,120,RGB(0,0,31));
    }
    
    void loop(){
      
    }

     都看到这了,还不点个赞吗?(✪ω✪)

  • 相关阅读:
    IOS Core Animation Advanced Techniques的学习笔记(五)
    IOS Core Animation Advanced Techniques的学习笔记(四)
    IOS Core Animation Advanced Techniques的学习笔记(三)
    IOS Core Animation Advanced Techniques的学习笔记(二)
    IOS Core Animation Advanced Techniques的学习笔记(一)
    NSString / NSMutableString 字符串处理,常用代码 (实例)
    UITextField的总结
    iOS7中计算UILabel中字符串的高度
    EventUtil 根据IE自动适配事件
    sql 添加修改说明
  • 原文地址:https://www.cnblogs.com/SirJackie/p/12180140.html
Copyright © 2011-2022 走看看