目录

显示器简介

液晶显示器

显示器的基本参数

液晶控制原理

 ILI9341液晶控制器简介

液晶屏的信号线及8080时序

使用STM32的FSMC模拟8080接口时序

FSMC简介

存储器控制器

时钟控制逻辑

FSMC模拟8080时序

FSMC控制液晶屏软件设计

编程要点

NOR FLASH时序结构体

FSMC初始化结构体

ILI9341的驱动代码和ST7789V的驱动代码

显示器简介

显示器属于计算机的I/O设备,即输入输出设备,它是一种将特定电子信息输出到屏幕上再反射到人眼的显示工具,常见的有CRT显示器,液晶显示器,LED点阵显示器及OLED显示器。

液晶显示器

液晶显示器,简称LCD(Liquid Crystal Display),相对于上一代CRT显示器(阴极射线管显示器),LCD显示器具有功耗低,体积小,承载的信息量大及不伤眼的优点,因而它成为了现在的主流电子显示设备。

显示器的基本参数

不管是哪一种显示器,都有一定的参数用于描述它们的特性,各个参数介绍如下:

  1. 像素:像素是组成图像的最基本单元要素,显示器的像素指它成像最小的点,即液晶的一个显示单元。
  2. 分辨率:一些嵌入式设备的显示器常以”行像素值*列像素值“表示屏幕的分辨率。如分辨率800*480表示该显示器的每一行有800个像素点,每一列有400个像素点,也可以理解为有800列,480行
  3. 色彩深度:色彩深度指显示器的每个像素点能表示多少种颜色,一般用”位“来表示。如单色屏的每个像素点能表示亮或灭两种状态(即实际上能显示两种颜色),用1个数据位就可以表示像素点的所有状态,所以他的色彩深度为1bit,其他常见的显示屏色深为16bit,24bits.
  4. 显示器尺寸:显示器的大小一般以英寸表示,如5英寸、21英寸、24英寸等,这个长度是指屏幕对角线的长度,通过显示器的对角线长度以及长宽比可以确定显示器的实际长宽尺寸。
  5. 点距:点距指两个相邻像素点之间的距离,它会影响画质的细腻度以及观看距离,相同尺寸的屏幕,若分辨率越高,则点距越小,画质越好,如现在有些手机的屏幕分辨率比电脑显示器的还大,这是手机屏幕点距小的原因,LED点阵显示屏的点距一般都比较大,所以适合远距离观看。

液晶控制原理

一个完整的显示屏由液晶显示面板、电容触摸面板以及PCB底板构成。图中的触摸面板带有触摸控制芯片,该芯片处理触摸信号并通过引出的信号线与外部器件通讯,触摸面板中间是透明的,它贴在液晶面板上面,一起构成屏幕的主体,触摸面板与液晶面板引出的排线连接到PCB底板上,根据实际需要,PCB底板上可能会带有”液晶控制芯片“,图中右侧的液晶屏PCB上带有RA8875的液晶控制器,因为控制液晶面板需要比较多的资源,所以大部分低级微控制器都不能直接控制液晶面板,需要额外配套一个专用液晶控制器来处理显示过程。外部微控制器只要把它希望显示的数据直接交给液晶控制器即可。而不带液晶控制器的PCB底板,只有小部分的电源管理电路。STM32F429芯片不需要额外的液晶控制器,也就是说他把液晶控制器集成到芯片内部了,可以理解为电脑的CPU集成显卡,STM32F1系列的没有集成,所以需要外接,可以理解为电脑的外置显卡。总的来说,这两类屏幕的控制框图如下所示:

 ILI9341液晶控制器简介

实验用到的液晶控制器芯片为ILI9341,它的内部结构非常复杂,见图ILI9341控制器内部框图。

该芯片最主要的就是位于中间的GRAM(Graphics RAM),它就是显存。GRAM中的每个存储单元都对应着液晶面板上的一个

