分享

STM32学习笔记一一TFTLCD 显示

 goodwangLib 2018-03-19

1.TFTLCD 简介

TFT-LCD 即薄膜晶体管液晶显示器。TFT-LCD与无源 TN-LCD、 STN-LCD 的简单矩阵不同,它在液晶显示屏的每一个象素上都设置有一个薄膜晶体管( TFT),可有效地克服非选通时的串扰,使显示液晶屏的静态特性与扫描线数无关,因此大大提高了图像质量。 TFT-LCD 也被叫做真彩液晶显示器。ALIENTEK TFTLCD 模块采用 16 位的并方式与外部连接。

2.80 并口有如下一些信号线:

信号线 作用
CS TFTLCD 片选信号
WR 向 TFTLCD 写入数据
RD 从 TFTLCD 读取数据
D[15: 0] 16 位双向数据线
RST 硬复位 TFTLCD
RS 命令/数据标志( 0,读写命令; 1,读写数据)

注:TFTLCD 模块的 RST 信号线是直接接到 STM32 的复位脚上,并不由软件控制,这样可以省下来一个 IO口。另外我们还需要一个背光控制线来控制 TFTLCD 的背光。所以,我们总共需要的 IO 口数目为 21 个。

3.ILI9341 控制器介绍

ILI9341 液晶控制器自带显存,其显存总大小为 172800( 240*320*18/8),即 18 位模式( 26万色)下的显存量。在 16 位模式下, ILI9341 采用 RGB565 格式存储颜色数据,此时 ILI9341的 18 位数据线与 MCU 的 16 位数据线以及 LCD GRAM 的对应关系如图:

这里写图片描述

ILI9341 在 16 位模式下面,数据线有用的是: D17~D13 和 D11~D1, D0和 D12 没有用到,实际上在我们 LCD 模块里面, ILI9341 的 D0 和 D12 压根就没有引出来,这样, ILI9341 的 D17~D13 和 D11~D1 对应 MCU 的 D15~D0。

MCU 的 16 位数据, 最低 5 位代表蓝色,中间 6 位为绿色,最高 5 位为红色。数值越大,表示该颜色越深。 另外,特别注意 ILI9341 所有的指令都是 8 位的(高 8 位无效),且参数除了读写 GRAM 的时候是 16 位,其他操作参数,都是 8 位的

4.ILI9341 的重要命令

(1)0XD3

这个是读 ID4 指令,用于读取 LCD 控制器的 ID

这里写图片描述

可以看出, 0XD3 指令后面跟了 4 个参数,最后 2 个参数,读出来是 0X93 和 0X41,刚好是控制器 ILI9341 的数字部分,从而,通过该指令,即可判别所用的 LCD 驱动器是什么型号,这样,我们的代码,就可以根据控制器的型号去执行对应驱动 IC 的初始化代码,从而兼容不同驱动 IC 的屏,使得一个代码支持多款 LCD。

(2)0X36

这是存储访问控制指令,可以控制 ILI9341 存储器的读写方向,简单的说,就是在连续写 GRAM 的时候,可以控制 GRAM 指针的增长方向,从而控制显示方式。(读 GRAM 也是一样)。该指令如表:

这里写图片描述

0X36 指令后面,紧跟一个参数,主要关注: MY、 MX、 MV 这三个位,通过这三个位的设置,可以控制整个 ILI9341 的全部扫描方向。

这里写图片描述

在利用 ILI9341 显示内容的时候,就有很大灵活性了,比如显示 BMP 图片,BMP 解码数据,就是从图片的左下角开始,慢慢显示到右上角,如果设置 LCD 扫描方向为从左到右,从下到上,那么我们只需要设置一次坐标,然后就不停的往 LCD 填充颜色数据即可,这样可以大大提高显示速度。

(3)0X2A

这是列地址设置指令, 在从左到右,从上到下的扫描方式(默认)下面,该指令用于设置横坐标( x 坐标),该指令如表 :

这里写图片描述

在默认扫描方式时,该指令用于设置 x 坐标,该指令带有 4 个参数,实际上是 2 个坐标值:SC 和 EC,即列地址的起始值和结束值, SC 必须小于等于 EC,且 0≤SC/EC≤239。一般在设置 x 坐标的时候,我们只需要带 2 个参数即可,也就是设置 SC 即可,因为如果 EC 没有变化,我们只需要设置一次即可(在初始化 ILI9341 的时候设置),从而提高速度。

