(整理)基于STM32的LCD操作

(整理)基于STM32的LCD操作
(整理)基于STM32的LCD操作

嵌入式系统》课程报告

基于 STM32的 LCD 操作

组长:曾昭智 组员:邓

宁、张小扬、牛洪澄

光电学院 电信 2班、3 班

2014.05.29

姓名

学院 班级 完成日期

目录

1、原理方案(功能框图介绍) (1)

2、电路连线及资源分配. (2)

3、所用主要器件或模块说明. (3)

4、程序流程图. (4)

5、调试心得. (5)

6、源代码 (6)

1.TFT-LCD 原理

1.1 TFT-LCD 简介

TFT-LCD即薄膜晶体管液晶显示器。其英文全称为:Thin Film Transistor-Liquid Crystal Display 。TFT-LCD与无源TN-LCD、STN-LCD 的简单

矩阵不同,它在液晶显示屏的每一个象素上都设置有一个薄膜晶体管(TFT),可有效地克服非选通时的串扰,使显示液晶屏的静态特性与扫描线数无关,因此大大提高了图像质量。TFT-LCD也被叫做真彩液晶显示器。

上一节介绍了OLED模块,这一节,我们给大家介绍ALIENTEK TFTLC模D 块,该模块有如下特点:

1,2.4 '/2.8 '两种大小的屏幕可选。

2,320×240的分辨率。

3,16位真彩显示。

4,自带触摸屏,可以用来作为控制输入。

5,通用的接口,除了ALIENTEK MiniSTM32开发板,该液晶模块还可以使用在优异特、STMSK、Y 红牛等开发板上。

本节,我们以 2.8 寸的ALIENTEKT FTLCD模块为例介绍,该模块采用的是显尚光电的DST2001PHT FTLCD,DST2001PH的控制器为ILI9320 ,采用26 万色的TFTLCD 屏,分辨率为320×240,采用16 位的80并口。

1.2 80 并口

ALIENTEK TFTLCD 模块采用80并口口方与外部链接,采用16位数据线(低了速度太慢,用彩色就没什么效果了)。该模块的80并口有如下一些信号线:CS:TFTLCD 片选信号。

WR:向TFTLCD 写入数据。

RD:从TFTLCD 读取数据。

D[15:0] :16位双向数据线。

RST:硬复位TFTLCD 。

RS:命令/数据标志(0,读写命令;1,读写数据)。

TFTLCD 模块的RST信号线和OLED 模块一样,也是直接接到STM32 的复位脚上,并

不由软件控制,这样可以省下来一个IO 口。另外我们还需要一个背光控制线来控制TFTLCD 的背光。所以,我们总共需要的IO 口数目为21 个。

1.3 ILI9320

模块的控制器为ILI9320 ,该控制器自带显存,其显存总大小为172820

(240*320*18/8 ),即18位模式(26万色)下的显存量。模块的16位数据线与显寸的对应关系为565 方式,如下图所示:

1.4 GRAM显示方向设置

1.5 TFTLCD 显示需要的相关设置步骤如下

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

这一步,先将我们与TFTLCD模块相连的IO口设置为输出,具体使用哪些IO口,这里需要根据连接电路以及TFTLCD模块的设置来确定。

(2)初始化TFTLCD模块。

其实这里就是上和上面OLED模块的初始化过程差不多。通过向TFTLCD写入一系列的设置,来启动TFTLCD的显示。为后续显示字符和数字做准备。

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

这里就是通过我们设计的程序,将要显示的字符送到TFTLCD模块就可以了,这些函数将在软件设计部分向大家介绍。

通过以上三步,我们就可以使用ALIENTEKT FTLCD模块来显示字符和数字了,并且可以显示各种颜色的背景。

2. 电路连线及资源分配

MiniSTM32 开发板底板的LCD接口和ALIENTEK TFTLCD模块直接可以对插,连接如下图:

图中绿色线圈出来的部分就是连接TFTLCD 模块的接口,这里在硬件上,TFTLCD 模块

与MiniSTM32 开发板的IO 口对应关系如下:

LCD_LED 对应PC10;

LCD_CS 对应PC9;

LCD _RS 对应PC8;

LCD _WR 对应PC7;

LCD _RD 对应PC6;

LCD _D[17:1] 对应PB[15:0];

这些线的连接,MiniSTM32 的内部已经连接好了,我们只需要