像素点,他右侧的各种模块共同作用把GRAM存储单元的数据转化成液晶面板的控制信号,使得像素点呈现特定的颜色,而像素点组合起来则成为一副完整的图像。框图的左上角为ILI9341的主要控制信号线和配置引脚,根据其不同的状态设置可以使芯片工作在不同的模式,如每个像素点的位数是6,16,还是18位;可配置使用SPI、8080接口还是RGB接口与MCU通讯。MCU通过SPI、8080接口或者RGB接口和ILI9341进行通讯,从而访问它的控制器(CR)、地址计数器(AC)、及GRAM。

在GRAM的左侧还有一个LED控制器(LED Conroller)。LCD为非发光性的显示装置,它需要借助背光源才能达到显示功能,LED控制器就是用来控制液晶屏中的LED背光源。

液晶屏的信号线及8080时序

ILI9341控制器根据自身的IM[3:0]信号线电平决定它与MCU之间的通讯方式,它本身支持SPI及8080通讯方式,我实验的是野火的STM32板子,它的ILI9341控制器在出厂之前就已经按固定配置好(内部已连接硬件电路),它被配置为通过8080接口通讯,使用16根数据线的RGB565格式。内部硬件电路连接完,剩下的其他信号线被引出到FPC排线,最后该排线由PCB底板引出到排针,排针再与实验板上的STM32芯片连接,引出的排针信号线见图液晶屏引出的信号线。

信号线 ILI9341对应的信号线 说明
LCD_DB[15:0] D[15:0] 数据信号
LCD_RD RDX 读数据信号,低电平有效
LCD_RS D/CX 数据/命令信号,高电平时,D[15:0]表示的是数据(RGB565像素数据或命令数据),低电平时D[15:0]表示的是控制命令
LCD_RESET RESX 复位信号,低电平有效
LCD_WR WRX 写数据信号,低电平有效
LCD_CS CSX 片选信号,低电平有效
LCD_BK - 背光信号,低电平点亮
GPIO[5:1] - 触摸屏的控制信号线,

这些信号线,就是8080通讯接口,带X的表示低电平有效,STM32通过该接口与ILI9341芯片进行通讯,实现对液晶屏的控制,通讯的内容主要包括命令和显存数据,显存数据即各个像素点的数据;命令是指ILI9341的控制命令,mcu可通过8080接口发送命令编码控制ILI9341的工作方式,例如复位命令,设置光标指令,睡眠模式指令等等,具体的要看ILI9341的数据手册,有详细的说明。

注意:这里不同的液晶控制芯片,对应的控制命令代码可能是不一样的,本人实验的时候,以为板子上的是ILI9341的控制芯片,但是最后发现,是用的ST7789V控制芯片,以至于出来的颜色不正确,最后配置正确,才成功。

 由图可知,写命令时序由片选信号CSX拉低开始,对数据/命令选择信号线D/CX也置低电平表示写入的是命令地址(可理解为命令编码),以写信号WRX为低,都信号RDX为高电平表示数据的传输方向为写入,此时在数据线D[15:0]输出命令地址,在第二个传输阶段传送的是命令的参数,所以D/CX要置为高电平,表示写入的是命令数据,命令数据是指某些指令带有的参数,如复位指令编码后面可以带一个参数,该参数表示多少秒后复位。

使用STM32的FSMC模拟8080接口时序

FSMC简介

FSMC是STM32的外设,用来管理扩展的存储器,FSMC可以用来驱动包括SRAM、NOR FLASH以及NAND FLASH类型的存储器,不能驱动SDRAM这种动态的存储器,而在STM32F429系列的控制器中,它具有FMC外设,可以驱动SDRAM存储器。

由于FSMC外设可以控制扩展的外部存储器,而对MCU对液晶屏的操作实际上是把显示数据写入到显存中,与控制存储器非常类似,且8080接口的通讯时序完全可以使用FSMC外设产生。

FSMC外设的结构见图

 通讯引脚

在框图的右侧是FSMC外设相关的控制引脚,由于控制不同类型的存储器时会有一些不同的引脚,因此看起来会有非常多,其中地址线FSMC_A和数据线FSMC_D是所有控制器都共用的。这些FSMC引脚具体对应的GPIO端口和引脚在相应的手册中可以看到。