(4)0X2B

是页地址设置指令, 在从左到右,从上到下的扫描方(默认)下面,该指令用于设置纵坐标( y 坐标)。该指令如表:

这里写图片描述

在默认扫描方式时,该指令用于设置 y 坐标,该指令带有 4 个参数,实际上是 2 个坐标值:SP 和 EP,即页地址的起始值和结束值, SP 必须小于等于 EP,且 0≤SP/EP≤319。一般在设置y 坐标的时候,我们只需要带 2 个参数即可,也就是设置 SP 即可,因为如果 EP 没有变化,我们只需要设置一次即可(在初始化 ILI9341 的时候设置),从而提高速度。

(5)0X2C

该指令是写 GRAM 指令,在发送该指令之后,我们便可以往 LCD的 GRAM 里面写入颜色数据了,该指令支持连续写,指令描述如表:

这里写图片描述

在收到指令 0X2C 之后,数据有效位宽变为 16 位,我们可以连续写入 LCD GRAM 值, 而 GRAM 的地址将根据 MY/MX/MV 设置的扫描方向进行自增。

(6)0X2E

该指令是读 GRAM 指令,用于读取 ILI9341 的显存( GRAM),输出情况如表:

这里写图片描述

该指令用于读取 GRAM,如表 所示,ILI9341在收到该指令后,第一次输出的是 dummy数据,也就是无效的数据,第二次开始,读取到的才是有效的 GRAM 数据(从坐标: SC, SP开始),输出规律为:每个颜色分量占 8 个位,一次输出 2 个颜色分量。

比如:

第一次输出是R1G1,随后的规律为:B1R2G2B2R3G3B3R4G4B4R5G5… 以此类推。如果我们只需要读取一个点的颜色值,那么只需要接收到参数 3 即可,如果要连续读取(利用 GRAM 地址自增),那么就按照上述规律去接收颜色数据。

5.TFTLCD 模块的使用流程

这里写图片描述

任何 LCD,使用流程都可以简单的用以上流程图表示。其中硬复位和初始化序列,只需要执行一次即可。而画点流程就是:设置坐标 -> 写 GRAM 指令 -> 写入颜色数据,然后在 LCD 上面,我们就可以看到对应的点显示我们写入的颜色了。读点流程为:设置坐标 -> 读 GRAM 指令 -> 读取颜色数据,这样就可以获取到对应点的颜色数据了。

1) 设置 STM32 与 TFTLCD 模块相连接的 IO。

先将我们与 TFTLCD 模块相连的 IO 口进行初始化,以便驱动 LCD。 这里需要根据连接电路以及 TFTLCD 模块的设置来确定。

2) 初始化 TFTLCD 模块。

即上图的初始化序列,这里我们没有硬复位 LCD,因为 MiniSTM32 开发板的 LCD 接口,将 TFTLCD 的 RST 同 STM32 的 RESET 连接在一起了,只要按下开发板的 RESET 键,就会对 LCD 进行硬复位。

初始化序列,就是向 LCD 控制器写入一系列的设置值(比如伽马校准),这些初始化序列一般 LCD 供应商会提供给客户,我们直接使用这些序列即可,不需要深入研究。在初始化之后, LCD 才可以正常使用。

3) 通过函数将字符和数字显示到 TFTLCD 模块上。

这一步则通过上图 左侧的流程,即:设置坐标->写 GRAM 指令->写 GRAM 来实现,但是这个步骤,只是一个点的处理,我们要显示字符/数字,就必须要多次使用这个步骤,从而达到显示字符/数字的目标,所以需要设计一个函数来实现数字/字符的显示,之后调用该函数,就可以实现数字/字符的显示了。

6.实例学习

(1)在硬件上, TFTLCD 模块与 MiniSTM32 开发板的 IO口对应关系如下:

功能 IO
LCD_LED PC10
LCD_CS PC9
LCD _RS PC8
LCD _WR PC7
LCD _RD PC6
LCD _D[17:1] PB[15:0]

(2)时序

模块的8080并口读/写的过程为:

先根据要写入/读取的数据的类型,设置RS为高(数据)/低(命令),然后拉低片选,选中ILI9341,接着我们根据是读数据,还是要写数据置RD/WR为低。

1.读数据:在RD的上升沿, 读取数据线上的数据(D[15:0]);

这里写图片描述

2.写数据:在WR的上升沿,使数据写入到ILI9341里面

这里写图片描述