将就好了。

3. 所用主要器件或模块说明

TFTLCD 模块插上

3.1 TFT-LCD 模块原理图

3.2 TFT-LCD 模块接口图

4. 程序流程图

写入数据

读取数据

5. 调试心得

调试之前需将MiniSTM32开发板连接至PC并且安装好相应的驱动程序;在调试程序的时候将错误程序下载到MiniSTM32中会导致LCD屏无法打开或者是

屏的现象,程序与开发板不兼容也会产生同样现象;并且在使用Keil 调试的时候没有进行正确的设置也会导致下载程序无法顺利进行。所以在调试的时候要确保程序的正确及对Keil 的正确的使用才能顺利完成实验。

调试结果(到屏幕的背景是不停切

换的

6. 源代码

6.1 LCD_WR_RE函G数:通过80并口向LCD模块写入8 位的寄存器命令#if LCD_FAST_IO==1 // 快速IO

void LCD_WR_REG(u8 data)

{

LCD_RS_CLR;/写/ 地址

LCD_CS_CLR;

DATAOUT(data);

LCD_WR_CLR;

LCD_WR_SET;

LCD_CS_SET;

}

#else// 正常IO

// 写寄存器函数

void LCD_WR_REG(u8 data)

{

LCD_RS=0;//写地址

LCD_CS=0;

DATAOUT(data);

LCD_WR=0;

LCD_WR=1;

LCD_CS=1;

}

#endif

6.2 LCD_READRE:G用来读取某个寄存器的值

// 读寄存器

u16 LCD_ReadReg(u8 LCD_Reg)

{

u16 t;

LCD_WR_REG(LCD_Reg); /写/ 入要读的寄存器号

GPIOB->CRL=0X88888888; //PB0-7 上拉输入

GPIOB->CRH=0X88888888; //PB8-15 上拉输入

GPIOB->ODR=0XFFFF; // 全部输出高

#if LCD_FAST_IO==1 // 快速IO

LCD_RS_SET;

LCD_CS_CLR;

// 读取数据(读寄存器时,并不需要读2次)

LCD_RD_CLR;

delay_us(5);//FOR 8989, 延时5us

LCD_RD_SET;

t=DATAIN;

LCD_CS_SET;

#else

LCD_RS=1;

LCD_CS=0;

// 读取数据(读寄存器时,并不需要读2次)

LCD_RD=0;

LCD_RD=1;

t=DATAIN;

LCD_CS=1;

#endif

GPIOB->CRL=0X33333333; //PB0-7 上拉输出

GPIOB->CRH=0X33333333; //PB8-15 上拉输出

GPIOB->ODR=0XFFFF; // 全部输出高

return t;

}

6.3 LCD_ReadRAM:用来读取GRAM的值

// 读取个某点的颜色值

//x:0~239

//y:0~319

// 返回值: 此点的颜色

u16 LCD_ReadPoint(u16 x,u16 y)

{

u16 t;

if(x>=LCD_W||y>=LCD_H)return 0;// 超过了范围, 直接返回LCD_SetCursor(x,y);

LCD_WR_REG(R34); // 选择GRAM地址

GPIOB->CRL=0X88888888; //PB0-7 上拉输入

GPIOB->CRH=0X88888888; //PB8-15 上拉输入

GPIOB->ODR=0XFFFF; // 全部输出高

#if LCD_FAST_IO==1 // 快速IO

LCD_RS_SET;

LCD_CS_CLR;

// 读取数据(读GRAM时,需要读2次)

LCD_RD_CLR;

LCD_RD_SET;

delay_us(2);//FOR 9320, 延时2us

//dummy READ

LCD_RD_CLR;

delay_us(2);//FOR 8989, 延时2us

LCD_RD_SET;

t=DATAIN;

LCD_CS_SET;

#else

LCD_RS=1;

LCD_CS=0;

// 读取数据(读GRAM时,需要读2次)

LCD_RD=0;

LCD_RD=1;

//dummy READ

LCD_RD=0;

LCD_RD=1;

t=DATAIN;

LCD_CS=1;

#endif

GPIOB->CRL=0X33333333; //PB0-7 上拉输出

GPIOB->CRH=0X33333333; //PB8-15 上拉输出

GPIOB->ODR=0XFFFF; // 全部输出高

if(DeviceCode==0X4531||DeviceCode==0X8989||DeviceCode==0XB505)ret urn t;// 这几种IC 直接返回颜色值

else return LCD_BGR2RGB(t);

}

6.4 LCD_SetCursor :用于设置坐标void LCD_SetCursor(u16 Xpos, u16 Ypos) {

#if USE_HORIZONTAL==1 if(DeviceCode==0X8989) {

LCD_WriteReg(0X4E, Ypos); LCD_WriteReg(0X4F, 319-Xpos);

}else

{

LCD_WriteReg(R32, Ypos);

LCD_WriteReg(R33, 319-Xpos);

} #else

if(DeviceCode==0X8989)

{

LCD_WriteReg(0X4E, Xpos);

LCD_WriteReg(0X4F, Ypos);

}else

{

LCD_WriteReg(R32, Xpos);

LCD_WriteReg(R33, Ypos);

} #endif }

6.5 POINT_COLO:R 画点函数void LCD_DrawPoint(u16 x,u16 y) {

LCD_SetCursor(x,y);// 设置光标位置LCD_WR_REG(R34);开// 始写入

GRAM LCD_WR_DATA(POINT_COLOR);

}

6.6 LCD_ShowChar:显示字符

// 在指定位置显示一个字符

//x:0~234

//y:0~308

//num: 要显示的字符:" "--->"~" //size: 字体大小12/16

//mode: 叠加方式(1) 还是非叠加方式(0) void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode)

{

#if USE_HORIZONTAL==1

#define MAX_CHAR_POSX 312

#define MAX_CHAR_POSY 232

#else

#define MAX_CHAR_POSX 232

#define MAX_CHAR_POSY 312

#endif

u8 temp;

u8 pos,t;

u16 x0=x;

u16 colortemp=POINT_COLOR;

if(x>MAX_CHAR_POSX||y>MAX_CHAR_POSY)return;

// 设置窗口num=num-' ';// 得到偏移后的值if(!mode) // 非叠加方式

{

for(pos=0;pos

{ if(size==12)temp=asc2_1206[num][pos];// 调用1206 字体else temp=asc2_1608[num][pos]; // 调用1608 字体

for(t=0;t

{ if(temp&0x01)POINT_COLOR=colortemp; else

POINT_COLOR=BACK_COLOR; LCD_DrawPoint(x,y); temp>>=1;

x++;

}

x=x0; y++;

}

}else// 叠加方式

{

for(pos=0;pos

{ if(size==12)temp=asc2_1206[num][pos];// else

temp=asc2_1608[num][pos]; // for(t=0;t

{ if(temp&0x01)LCD_DrawPoint(x+t,y+pos);// temp>>=1; }

}

}

POINT_COLOR=colortemp;

}

6.7 LCD_Init (简化):初始化模块

void LCD_Init(void)

{

u16 DeviceCode;

RCC->APB2ENR|=1<<3;/先/ 使能外设 PORT 时B 钟 RCC->APB2ENR|=1<<4;/先/ 使能外设 PORT 时C 钟 RCC->APB2ENR|=1<<0; //开启辅助时钟

AFIO->MAPR=0X04000000; //关闭 JTAG //PORTC6~10复用推挽输出 GPIOC->CRH&=0XFFFFF000; GPIOC->CRH|=0X00000333; GPIOC->CRL&=0X00FFFFFF; GPIOC->CRL|=0X33000000; GPIOC->ODR|=0X07C0; //PORTB 推挽输出

GPIOB->CRH=0X33333333; GPIOB->CRL=0X33333333; GPIOB->ODR=0XFFFF; Delay(5); // delay 50 ms

LCD_WriteReg(0x0000,0x0001); Delay(5); // delay 50 ms

DeviceCode = LCD_ReadReg(0x0000); //printf("ID:%d\n" , DeviceCode);

调用 1206 字

体 调用 1608 字体 画一个点

if(DeviceCode==0x9325||DeviceCode==0x9328)//ILI9325 {

?? //9325/9328 初始化代码

}

else if(DeviceCode==0x9320||DeviceCode==0x9300)

{

?? //9320/9300 初始化代码

}

else if(DeviceCode==0x1505) { ?? //1505 初始化代码

}

else if(DeviceCode==0x8989)

{

?? //8989 初始化代码

}

Delay(5000);

LCD_Clear(WHITE);

}

6.8 输入以下代码(简化代码)来控制 I/O 口,当使用快速模式来控制的时

候,就可以有效提升速度。 另外这段代码对颜色和驱动器的寄存器进行了很多宏 定义:

#ifndef __LCD_H #define __LCD_H #include "sys.h" #include "stdlib.h"

//TFTLCD 部分外要调用的函数

extern u16 POINT_COLOR;// 默认红色

extern u16 BACK_COLOR; // 背景颜色 . 默认为白色 // LCD 端口定义 #define LCD_LED PCout(10) //LCD 背光 PC10 #define LCD_CS PCout(9) // #define LCD_RS PCout(8) // #define LCD_WR PCout(7) // #define LCD_RD PCout(6) // //PB0~15 ,作为数据线

#define DATAOUT(x) GPIOB->ODR=x; // 数据输出 #define DATAIN GPIOB->IDR; // 数据输入 // 画笔颜色

#define WHITE 0xFFFF #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800

#define MAGENTA 0xF81F #define GREEN 0x07E0 #define CYAN 0x7FFF #define YELLOW 0xFFE0

#define BROWN 0XBC40 // 棕色 #define BRRED 0XFC07 // 棕红色

片选端口 PC9 数据/命令 PC8 写数据 PC7 读数据 PC6

#define GRAY 0X8430 // 灰色

#define LGRAY 0XC618 // 浅灰色extern u16 BACK_COLOR,POINT_COLOR ;

void LCD_Init(void);

void LCD_Clear(u16 Color);

void LCD_SetCursor(u8 Xpos ,u16 Ypos);

void LCD_DrawPoint(u8 x ,u16 y);// 画点

void Draw_Circle(u8 x0 ,u16 y0 ,u8 r);

void LCD_DrawLine(u8 x1 ,u16 y1 ,u8 x2 ,u16 y2);

void LCD_DrawRectangle(u8 x1 ,u16 y1 ,u8 x2 ,u16 y2);

void LCD_Fill(u8 xsta ,u16 ysta ,u8 xend ,u16 yend ,u16 color);

void LCD_ShowChar(u8 x ,u16 y ,u8 num,u8 size ,u8 mode);// 显示一个字符

void LCD_ShowNum(u8 x,u8 y,u32 num,u8 len ,u8 size); // 显示一个数字

void LCD_ShowString(u8 x ,u16 y ,const u8 *p); // 显示一个字符串,16字体

void LCD_WriteReg(u8 LCD_Reg,u16 LCD_RegValue);

u16 LCD_ReadReg(u8 LCD_Reg);

void LCD_WriteRAM_Prepare(void);

void LCD_WriteRAM(u16 RGB_Code);

u16 LCD_ReadRAM(void);

//9320/9325 LCD 寄存器

#define R0 0x00

#define R1 0x01

#define R2 0x02

??// 寄存器定义区

#define R192 0xC0

#define R193 0xC1

#define R229 0xE5

#endif

6.9 Test 中的main 函数:该部分代码将显示一些固定的字符,然后不停

的切换背景颜色,每1s 切换一次。而LED0也会不停的闪烁,指示程序已经在运行

int main(void)

{

u8 x=0;

SystemInit();

delay_init(72); // 延时初始化

NVIC_Configuration();

uart_init(9600);

LED_Init();

KEY_Init();

LCD_Init();

POINT_COLOR=RED;

while(1)

{

switch(x)

{

case 0:LCD_Clear(WHITE);break;

case 1:LCD_Clear(BLACK);break;

case 2:LCD_Clear(BLUE);break;

case 3:LCD_Clear(RED);break; case

4:LCD_Clear(MAGENTA);break; case

5:LCD_Clear(GREEN);break;

case 6:LCD_Clear(CYAN);break;

case 7:LCD_Clear(YELLOW);break;

case 8:LCD_Clear(BRRED);break;

case 9:LCD_Clear(GRAY);break;

case 10:LCD_Clear(LGRAY);break; case

11:LCD_Clear(BROWN);break;

}

POINT_COLOR=RED;

LCD_ShowString(30,50,"Mini STM32 ^_^");

LCD_ShowString(30,70,"2.4'/2.8' TFTLCD TEST");

LCD_ShowString(30,90,"ATOM@ALIENTEK");

LCD_ShowString(30,110,"2010/12/30");

x++;

if(x==12)x=0;

LED0=!LED0;

delay_ms(1000);

}

相关主题
相关文档
最新文档