[Principle] drive the whole process from zero to write ILI9341 (based on Arduino)

Taobao recently to start a piece ILI9341 color screen that supports a resolution of 320x240. Before always been curious about this kind of principle-driven single-chip color screen, I intend to write a driver, handling ILI9341 screen from the current level. Ado, here we go (¯ ▽ ¯) ~ *

1.ILI9341 chip and the drive plate ILI9341

Here we must first clear two concepts, ILI9341 chip and ILI9341 drive plate.

ILI9341 chip is released ilitek LCD driver chips, look like this:

And the drive plate ILI9341 Taobao is to ILI9341 chip, stitch welded together, and the screen board, it may look like this:

 

It may look like this:

 

 It might look like this:

 

Yes, different manufacturers can be manufactured in different shapes, different interfaces ILI9341 drive plate, but above all they ILI9341 chip, so that we can operate the same way.

2. How does it operate?

This is the back ILI9341 driver board, I made some mark on it, it should be easy to understand something. As long as we control these pins are energized or not (High and Low), will be able to gain control of this screen "full access"! So what is the definition of these pins it? We look at one by one:

The upper left corner there are five of the most important pins are LCD_RST, LCD_CS, LCD_RS, LCD_WR and LCD_RD :( can not write text directly aligned colon, no way to open a code box (¯ ▽ ¯) ~ *)

LCD_RST: i.e. LCD Reset, for resetting after power, initializes the entire module.

LCD_CS: i.e. LCD Chip Select, a chip select operation between the plurality of chips. Since this drive plate is only one available chip, it is generally not energized the pin.

LCD_RS: also known as D / CX signal line, for switching the write command (Command) and the write data (Data), the display screen when a write command (Command), the pin should not be energized so that, when the write of the display data (Data time), should be allowed to pin power.

LCD_WR: Write Enable. When LCD_WR not energized, and the energization LCD_RD, a write data transfer direction.

LCD_RD: Read Enable.

Pin power responsible for the lower left corner, do not go into detail.

右上角的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(){
  
}

 

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

Guess you like

Origin www.cnblogs.com/lyj00912/p/12180140.html