3.例程分析

//LCD重要参数集
typedef struct  
{                                           
    u16 width;          //LCD 宽度
    u16 height;         //LCD 高度
    u16 id;             //LCD ID
    u8  dir;            //横屏还是竖屏控制:0,竖屏;1,横屏。   
    u16 wramcmd;        //开始写gram指令
    u16 setxcmd;        //设置x坐标指令
    u16  setycmd;       //设置y坐标指令    
}_lcd_dev; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

/*写数据函数:通过 80 并口向 LCD 模块写入一个 16 位的数据,宏定义的方式,以提高速度。*/
 #define LCD_WR_DATA(data){    LCD_RS_SET;    LCD_CS_CLR;    DATAOUT(data);    LCD_WR_CLR;    LCD_WR_SET;    LCD_CS_SET;}   

void LCD_WR_DATAX(u16 data)
{
    LCD_RS_SET;
    LCD_CS_CLR;
    DATAOUT(data);
    LCD_WR_CLR;
    LCD_WR_SET;
    LCD_CS_SET;
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

/*通过 8080 并口向 LCD 模块写入寄存器命令*/
//写寄存器函数
//data:寄存器值
void LCD_WR_REG(u16 data)
{
    LCD_RS_CLR;//写地址
    LCD_CS_CLR;
    DATAOUT(data);
    LCD_WR_CLR;
    LCD_WR_SET;
    LCD_CS_SET;
}

/*读取 LCD 控制器的寄存器数据(非 GRAM 数据)*/
//读 LCD 寄存器数据
//返回值:读到的值
u16 LCD_RD_DATA(void)
{
    u16 t;
    GPIOB->CRL=0X88888888; //PB0-7 上拉输入
    GPIOB->CRH=0X88888888; //PB8-15 上拉输入
    GPIOB->ODR=0X0000; //全部输出 0
    LCD_RS_SET;
    LCD_CS_CLR;
    LCD_RD_CLR; //读取数据(读寄存器时,并不需要读 2 次)
    if(lcddev.id==0X8989)delay_us(2);//FOR 8989,延时 2us
    t=DATAIN;
    LCD_RD_SET;
    LCD_CS_SET;
    GPIOB->CRL=0X33333333; //PB0-7 上拉输出
    GPIOB->CRH=0X33333333; //PB8-15 上拉输出
    GPIOB->ODR=0XFFFF; //全部输出高
    return t;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

/*LCD 寄存器操作*/
//写寄存器:用于向 LCD 指定寄存器写入指定数据
//LCD_Reg:寄存器编号
//LCD_RegValue:要写入的值
void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue)
{
    LCD_WR_REG(LCD_Reg);
    LCD_WR_DATA(LCD_RegValue);
}

//读寄存器:用于读取指定寄存器的数据
//LCD_Reg:寄存器编号
//返回值:读到的值
u16 LCD_ReadReg(u16 LCD_Reg)
{
    LCD_WR_REG(LCD_Reg); //写入要读的寄存器号
    return LCD_RD_DATA();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

/*坐标设置*/
//设置光标位置:将 LCD 的当前操作点设置到指定坐标(x,y)
//Xpos:横坐标
//Ypos:纵坐标
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
    if(lcddev.id==0X9341||lcddev.id==0X5310)
    {
    LCD_WR_REG(lcddev.setxcmd);
    LCD_WR_DATA(Xpos>>8);
    LCD_WR_DATA(Xpos&0XFF);
    LCD_WR_REG(lcddev.setycmd);
    LCD_WR_DATA(Ypos>>8);
    LCD_WR_DATA(Ypos&0XFF);
    }else if(lcddev.id==0X6804)
    {
    if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//横屏时处理
    LCD_WR_REG(lcddev.setxcmd);
    LCD_WR_DATA(Xpos>>8);
    LCD_WR_DATA(Xpos&0XFF);
    LCD_WR_REG(lcddev.setycmd);
    LCD_WR_DATA(Ypos>>8);
    LCD_WR_DATA(Ypos&0XFF);
    }else if(lcddev.id==0X5510)
    {
    LCD_WR_REG(lcddev.setxcmd);
    LCD_WR_DATA(Xpos>>8);
    LCD_WR_REG(lcddev.setxcmd+1);
    LCD_WR_DATA(Xpos&0XFF);
    LCD_WR_REG(lcddev.setycmd);
    LCD_WR_DATA(Ypos>>8);
    LCD_WR_REG(lcddev.setycmd+1);
    LCD_WR_DATA(Ypos&0XFF);
    }else
    {
    if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//横屏其实就是调转 x,y 坐标
    LCD_WriteReg(lcddev.setxcmd, Xpos);
    LCD_WriteReg(lcddev.setycmd, Ypos);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

//画点
//x,y:坐标
//POINT_COLOR:此点的颜色
void LCD_DrawPoint(u16 x,u16 y)
{
    LCD_SetCursor(x,y); //设置光标位置
    LCD_WriteRAM_Prepare(); //开始写入 GRAM
    LCD_WR_DATA(POINT_COLOR);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

//读取个某点的颜色值
//x,y:坐标
//返回值:此点的颜色
u16 LCD_ReadPoint(u16 x,u16 y)
{
    u16 r,g,b;
    if(x>=lcddev.width||y>=lcddev.height)
        return 0; //超过了范围,直接返回
    LCD_SetCursor(x,y);
    if(lcddev.id==0X9341||lcddev.id==0X6804||lcddev.id==0X5310||lcddev.id==0X1963)
    LCD_WR_REG(0X2E);//9341/6804/3510/1963 发送读 GRAM 指令
    else if(lcddev.id==0X5510)LCD_WR_REG(0X2E00);//5510 发送读 GRAM 指令
    else LCD_WR_REG(0X22); //其他 IC 发送读 GRAM 指令
    GPIOB->CRL=0X88888888; //PB0-7 上拉输入
    GPIOB->CRH=0X88888888; //PB8-15 上拉输入
    GPIOB->ODR=0XFFFF; //全部输出高
    LCD_RS_SET;
    LCD_CS_CLR;
    LCD_RD_CLR; //读取数据(读 GRAM 时,第一次为假读)
    opt_delay(2); //延时
    r=DATAIN; //实际坐标颜色
    LCD_RD_SET;
    if(lcddev.id==0X1963)
    {
    LCD_CS_SET;
    GPIOB->CRL=0X33333333; //PB0-7 上拉输出
    GPIOB->CRH=0X33333333; //PB8-15 上拉输出
    GPIOB->ODR=0XFFFF; //全部输出高
    return r; //1963 直接读就可以
    }
    LCD_RD_CLR; //dummy READ
    opt_delay(2); //延时
    r=DATAIN; //实际坐标颜色
    LCD_RD_SET;
    if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X5510)//这几个 IC 要分 2 次读出
    {
    LCD_RD_CLR;
    opt_delay(2);//延时
    b=DATAIN;//读取蓝色值
    LCD_RD_SET;
    g=r&0XFF;//对于 9341,第一次读取的是 RG 的值,R 在前,G 在后,各占 8 位
    g<<=8;
    }else if(lcddev.id==0X6804)
    {
    LCD_RD_CLR;
    LCD_RD_SET;
    r=DATAIN;//6804 第二次读取的才是真实值
    }
    LCD_CS_SET;
    GPIOB->CRL=0X33333333; //PB0-7 上拉输出
    GPIOB->CRH=0X33333333; //PB8-15 上拉输出
    GPIOB->ODR=0XFFFF; //全部输出高
    if(lcddev.id==0X9325||lcddev.id==0X4535||lcddev.id==0X4531||lcddev.id==0X8989||
    lcddev.id==0XB505)return r; //这几种 IC 直接返回颜色值
    else if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X5510)
    return (((r>>11)<<11)|((g>>10)<<5)|(b>>11));//这几个 IC 需要公式转换一下
    else return LCD_BGR2RGB(r); //其他 IC
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

//在指定位置显示一个字符
//x,y:起始坐标
//num:要显示的字符:" "--->"~"
//size:字体大小 12/16/24
//mode:叠加方式(1)还是非叠加方式(0)
void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode)
{
    u8 temp,t1,t;
    u16 y0=y;
    u8 csize=(size/8+((size%8)?1:0))*(size/2);//得到字体一个字符对应点阵集所占字节数
    //设置窗口
    num=num-' ';//得到偏移后的值
    for(t=0;t<csize;t++)
    {
    if(size==12)temp=asc2_1206[num][t]; //调用 1206 字体
    else if(size==16)temp=asc2_1608[num][t]; //调用 1608 字体
    else if(size==24)temp=asc2_2412[num][t]; //调用 2412 字体
    else return; //没有的字库
    for(t1=0;t1<8;t1++)
    {
    if(temp&0x80)
    LCD_Fast_DrawPoint(x,y,POINT_COLOR);
    else if(mode==0)
    LCD_Fast_DrawPoint(x,y,BACK_COLOR);
    temp<<=1;
    y++;
    if(x>=lcddev.width)return; //超区域了
    if((y-y0)==size)
    {
    y=y0; x++;
    if(x>=lcddev.width)return; //超区域了
    break;
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

//该初始化函数可以初始化各种 ALIENTEK 出品的 LCD 液晶屏
void LCD_Init(void)
{ 
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //使能PORTB,C时钟和AFIO时钟
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);//开启SWD,失能JTAG

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6;     ///PORTC6~10复用推挽输出
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC  

    GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //  PORTB推挽输出
    GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB

    GPIO_SetBits(GPIOB,GPIO_Pin_All);

    delay_ms(50); // delay 50 ms 
    LCD_WriteReg(0x0000,0x0001);
    delay_ms(50); // delay 50 ms 
    lcddev.id = LCD_ReadReg(0x0000);   
    if(lcddev.id<0XFF||lcddev.id==0XFFFF||lcddev.id==0X9300)//读到ID不正确,新增lcddev.id==0X9300判断,因为9341在未被复位的情况下会被读成9300
    {   
        //尝试9341 ID的读取      
        LCD_WR_REG(0XD3);                  
        LCD_RD_DATA();              //dummy read    
        LCD_RD_DATA();              //读到0X00
        lcddev.id=LCD_RD_DATA();    //读取93                                 
        lcddev.id<<=8;
        lcddev.id|=LCD_RD_DATA();   //读取41                 
        if(lcddev.id!=0X9341)       //非9341,尝试是不是6804
        {   
            LCD_WR_REG(0XBF);                  
            LCD_RD_DATA();          //dummy read     
            LCD_RD_DATA();          //读回0X01               
            LCD_RD_DATA();          //读回0XD0                
            lcddev.id=LCD_RD_DATA();//这里读回0X68 
            lcddev.id<<=8;
            lcddev.id|=LCD_RD_DATA();//这里读回0X04   
            if(lcddev.id!=0X6804)   //也不是6804,尝试看看是不是NT35310
            { 
                LCD_WR_REG(0XD4);                  
                LCD_RD_DATA();              //dummy read  
                LCD_RD_DATA();              //读回0X01     
                lcddev.id=LCD_RD_DATA();    //读回0X53    
                lcddev.id<<=8;   
                lcddev.id|=LCD_RD_DATA();   //这里读回0X10   
                if(lcddev.id!=0X5310)       //也不是NT35310,尝试看看是不是NT35510
                {
                    LCD_WR_REG(0XDA00); 
                    LCD_RD_DATA();          //读回0X00     
                    LCD_WR_REG(0XDB00); 
                    lcddev.id=LCD_RD_DATA();//读回0X80
                    lcddev.id<<=8;  
                    LCD_WR_REG(0XDC00); 
                    lcddev.id|=LCD_RD_DATA();//读回0X00       
                    if(lcddev.id==0x8000)lcddev.id=0x5510;//NT35510读回的ID是8000H,为方便区分,我们强制设置为5510
                    if(lcddev.id!=0X5510)           //也不是NT5510,尝试看看是不是SSD1963
                    {
                        LCD_WR_REG(0XA1);
                        lcddev.id=LCD_RD_DATA();
                        lcddev.id=LCD_RD_DATA();    //读回0X57
                        lcddev.id<<=8;   
                        lcddev.id|=LCD_RD_DATA();   //读回0X61    
                        if(lcddev.id==0X5761)lcddev.id=0X1963;//SSD1963读回的ID是5761H,为方便区分,我们强制设置为1963
                    }
                }
            }
        }   
    }
    printf(" LCD ID:%x\r\n",lcddev.id); //打印LCD ID  
    if(lcddev.id==0X9341)   //9341初始化
    {    
        LCD_WR_REG(0xCF);  
        LCD_WR_DATAX(0x00); 
        LCD_WR_DATAX(0xC1); 
        LCD_WR_DATAX(0X30); 
        LCD_WR_REG(0xED);  
        LCD_WR_DATAX(0x64); 
        LCD_WR_DATAX(0x03); 
        LCD_WR_DATAX(0X12); 
        LCD_WR_DATAX(0X81); 
        LCD_WR_REG(0xE8);  
        LCD_WR_DATAX(0x85); 
        LCD_WR_DATAX(0x10); 
        LCD_WR_DATAX(0x7A); 
        LCD_WR_REG(0xCB);  
        LCD_WR_DATAX(0x39); 
        LCD_WR_DATAX(0x2C); 
        LCD_WR_DATAX(0x00); 
        LCD_WR_DATAX(0x34); 
        LCD_WR_DATAX(0x02); 
        LCD_WR_REG(0xF7);  
        LCD_WR_DATAX(0x20); 
        LCD_WR_REG(0xEA);  
        LCD_WR_DATAX(0x00); 
        LCD_WR_DATAX(0x00); 
        LCD_WR_REG(0xC0);    //Power control 
        LCD_WR_DATAX(0x1B);   //VRH[5:0] 
        LCD_WR_REG(0xC1);    //Power control 
        LCD_WR_DATAX(0x01);   //SAP[2:0];BT[3:0] 
        LCD_WR_REG(0xC5);    //VCM control 
        LCD_WR_DATAX(0x30);      //3F
        LCD_WR_DATAX(0x30);      //3C
        LCD_WR_REG(0xC7);    //VCM control2 
        LCD_WR_DATAX(0XB7); 
        LCD_WR_REG(0x36);    // Memory Access Control 
        LCD_WR_DATAX(0x48); 
        LCD_WR_REG(0x3A);   
        LCD_WR_DATAX(0x55); 
        LCD_WR_REG(0xB1);   
        LCD_WR_DATAX(0x00);   
        LCD_WR_DATAX(0x1A); 
        LCD_WR_REG(0xB6);    // Display Function Control 
        LCD_WR_DATAX(0x0A); 
        LCD_WR_DATAX(0xA2); 
        LCD_WR_REG(0xF2);    // 3Gamma Function Disable 
        LCD_WR_DATAX(0x00); 
        LCD_WR_REG(0x26);    //Gamma curve selected 
        LCD_WR_DATAX(0x01); 
        LCD_WR_REG(0xE0);    //Set Gamma 
        LCD_WR_DATAX(0x0F); 
        LCD_WR_DATAX(0x2A); 
        LCD_WR_DATAX(0x28); 
        LCD_WR_DATAX(0x08); 
        LCD_WR_DATAX(0x0E); 
        LCD_WR_DATAX(0x08); 
        LCD_WR_DATAX(0x54); 
        LCD_WR_DATAX(0XA9); 
        LCD_WR_DATAX(0x43); 
        LCD_WR_DATAX(0x0A); 
        LCD_WR_DATAX(0x0F); 
        LCD_WR_DATAX(0x00); 
        LCD_WR_DATAX(0x00); 
        LCD_WR_DATAX(0x00); 
        LCD_WR_DATAX(0x00);          
        LCD_WR_REG(0XE1);    //Set Gamma 
        LCD_WR_DATAX(0x00); 
        LCD_WR_DATAX(0x15); 
        LCD_WR_DATAX(0x17); 
        LCD_WR_DATAX(0x07); 
        LCD_WR_DATAX(0x11); 
        LCD_WR_DATAX(0x06); 
        LCD_WR_DATAX(0x2B); 
        LCD_WR_DATAX(0x56); 
        LCD_WR_DATAX(0x3C); 
        LCD_WR_DATAX(0x05); 
        LCD_WR_DATAX(0x10); 
        LCD_WR_DATAX(0x0F); 
        LCD_WR_DATAX(0x3F); 
        LCD_WR_DATAX(0x3F); 
        LCD_WR_DATAX(0x0F); 
        LCD_WR_REG(0x2B); 
        LCD_WR_DATAX(0x00);
        LCD_WR_DATAX(0x00);
        LCD_WR_DATAX(0x01);
        LCD_WR_DATAX(0x3f);
        LCD_WR_REG(0x2A); 
        LCD_WR_DATAX(0x00);
        LCD_WR_DATAX(0x00);
        LCD_WR_DATAX(0x00);
        LCD_WR_DATAX(0xef);  
        LCD_WR_REG(0x11); //Exit Sleep
        delay_ms(120);
        LCD_WR_REG(0x29); //display on  
    }   
    LCD_Display_Dir(0);         //默认为竖屏
    LCD_LED=1;                  //点亮背光
    LCD_Clear(WHITE);
}       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172

注:此处仅为9341 的初始化


参考:

原子开发手册—–库函数版

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多