FSMC信号名 信号方向 功能
CLK 输出 时钟(同步突发模式使用)
A[25:0] 输出 地址总线
D[15:0] 输入/输出 双向数据总线
NE[X] 输出 片选,x=1,2,3,4
NOE 输出 输出使能
NWE 输出 写使能
NWAIT 输入 NOR闪存要求FSMC等待的信号
NADV 输出 地址,数据线复用时作锁存的信号

在控制LCD时,使用的是类似异步,地址与数据线独立的NOR FLASH控制方式,所以实际上CLK、NWAIT、NADV引脚并没有使用到。

其中比较特殊的FSMC_NE1/2/3/4号引脚,不同的引脚对应STM32内部不同的控制区域。例如,当STM32访问0x68000000~0x6BFFFFFF地址空间时,FSMC_NE3引脚会自动设置为低电平,由于他一般连接到外部存储器的片选引脚且低电平有效,所以外部存储器的片选被使能,而访问0x60000000~0x63FFFFFF地址时,FSMC_NE1会输出低电平。当时用不同的FSMC_NE引脚连接外部存储器时,STM32访问外部存储的地址不一样,从而达到控制多个外部存储器芯片的目的。

存储器控制器

上面不同类型的引脚是连接到FSMC内部对应的存储器控制器中的。NOR/PSRAM/SRAM设备使用相同的控制器,NAND/PC卡设备使用相同的控制器,不同的控制器有专用的寄存器用于配置其工作模式。

控制NOR FLASH的有FSMC_BCR1/2/3/4控制寄存器,FSMC_BTR1/2/3/4片选时序寄存器以及FSMC_BWTR1/2/3/4写时序寄存器。每种寄存器都有4个,分别对应对于4个不同的存储区域,各种寄存器介绍如下:

  • FSMC_BCR控制寄存器可配置要控制的存储器类型、数据线宽度以及信号有效极性等参数
  • FSMC_BTR时序寄存器用于配置SRAM访问时的各种时间延迟、如数据保持时间、地址保持时间、地址建立时间、数据建立时间。
  • FSMC_BWTR时序寄存器和FSMC_BTR寄存器控制的参数类似,它专门用于控制写时许的时间参数。

时钟控制逻辑

FSMC外设挂载在AHB总线上,时钟信号来自于HCLK默认为72MHZ,控制器的同步时钟输出就是由他分频得到的。例如,NOR控制器的FSMC_CLK引脚输出的时钟,它可用于与同步类型的NOR FLASH芯片进行同步通讯,它的时钟频率可通过FSMC_BTR寄存器的CLKDIV位配置,可以配置为HCLK的1/2或者1/3,也就是说,若他与同步类型的NOR FLASH通讯时,同步时钟最高频率为36MHZ.

FSMC模拟8080时序

对比FSMC NOR/PSRAM中的模式B时序与ILI9341液晶控制芯片的8080时序可以发现,这两个时序是非常相似的,除了FSMC的地址线A和8080的D/CX线,可以说是完全一样的。

FSMC_NOR信号线 功能 8080信号线 功能
NEx 片选信号 CSX 片选信号
NWR 写使能 WRX 写使能
NOE 读使能 RDX 读使能
D[15:0] 数据信号 D[15:0] 数据信号
A[25:0] 地址信号 A[25:0] 地址信号

 对于FSMC和8080接口,前四种信号线完全都是一样的,仅仅是FSMC的地址信号线A[25:0]与8080的数据/命令选择线D/CX有区别。而对于D/CX线,它为高电平的时候表示数值,为低电平时就表示命令,如果能够使用FSMC的A地址线的根据不同情况下的产生相应的电平,那么就完全可以使用FSMC来产生8080接口需要的时序了。

FSMC控制液晶屏软件设计

