ST7789v是Sitronix公司研制的,用于驱动LCD的芯片,在市场上有很多TFT屏使用这款芯片驱动,虽然驱动芯片相同,但不同TFT厂家在设计接口时各有不同。一时兴起,研究了一下HC32L196芯片驱动ST7789v,经过一段时间的努力,在朋友们的支持下。对GPIO模拟SPI、硬件SPI、8位并口、16位并口四种接口形式进行了探索。记录下来,与朋友们分享。
1 ST7789v的接口
按照《ST7789v Datasheet》的描述,ST7789v的接口有以下几种:
- Parallel 8080-series MCU Interface (8-bit, 9-bit, 16-bit & 18-bit)
- 6/16/18 RGB Interface(VSYNC, HSYNC, DOTCLK, ENABLE, DB[17:0])
在《ST7789v Datasheet》的“6.2 Interface Logic Pins”中有详细的说明,不再赘述。这里有几点需要注意:
(1)TFT厂家提供的接口描述与《ST7789v Datasheet》里的可能不一致,特别是引脚名称,需要核对清除;
(2)TFT屏幕内的IM3是连接的高电平还是低电平,这直接约束可以使用哪些接口;
(3)并口引脚的线序必须与厂家核对清楚。
1.1 SPI接口的硬件连接
SPI接口使用的连线少,相对简单,这也是市面上这种屏多的原因吧。我实验的是4-line 8bit serial I/F 和4-line 8bit serial I/F Ⅱ,这两种接口在硬件连接上相近(IM3,它常常被TFT厂家在内部连好了,4-line 8bit serial I/F Ⅱ下的SDO我没有使用)。
连接图很简单,看端口定义更好些:
/*MCU连接ST7789V端口定义*/
#define LCD_CS_PORT GpioPortA
#define LCD_CS_PIN GpioPin4 //CS
#define LCD_DCX_PORT GpioPortA
#define LCD_DCX_PIN GpioPin5 //不同显示屏厂家标识不同,如:RS/SPISCL/SCK
#define LCD_SDA_PORT GpioPortA
#define LCD_SDA_PIN GpioPin7 //SDA/MOSI
#define LCD_WRX_PORT GpioPortA
#define LCD_WRX_PIN GpioPin3 //不同显示屏厂家标识不同,如:WR
/*ST7789 Reset控制端口定义*/
#define LCD_RESX_PORT GpioPortA
#define LCD_RESX_PIN GpioPin10 //不同显示屏厂家标识不同,如:RESET/RES
/**/
#define LCD_WRX(n) (n ? Gpio_SetIO(LCD_WRX_PORT, LCD_WRX_PIN):Gpio_ClrIO(LCD_WRX_PORT, LCD_WRX_PIN)) //1数据,0命令
1.2 Parallel接口的硬件连接
并口连线相对麻烦一些,特别是DB口,不同TFT厂家的标识不同,与芯片引脚并不对应,直接按照Datasheet调试会有问题,我就是因为这个浪费了好多时间。上代码:
/*MCU连接ST7789V端口定义*/
#define LCD_DB_PORT GpioPortB
#define LCD_DB0_PIN GpioPin0
#define LCD_DB1_PIN GpioPin1
#define LCD_DB2_PIN GpioPin2
#define LCD_DB3_PIN GpioPin3
#define LCD_DB4_PIN GpioPin4
#define LCD_DB5_PIN GpioPin5
#define LCD_DB6_PIN GpioPin6
#define LCD_DB7_PIN GpioPin7
#define LCD_DB8_PIN GpioPin8
#define LCD_DB9_PIN GpioPin9
#define LCD_DB10_PIN GpioPin10
#define LCD_DB11_PIN GpioPin11
#define LCD_DB12_PIN GpioPin12
#define LCD_DB13_PIN GpioPin13
#define LCD_DB14_PIN GpioPin14
#define LCD_DB15_PIN GpioPin15
#define LCD_CS_PORT GpioPortA
#define LCD_CS_PIN GpioPin4
#define LCD_DCX_PORT GpioPortA
#define LCD_DCX_PIN GpioPin5 //不同显示屏厂家标识不同,如:RS/SPISCL,
#define LCD_WRX_PORT GpioPortA
#define LCD_WRX_PIN GpioPin3
#define LCD_RDX_PORT GpioPortA
#define LCD_RDX_PIN GpioPin8
#define LCD_RESX_PORT GpioPortA
#define LCD_RESX_PIN GpioPin10 //不同显示屏厂家标识不同,如:RESET/RES
#define LCD_TE_PORT GpioPortC
#define LCD_TE_PIN GpioPin3 //TE,未使用。
#define LCD_CS(n) (n ? Gpio_SetIO(LCD_CS_PORT, LCD_CS_PIN) : Gpio_ClrIO(LCD_CS_PORT, LCD_CS_PIN))
#define LCD_DCX(n) (n ? Gpio_SetIO(LCD_DCX_PORT, LCD_DCX_PIN) : Gpio_ClrIO(LCD_DCX_PORT, LCD_DCX_PIN))
#define LCD_WRX(n) (n ? Gpio_SetIO(LCD_WRX_PORT, LCD_WRX_PIN) : Gpio_ClrIO(LCD_WRX_PORT, LCD_WRX_PIN))
#define LCD_RDX(n) (n ? Gpio_SetIO(LCD_RDX_PORT, LCD_RDX_PIN) : Gpio_ClrIO(LCD_RDX_PORT, LCD_RDX_PIN))
2 TFT复位HWReset
这是驱动ST7789v的第一步,复位正确与否直接决定ST7789v能否正常工作。在Datasheet中“7.4.5 Reset Timing”有详细描述,主要看TRW的时间,只要时间给够,基本不会有问题。网上的例程很多。延迟时间可以重新设置,实测并不需要代码中那么长的延时。
void LCD_HWReset(void)
{
Gpio_SetIO(LCD_RESX_PORT, LCD_RESX_PIN);
delay1ms(1);
Gpio_ClrIO(LCD_RESX_PORT, LCD_RESX_PIN);
delay1ms(50);
Gpio_SetIO(LCD_RESX_PORT, LCD_RESX_PIN);
Spi_SetCS(M0P_SPI0, TRUE);
delay1ms(120);
}
3 TFT初始化
对ST7789v的寄存器进行设置,使其工作在需要的状态。
void LCD_Init(en_original_location_t original)
{
//初始化LCD
LCD_WR_CMD(0x11);
delay1ms(120);
LCD_WR_CMD(0x36);
LCD_WR_Data8(original);
LCD_WR_CMD(0x3A);
LCD_WR_Data8(0x05);
LCD_WR_CMD(0xB2);
LCD_WR_Data8(0x0C);
LCD_WR_Data8(0x0C);
LCD_WR_Data8(0x00);
LCD_WR_Data8(0x33);
LCD_WR_Data8(0x33);
LCD_WR_CMD(0xB7);
LCD_WR_Data8(0x35);
LCD_WR_CMD(0xBB);
LCD_WR_Data8(0x32);
LCD_WR_CMD(0xC2);
LCD_WR_Data8(0x01);
LCD_WR_CMD(0xC3);
LCD_WR_Data8(0x15);//4.5V
LCD_WR_CMD(0xC4);
LCD_WR_Data8(0x20);
LCD_WR_CMD(0xC6);
LCD_WR_Data8(0x0F);
LCD_WR_CMD(0xD0);
LCD_WR_Data8(0xA4);
LCD_WR_Data8(0xA1);
LCD_WR_CMD(0xE0);
LCD_WR_Data8(0xD0);
LCD_WR_Data8(0x0A);
LCD_WR_Data8(0x10);
LCD_WR_Data8(0x0C);
LCD_WR_Data8(0x0C);
LCD_WR_Data8(0x18);
LCD_WR_Data8(0x35);
LCD_WR_Data8(0x43);
LCD_WR_Data8(0x4D);
LCD_WR_Data8(0x39);
LCD_WR_Data8(0x13);
LCD_WR_Data8(0x13);
LCD_WR_Data8(0x2D);
LCD_WR_Data8(0x34);
LCD_WR_CMD(0xE1);
LCD_WR_Data8(0xD0);
LCD_WR_Data8(0x05);
LCD_WR_Data8(0x0B);
LCD_WR_Data8(0x06);
LCD_WR_Data8(0x05);
LCD_WR_Data8(0x02);
LCD_WR_Data8(0x35);
LCD_WR_Data8(0x43);
LCD_WR_Data8(0x4D);
LCD_WR_Data8(0x16);
LCD_WR_Data8(0x15);
LCD_WR_Data8(0x15);
LCD_WR_Data8(0x2E);
LCD_WR_Data8(0x32);
LCD_WR_CMD(0x21);
LCD_WR_CMD(0x29);
}
4 开始使用TFT
完成以上工作就可以使用TFT进行显示了。
5 易出问题
(1)时序问题
无论SPI还是Parallel,MCU和ST7789v通信的关建都是时序,时序正确,工作会正常,否则出现的问题千奇百怪。如:无法在某些特定区域显示,只能显示半屏数据,花屏.....
MCU使用8MHz主频,仿真SPI时,显示屏正常,直接用硬件SPI,TFT根本不显示,反复检查,使用了1/128分频后,TFT才正常工作。这点和网上找到的资料描述情况不同,尚不知是何原因,按照“7.4.3 Serial Interface Characteristics (4-line serial)”的说明,不应该这么慢的速度。
MCU使用>16MHz主频时,Parallel接口,在向ST7789v发送数据时,需要在给WRX上升沿之前做延时处理,这点与手册描述的时间状况一致。
(2)并口的高低字节问题
认真阅读“8.1 MPU Interface Type Selection”,这里面的DB往往和TFT厂提供的DB不一致。