ESP32 GC9A01 测试代码

最近买了一个圆形的液晶显示屏,这个造型很特别是表盘的原型。它的主控是 GC9A01,我在网上搜了一圈没有找到现成的库于是只能自己研究。查看了一下 SPEC发现Command 之类的和ST7789基本相同,但是直接使用 ST7789 无法驱动显示。为此只能从头研究。

GC9A01 TFT LCD

测试使用 FireBeetle(ESP32),特别需要注意的是从资料上看这个屏幕只支持 3.3V,因此使用 UNO 这样的板子有烧毁的可能,我也并没有试验过UNO 这样的5V 的板子,具体建议询问卖家。

硬件连接:

FireBeetle(ESP32)GC9A01 
3.3VVCC 
GNDGND 
D9DC 
D2RST 
D10(预留给CS 未使用)  
 CSGND
 BLK未连接
 SCL 
 SDA 
ESP32和 GC9A01连接

最终只得从卖家的代码上修改。卖家提供了很多代码,最终选择从C51 代码上修改:

#include <SPI.h>
//画笔颜色
#define WHITE            0xFFFF
#define BLACK            0x0000   
#define BLUE             0x001F  
#define BRED             0XF81F
#define GRED             0XFFE0
#define GBLUE            0X07FF
#define RED              0xF800
#define MAGENTA          0xF81F
#define GREEN            0x07E0
#define CYAN             0x7FFF
#define YELLOW           0xFFE0
#define BROWN            0XBC40 //棕色
#define BRRED            0XFC07 //棕红色
#define GRAY             0X8430 //灰色
#define DARKBLUE         0X01CF //深蓝色
#define LIGHTBLUE        0X7D7C //浅蓝色  
#define GRAYBLUE         0X5458 //灰蓝色
#define LIGHTGREEN       0X841F //浅绿色
#define LGRAY            0XC618 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE        0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE           0X2B12 //浅棕蓝色(选择条目的反色)

#define TFT_DC D9
#define TFT_RST D2
#define TFT_CS D10

#define LCD_RES_Clr()  digitalWrite(TFT_RST,LOW)
#define LCD_RES_Set()  digitalWrite(TFT_RST,HIGH)

#define LCD_DC_Clr()  digitalWrite(TFT_DC,LOW)
#define LCD_DC_Set()  digitalWrite(TFT_DC,HIGH)

#define u16 word
#define delay_ms delay
#define LCD_W 240
#define LCD_H 240

#if defined (SPI_HAS_TRANSACTION)
  static SPISettings mySPISettings;
#endif

/******************************************************************************
      函数说明:LCD写入命令
      入口数据:dat 写入的命令
      返回值:  无
******************************************************************************/
void LCD_WR_REG(byte c)
{
  LCD_DC_Clr();//写命令
  #if defined (SPI_HAS_TRANSACTION)
      SPI.begin();
      SPI.beginTransaction(mySPISettings);
      SPI.transfer(c);
      SPI.endTransaction();
  #endif
  LCD_DC_Set();
}
/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:  无
******************************************************************************/
void LCD_WR_DATA(u16 dat)
{
    #if defined (SPI_HAS_TRANSACTION)
      SPI.begin();
      SPI.beginTransaction(mySPISettings);
      SPI.transfer(dat>>8);
      SPI.transfer(dat);
      SPI.endTransaction();
  #endif
}
/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:  无
******************************************************************************/
void LCD_WR_DATA8(byte c)
{
  #if defined (SPI_HAS_TRANSACTION)
      SPI.begin();
      SPI.beginTransaction(mySPISettings);
      SPI.transfer(c);
      SPI.endTransaction();
  #endif
}