编程要点

  • 初始化通讯时的目标引脚及端口时钟
  • 使能FSMC外设的时钟
  • 配置FSMC为异步NOR FLASH模式以仿真8080时序
  • 建立机制使用FSMC向液晶屏发送命令及数据
  • 发送控制命令初始化液晶屏
  • 编写液晶屏的绘制像素点函数
  • 利用描点函数制作各种不同的液晶屏显示应用如画线、画圆、画矩形

NOR FLASH时序结构体

控制FSMC使用NOR FLASH存储器时主要是配置时序寄存器以及控制寄存器,利用ST标准库的时序结构体以及初始化结构体可以很方便的写入参数。

NOR FLASH时序结构体的成员见代码

typedef struct
{
  uint32_t FSMC_AddressSetupTime;    /**地址建立时间0-0xF个HCLK周期/
 
  uint32_t FSMC_AddressHoldTime;     /*地址保持时间,0-0xF个HCLK周期*/
 
  uint32_t FSMC_DataSetupTime;        /*地址建立时间,0-0xF个HCLK周期*/
 
  uint32_t FSMC_BusTurnAroundDuration;  /*总线转换周期,0-0xF个HCLK周期,在NOR FLASH*/
 
  uint32_t FSMC_CLKDivision;          /*时钟分频因子,1-0xF,若控制异步存储器,则本参数无效*/
 
  uint32_t FSMC_DataLatency;         /*数据延迟时间,若控制异步存储器,本参数无效*/   
                                              
  uint32_t FSMC_AccessMode;          /*设置访问模式*/
           
}FSMC_NORSRAMTimingInitTypeDef;


这个结构体与SRAM中的时序结构体完全一样,以下仅列出控制NOR FLASH时使用模式B用的结构体成员说明:

  1. FSMC_AddressSetupTime:本成员设置地址建立时间,即FSMC读写时序图FSMC写NOR_FLASH的时序图中的ADDSET值,它可以被设置为0-0xF个HCLK周期数,按STM32标准库默认配置,HCLK的时钟频率为72MHZ,即一个HCLK周期为1/72微秒。
  2. FSMC_DataSetupTime:本成员设置数据建立时间,即FSMC读写时序图FSMC写NOR FLASH的时序图中的DATAST值,它可以被设置为0-0xf个HCLK周期数。
  3.  FSMC_BusTurnAroundDuration:本成员设置总线转换周期,在NOR FLASH存储器中,地址线与数据线可以分时复用,总线转换周期就是指总现在这两种状态间切换需要的延时,防止冲突。控制其他存储器时这个参数无效,配置为0即可。
  4. FSMC_CLKDivision:本成员用于设置时钟分频,它以HCLK时钟作为输入,经过FSMC_CLKDivision分频后输出到FSMC_CLK引脚作为通讯使用的同步时钟,控制其他异步通讯的存储器时,这个参数无效,配置为0即可。
  5. FSMC_DataLatency:本成员设置数据保持时间,它表示在读取第一个数据之前要等待的周期数,该周期指同步时钟的周期,本参数仅用于同步NOR FLASH类型的存储器,控制其他类型的存储器时,该参数无效,配置为0即可。
  6. FSMC_AccessMode:本成员设置存储器访问模式,不同的模式下FSMC访问存储器地址时引脚输出的时序不一样,可选FSMC_AccessMode_A/B/C/D模式,控制异步NOR FLASH时使用B模式。

这个FSMC_NORSRAMTimingInitTypeDef时序结构体配置的延时参数,将作为FSMC NOR FLASH初始化结构体的一个成员。