void LCD_Init(void)
{
  
  LCD_RES_Clr();//复位
  delay_ms(100);
  LCD_RES_Set();
  delay_ms(100);
  
  LCD_WR_REG(0xEF);
  LCD_WR_REG(0xEB);
  LCD_WR_DATA8(0x14); 
  
  LCD_WR_REG(0xFE);      
  LCD_WR_REG(0xEF); 

  LCD_WR_REG(0xEB); 
  LCD_WR_DATA8(0x14); 

  LCD_WR_REG(0x84);     
  LCD_WR_DATA8(0x40); 

  LCD_WR_REG(0x85);     
  LCD_WR_DATA8(0xFF); 

  LCD_WR_REG(0x86);     
  LCD_WR_DATA8(0xFF); 

  LCD_WR_REG(0x87);     
  LCD_WR_DATA8(0xFF);

  LCD_WR_REG(0x88);     
  LCD_WR_DATA8(0x0A);

  LCD_WR_REG(0x89);     
  LCD_WR_DATA8(0x21); 

  LCD_WR_REG(0x8A);     
  LCD_WR_DATA8(0x00); 

  LCD_WR_REG(0x8B);     
  LCD_WR_DATA8(0x80); 

  LCD_WR_REG(0x8C);     
  LCD_WR_DATA8(0x01); 

  LCD_WR_REG(0x8D);     
  LCD_WR_DATA8(0x01); 

  LCD_WR_REG(0x8E);     
  LCD_WR_DATA8(0xFF); 

  LCD_WR_REG(0x8F);     
  LCD_WR_DATA8(0xFF); 


  LCD_WR_REG(0xB6);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x20);

  LCD_WR_REG(0x36);
  LCD_WR_DATA8(0x08);


  LCD_WR_REG(0x3A);     
  LCD_WR_DATA8(0x05); 


  LCD_WR_REG(0x90);     
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x08); 

  LCD_WR_REG(0xBD);     
  LCD_WR_DATA8(0x06);
  
  LCD_WR_REG(0xBC);     
  LCD_WR_DATA8(0x00); 

  LCD_WR_REG(0xFF);     
  LCD_WR_DATA8(0x60);
  LCD_WR_DATA8(0x01);
  LCD_WR_DATA8(0x04);

  LCD_WR_REG(0xC3);     
  LCD_WR_DATA8(0x13);
  LCD_WR_REG(0xC4);     
  LCD_WR_DATA8(0x13);

  LCD_WR_REG(0xC9);     
  LCD_WR_DATA8(0x22);

  LCD_WR_REG(0xBE);     
  LCD_WR_DATA8(0x11); 

  LCD_WR_REG(0xE1);     
  LCD_WR_DATA8(0x10);
  LCD_WR_DATA8(0x0E);

  LCD_WR_REG(0xDF);     
  LCD_WR_DATA8(0x21);
  LCD_WR_DATA8(0x0c);
  LCD_WR_DATA8(0x02);

  LCD_WR_REG(0xF0);   
  LCD_WR_DATA8(0x45);
  LCD_WR_DATA8(0x09);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x26);
  LCD_WR_DATA8(0x2A);

  LCD_WR_REG(0xF1);    
  LCD_WR_DATA8(0x43);
  LCD_WR_DATA8(0x70);
  LCD_WR_DATA8(0x72);
  LCD_WR_DATA8(0x36);
  LCD_WR_DATA8(0x37);  
  LCD_WR_DATA8(0x6F);


  LCD_WR_REG(0xF2);   
  LCD_WR_DATA8(0x45);
  LCD_WR_DATA8(0x09);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x26);
  LCD_WR_DATA8(0x2A);

  LCD_WR_REG(0xF3);   
  LCD_WR_DATA8(0x43);
  LCD_WR_DATA8(0x70);
  LCD_WR_DATA8(0x72);
  LCD_WR_DATA8(0x36);
  LCD_WR_DATA8(0x37); 
  LCD_WR_DATA8(0x6F);

  LCD_WR_REG(0xED); 
  LCD_WR_DATA8(0x1B); 
  LCD_WR_DATA8(0x0B); 

  LCD_WR_REG(0xAE);     
  LCD_WR_DATA8(0x77);
  
  LCD_WR_REG(0xCD);     
  LCD_WR_DATA8(0x63);   


  LCD_WR_REG(0x70);     
  LCD_WR_DATA8(0x07);
  LCD_WR_DATA8(0x07);
  LCD_WR_DATA8(0x04);
  LCD_WR_DATA8(0x0E); 
  LCD_WR_DATA8(0x0F); 
  LCD_WR_DATA8(0x09);
  LCD_WR_DATA8(0x07);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x03);

  LCD_WR_REG(0xE8);     
  LCD_WR_DATA8(0x34);

  LCD_WR_REG(0x62);     
  LCD_WR_DATA8(0x18);
  LCD_WR_DATA8(0x0D);
  LCD_WR_DATA8(0x71);
  LCD_WR_DATA8(0xED);
  LCD_WR_DATA8(0x70); 
  LCD_WR_DATA8(0x70);
  LCD_WR_DATA8(0x18);
  LCD_WR_DATA8(0x0F);
  LCD_WR_DATA8(0x71);
  LCD_WR_DATA8(0xEF);
  LCD_WR_DATA8(0x70); 
  LCD_WR_DATA8(0x70);

  LCD_WR_REG(0x63);     
  LCD_WR_DATA8(0x18);
  LCD_WR_DATA8(0x11);
  LCD_WR_DATA8(0x71);
  LCD_WR_DATA8(0xF1);
  LCD_WR_DATA8(0x70); 
  LCD_WR_DATA8(0x70);
  LCD_WR_DATA8(0x18);
  LCD_WR_DATA8(0x13);
  LCD_WR_DATA8(0x71);
  LCD_WR_DATA8(0xF3);
  LCD_WR_DATA8(0x70); 
  LCD_WR_DATA8(0x70);

  LCD_WR_REG(0x64);     
  LCD_WR_DATA8(0x28);
  LCD_WR_DATA8(0x29);
  LCD_WR_DATA8(0xF1);
  LCD_WR_DATA8(0x01);
  LCD_WR_DATA8(0xF1);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x07);

  LCD_WR_REG(0x66);     
  LCD_WR_DATA8(0x3C);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0xCD);
  LCD_WR_DATA8(0x67);
  LCD_WR_DATA8(0x45);
  LCD_WR_DATA8(0x45);
  LCD_WR_DATA8(0x10);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x00);

  LCD_WR_REG(0x67);     
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x3C);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x01);
  LCD_WR_DATA8(0x54);
  LCD_WR_DATA8(0x10);
  LCD_WR_DATA8(0x32);
  LCD_WR_DATA8(0x98);

  LCD_WR_REG(0x74);     
  LCD_WR_DATA8(0x10); 
  LCD_WR_DATA8(0x85); 
  LCD_WR_DATA8(0x80);
  LCD_WR_DATA8(0x00); 
  LCD_WR_DATA8(0x00); 
  LCD_WR_DATA8(0x4E);
  LCD_WR_DATA8(0x00);         
  
  LCD_WR_REG(0x98);     
  LCD_WR_DATA8(0x3e);
  LCD_WR_DATA8(0x07);

  LCD_WR_REG(0x35); 
  LCD_WR_REG(0x21);

  LCD_WR_REG(0x11);
  delay_ms(120);
  LCD_WR_REG(0x29);
  delay_ms(20);
} 

/******************************************************************************
      函数说明:设置起始和结束地址
      入口数据:x1,x2 设置列的起始和结束地址
                y1,y2 设置行的起始和结束地址
      返回值:  无
******************************************************************************/
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
{
    LCD_WR_REG(0x2a);//列地址设置
    LCD_WR_DATA(x1);
    LCD_WR_DATA(x2);
    LCD_WR_REG(0x2b);//行地址设置
    LCD_WR_DATA(y1);
    LCD_WR_DATA(y2);
    LCD_WR_REG(0x2c);//储存器写
}

/******************************************************************************
      函数说明:在指定区域填充颜色
      入口数据:xsta,ysta   起始坐标
                xend,yend   终止坐标
                color       要填充的颜色
      返回值:  无
******************************************************************************/
void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
{          
  u16 i,j; 
  LCD_Address_Set(xsta,ysta,xend-1,yend-1);//设置显示范围
  for(i=ysta;i<yend;i++)
  {                               
    for(j=xsta;j<xend;j++)
    {
      LCD_WR_DATA(color);
    }
  }                   
}
void setup() {
  pinMode(TFT_CS,OUTPUT);
  digitalWrite(TFT_CS,LOW);
  pinMode(TFT_DC,OUTPUT);
    pinMode(TFT_RST,OUTPUT);

  mySPISettings = SPISettings(1000000, MSBFIRST, SPI_MODE0);
  LCD_Init();

}

void loop() {
  LCD_Fill(0,0,LCD_W,LCD_H,BLUE);
  LCD_Fill(0,0,LCD_W,LCD_H,WHITE);
  LCD_Fill(0,0,LCD_W,LCD_H,BRED);
  LCD_Fill(0,0,LCD_W,LCD_H,GRED);
  LCD_Fill(0,0,LCD_W,LCD_H,RED);
  LCD_Fill(0,0,LCD_W,LCD_H,MAGENTA);
  LCD_Fill(0,0,LCD_W,LCD_H,GREEN);
  LCD_Fill(0,0,LCD_W,LCD_H,CYAN);     
}

测试的内容是不断让屏幕变换颜色:

FillScreen 测试

《ESP32 GC9A01 测试代码》有4个想法

  1. void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
    {
    u16 i,j;
    LCD_Address_Set(xsta,ysta,xend-1,yend-1);//设置显示范围
    SPI.begin();
    SPI.beginTransaction(mySPISettings);
    for(i=ysta;i<yend;i++)
    {
    for(j=xsta;j<xend;j++)
    {
    SPI.transfer16(color);
    }
    }
    SPI.endTransaction();
    }
    这样写刷屏速度能提高十几倍

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注