FSMC初始化结构体

 
typedef struct
{
  uint32_t FSMC_Bank;                /*设置要控制的Bank区域*/
 
  uint32_t FSMC_DataAddressMux;     /*设置地址总线与数据总线是否复用*/
 
  uint32_t FSMC_MemoryType;         /*设置存储器类型*/
 
  uint32_t FSMC_MemoryDataWidth;     /*设置存储器的数据宽度*/
 
  uint32_t FSMC_BurstAccessMode;     /*设置是否支持突发访问模式,只支持同步类型的存储器*/
                                       
  uint32_t FSMC_AsynchronousWait;    /*设置是否使能在同步传输时的等待信号*/
 
  uint32_t FSMC_WaitSignalPolarity; /*设置等待信号的极性*/
 
  uint32_t FSMC_WrapMode;            /*设置是否支持对齐的突发模式*/
 
  uint32_t FSMC_WaitSignalActive;    /*配置等待信号在等待前有效还是等待期间有效*/
 
  uint32_t FSMC_WriteOperation;      /*设置是否写使能*/
 
  uint32_t FSMC_WaitSignal;          /*设置是否是能等待状态插入*/
 
  uint32_t FSMC_ExtendedMode;        /*设置是否是能扩展模式*/
 
  uint32_t FSMC_WriteBurst;          /*设置是否是能写突发操作*/
 
  FSMC_NORSRAMTimingInitTypeDef* FSMC_ReadWriteTimingStruct; /*当不使用扩展模式时,本参数用于配置读写时序,否则用于配置读时序*/
/*当使用扩展模式时,本参数用于配置写时序*/
  FSMC_NORSRAMTimingInitTypeDef* FSMC_WriteTimingStruct;   
}FSMC_NORSRAMInitTypeDef;


这个结构体,除最后两个成员是上面讲解的时序配置外,其他结构体成员的配置都对应到FSMC_BCR中的寄存器位,各个成员的意义介绍如下:

(1)FSMC_Bank

本成员用于选择FSMC映射的存储区域,它的可选参数以及相应的内核地址映射范围表可以选择的存储区域及区域对应的地址范围。

可以输入的宏 对应的地址区域
FSMC_Bank1_NORSRAM1 0x60000000-0x63FFFFFF
FSMC_Bank1_NORSRAM2 0x64000000-0x67FFFFFF
FSMC_Bank1_NORSRAM3 0x68000000-0x6BFFFFFF
FSMC_Bank1_NORSRAM4 0x6C000000-0x6FFFFFFF

(2)FSMC_DataAddressMux

本成员用于设置地址总线与数据总线是否复用,在控制NOR FLASH时,可以地址总线与数据总线分时复用,可以减少用STM32信号线的数量。

(3)FSMC_MemoryType

本成员用于设置要控制的存储器类型,它支持的存储器类型为SRAM,PSRAM以及NOR FLASH

(4)FSMC_MemoryDataWidth

本成员用于设置要控制的存储器的数据宽度,可选择设置为8/16位

(5)FSMC_BurstAccessMode

本成员用于设置是否使用突发访问模式,突发访问模式是指发送一个地址后连续访问多个数据,非突发模式下每访问一个数据都需要输入一个地址,仅在控制同步类型的存储器时才能使用突发模式。

(6) FSMC_AsynchronousWait
本 成 员 用 于 设 置 是 否 使 能 在 同 步 传 输 时 使 用 的 等 待 信 号
(FSMC_AsynchronousWait_Enable/Disable) , 在 控 制 同 步 类 型 的 NOR 或 PSRAM
时,存储器可以使用 FSMC_NWAIT 引脚通知 STM32 需要等待。
(7) FSMC_WaitSignalPolarity
本成员用于设置等待信号的有效极性,即要求等待时,使用高电平还是低电平
(FSMC_WaitSignalPolarity_High/Low) 
(8) FSMC_WrapMode
本成员用于设置是否支持把非对齐的 AHB 突发操作分割成 次线性操作
(FSMC_WrapMode_Enable/Disable) ,该配置仅在突发模式下有效。
(9) FSMC_WaitSignalActive
本 成 员 用 于 配 置 在 突 发 传 输 模 式 时, 决 定 存 储 器 是 在 等 待
状 态 之 前 的 一 个 数 据 周 期 有 效 还 是 在 等 待 状 态 期 间 有 效
(FSMC_WaitSignalActive_BeforeWaitState/DuringWaitState) 
(10) FSMC_WriteOperation
这个成员用于设置是否写使能 (FSMC_WriteOperation_ Enable /Disable) ,禁止写使能的
话 FSMC 只能从存储器中读取数据,不能写入。
(11) FSMC_WaitSignal
本成员用于设置当存储器处于突发传输模式时,是否允许通过 NWAIT 信号插入等待
状态 (FSMC_WaitSignal_Enable/Disable) 
(12) FSMC_ExtendedMode
本成员用于设置是否使用扩展模式 (FSMC_ExtendedMode_Enable/Disable) ,在非扩
展模式下,对存储器读写的时序都只使用 FSMC_BCR 寄存器中的配置,即下面的
FSMC_ReadWriteTimingStruct 结构体成员;在扩展模式下,对存储器的读写时序可以
分开配置,读时序使用 FSMC_BCR 寄存器,写时序使用 FSMC_BWTR 寄存器的配置,
即后面的 FSMC_WriteTimingStruct 结构体成员。
(13) FSMC_ReadWriteTimingStruct
本 成 员 是 一 个 指 针, 赋 值 时 使 用 上 一 小 节 中 讲 解 的 时 序 结 构 体
FSMC_NORSRAMInitTypeDef 设置,当不使用扩展模式时,读写时序都使用本
成员的参数配置。
(14) FSMC_WriteTimingStruct
同样地,本成员也是一个时序结构体的指针,只有当使用扩展模式时,本配置才有效,
它是写操作使用的时序。
对本结构体赋值完成后,调用 FSMC_NORSRAMInit 库函数即可把配置参数写入到 FSMC_BCR
及 FSMC_BTR/BWTR 寄存器中。

ILI9341的驱动代码和ST7789V的驱动代码

ILI9341的驱动代码:这是由官方给的官方驱动代码
 /*  Power control B (CFh)  */
    DEBUG_DELAY  ();
    ILI9341_Write_Cmd ( 0xCF  );
    ILI9341_Write_Data ( 0x00  );
    ILI9341_Write_Data ( 0x81  );
    ILI9341_Write_Data ( 0x30  );
    
    /*  Power on sequence control (EDh) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xED );
    ILI9341_Write_Data ( 0x64 );
    ILI9341_Write_Data ( 0x03 );
    ILI9341_Write_Data ( 0x12 );
    ILI9341_Write_Data ( 0x81 );
    
    /*  Driver timing control A (E8h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xE8 );
    ILI9341_Write_Data ( 0x85 );
    ILI9341_Write_Data ( 0x10 );
    ILI9341_Write_Data ( 0x78 );
    
    /*  Power control A (CBh) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xCB );
    ILI9341_Write_Data ( 0x39 );
    ILI9341_Write_Data ( 0x2C );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x34 );
    ILI9341_Write_Data ( 0x03 );
    
    /* Pump ratio control (F7h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xF7 );
    ILI9341_Write_Data ( 0x20 );
    
    /* Driver timing control B */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xEA );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x00 );
    
    /* Frame Rate Control (In Normal Mode/Full Colors) (B1h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xB1 );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x1B );
    
    /*  Display Function Control (B6h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xB6 );
    ILI9341_Write_Data ( 0x0A );
    ILI9341_Write_Data ( 0xA2 );
    
    /* Power Control 1 (C0h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xC0 );
    ILI9341_Write_Data ( 0x35 );
    
    /* Power Control 2 (C1h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xC1 );
    ILI9341_Write_Data ( 0x11 );
    
    /* VCOM Control 1 (C5h) */
    ILI9341_Write_Cmd ( 0xC5 );
    ILI9341_Write_Data ( 0x45 );
    ILI9341_Write_Data ( 0x45 );
    
    /*  VCOM Control 2 (C7h)  */
    ILI9341_Write_Cmd ( 0xC7 );
    ILI9341_Write_Data ( 0xA2 );
    
    /* Enable 3G (F2h) */
    ILI9341_Write_Cmd ( 0xF2 );
    ILI9341_Write_Data ( 0x00 );
    
    /* Gamma Set (26h) */
    ILI9341_Write_Cmd ( 0x26 );
    ILI9341_Write_Data ( 0x01 );
    DEBUG_DELAY ();
    
    /* Positive Gamma Correction */
    ILI9341_Write_Cmd ( 0xE0 ); //Set Gamma
    ILI9341_Write_Data ( 0x0F );
    ILI9341_Write_Data ( 0x26 );
    ILI9341_Write_Data ( 0x24 );
    ILI9341_Write_Data ( 0x0B );
    ILI9341_Write_Data ( 0x0E );
    ILI9341_Write_Data ( 0x09 );
    ILI9341_Write_Data ( 0x54 );
    ILI9341_Write_Data ( 0xA8 );
    ILI9341_Write_Data ( 0x46 );
    ILI9341_Write_Data ( 0x0C );
    ILI9341_Write_Data ( 0x17 );
    ILI9341_Write_Data ( 0x09 );
    ILI9341_Write_Data ( 0x0F );
    ILI9341_Write_Data ( 0x07 );
    ILI9341_Write_Data ( 0x00 );
    
    /* Negative Gamma Correction (E1h) */
    ILI9341_Write_Cmd ( 0XE1 ); //Set Gamma
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x19 );
    ILI9341_Write_Data ( 0x1B );
    ILI9341_Write_Data ( 0x04 );
    ILI9341_Write_Data ( 0x10 );
    ILI9341_Write_Data ( 0x07 );
    ILI9341_Write_Data ( 0x2A );
    ILI9341_Write_Data ( 0x47 );
    ILI9341_Write_Data ( 0x39 );
    ILI9341_Write_Data ( 0x03 );
    ILI9341_Write_Data ( 0x06 );
    ILI9341_Write_Data ( 0x06 );
    ILI9341_Write_Data ( 0x30 );
    ILI9341_Write_Data ( 0x38 );
    ILI9341_Write_Data ( 0x0F );
    
    /* memory access control set */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0x36 ); 	
    ILI9341_Write_Data ( 0xC8 );    /*竖屏  左上角到 (起点)到右下角 (终点)扫描方式*/
    DEBUG_DELAY ();
    
    /* column address control set */
    ILI9341_Write_Cmd ( CMD_SetCoordinateX ); 
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0xEF );
    
    /* page address control set */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( CMD_SetCoordinateY ); 
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x01 );
    ILI9341_Write_Data ( 0x3F );
    
    /*  Pixel Format Set (3Ah)  */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0x3a ); 
    ILI9341_Write_Data ( 0x55 );
    
    /* Sleep Out (11h)  */
    ILI9341_Write_Cmd ( 0x11 );	
    ILI9341_Delay ( 0xAFFf<<2 );
    DEBUG_DELAY ();
    
    /* Display ON (29h) */
    ILI9341_Write_Cmd ( 0x29 ); 
	}

ST7789V官方驱动代码
 /*  Power control B (CFh)  */
    DEBUG_DELAY  ();
    ILI9341_Write_Cmd ( 0xCF  );
    ILI9341_Write_Data ( 0x00  );
    ILI9341_Write_Data ( 0xC1  );
    ILI9341_Write_Data ( 0x30  );
    
    /*  Power on sequence control (EDh) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xED );
    ILI9341_Write_Data ( 0x64 );
    ILI9341_Write_Data ( 0x03 );
    ILI9341_Write_Data ( 0x12 );
    ILI9341_Write_Data ( 0x81 );
    
    /*  Driver timing control A (E8h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xE8 );
    ILI9341_Write_Data ( 0x85 );
    ILI9341_Write_Data ( 0x10 );
    ILI9341_Write_Data ( 0x78 );
    
    /*  Power control A (CBh) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xCB );
    ILI9341_Write_Data ( 0x39 );
    ILI9341_Write_Data ( 0x2C );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x34 );
    ILI9341_Write_Data ( 0x02 );
    
    /* Pump ratio control (F7h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xF7 );
    ILI9341_Write_Data ( 0x20 );
    
    /* Driver timing control B */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xEA );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x00 );
    
    
    /* Power Control 1 (C0h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xC0 );   //Power control
    ILI9341_Write_Data ( 0x21 );  //VRH[5:0]
    
    /* Power Control 2 (C1h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xC1 );   //Power control
    ILI9341_Write_Data ( 0x11 );  //SAP[2:0];BT[3:0]
    
    /* VCOM Control 1 (C5h) */
    ILI9341_Write_Cmd ( 0xC5 );
    ILI9341_Write_Data ( 0x2D );
    ILI9341_Write_Data ( 0x33 );
    
    /*  VCOM Control 2 (C7h)  */
//	ILI9341_Write_Cmd ( 0xC7 );
//	ILI9341_Write_Data ( 0XC0 );
    
    /* memory access control set */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0x36 );   //Memory Access Control
    ILI9341_Write_Data ( 0x00 );  /*竖屏  左上角到 (起点)到右下角 (终点)扫描方式*/
    DEBUG_DELAY ();
    
    ILI9341_Write_Cmd(0x3A);   
    ILI9341_Write_Data(0x55); 
    
      /* Frame Rate Control (In Normal Mode/Full Colors) (B1h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xB1 );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x17 );
    
    /*  Display Function Control (B6h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xB6 );
    ILI9341_Write_Data ( 0x0A );
    ILI9341_Write_Data ( 0xA2 );
    
    ILI9341_Write_Cmd(0xF6);    			
    ILI9341_Write_Data(0x01); 
    ILI9341_Write_Data(0x30); 
    
    /* Enable 3G (F2h) */
    ILI9341_Write_Cmd ( 0xF2 );
    ILI9341_Write_Data ( 0x00 );
    
    /* Gamma Set (26h) */
    ILI9341_Write_Cmd ( 0x26 );
    ILI9341_Write_Data ( 0x01 );
    DEBUG_DELAY ();
    
    /* Positive Gamma Correction */
    ILI9341_Write_Cmd(0xe0); //Positive gamma
    ILI9341_Write_Data(0xd0);         
    ILI9341_Write_Data(0x00); 
    ILI9341_Write_Data(0x02); 
    ILI9341_Write_Data(0x07); 
    ILI9341_Write_Data(0x0b); 
    ILI9341_Write_Data(0x1a); 
    ILI9341_Write_Data(0x31); 
    ILI9341_Write_Data(0x54); 
    ILI9341_Write_Data(0x40); 
    ILI9341_Write_Data(0x29); 
    ILI9341_Write_Data(0x12); 
    ILI9341_Write_Data(0x12); 
    ILI9341_Write_Data(0x12); 
    ILI9341_Write_Data(0x17);
 
    /* Negative Gamma Correction (E1h) */
    ILI9341_Write_Cmd(0xe1); //Negative gamma
    ILI9341_Write_Data(0xd0); 
    ILI9341_Write_Data(0x00); 
    ILI9341_Write_Data(0x02); 
    ILI9341_Write_Data(0x07); 
    ILI9341_Write_Data(0x05); 
    ILI9341_Write_Data(0x25); 
    ILI9341_Write_Data(0x2d); 
    ILI9341_Write_Data(0x44); 
    ILI9341_Write_Data(0x45); 
    ILI9341_Write_Data(0x1c); 
    ILI9341_Write_Data(0x18); 
    ILI9341_Write_Data(0x16); 
    ILI9341_Write_Data(0x1c); 
    ILI9341_Write_Data(0x1d); 
  
	
	/* column address control set */
	ILI9341_Write_Cmd ( CMD_SetCoordinateX ); 
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0xEF );
	
	/* page address control set */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( CMD_SetCoordinateY ); 
	ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x01 );
	ILI9341_Write_Data ( 0x3F );
	
	
    /* Sleep Out (11h)  */
    ILI9341_Write_Cmd ( 0x11 );	  //Exit Sleep
    ILI9341_Delay ( 0xAFFf<<2 );
    DEBUG_DELAY ();
    
    /* Display ON (29h) */
    ILI9341_Write_Cmd ( 0x29 );   //Display on
    
    ILI9341_Write_Cmd(0x2c);
  }