Flexible Static Memory Controller
1> 实验概述
通过 STM32F103内部FSMC模块,控制TFT-LCD,显示字符和图片
2> TFT-LCD
TFT-LCD薄膜晶体管液晶显示器(Thin Film Transistor Liquid Crystal Display)
参数:
LCD尺寸: 2.8寸;
分辨率:320 * 240;
色彩深度:16位(65K色);
数据格式:RGB565;
接口类型:8080(16bit);
驱动芯片:ILI9431;
3> 驱动芯片 ILI9341
显存GRAM:172,800 Bytes
分辨率:240RGBx320 dots
3.1> 8080硬件接口
3.2> 驱动芯片 ILI9341 读时序
读数据:在读使能【RDX】上升沿,读取数据线上的数据;
3.3> 驱动芯片 ILI9341 写时序
写时序:写使能【WRX】上升沿,将数据写入ILI9431;
3.3> 驱动芯片 ILI9341 时序参数
twrh,写使能,高电平脉宽:15ns;
twrl,写使能,低电平脉宽:15ns;
trdh,读LCD的ID号,高电平脉宽:90ns;
trdl,读LCD的ID号,低电平脉宽:45ns;
trdhfm,读LCD显存GRAM高电平脉宽:90ns;
trdlfm,读LCD显存GRAM低电平脉宽:355ns;
3.4> RGB565格式
红色R:5bit,绿色G:6bit,蓝色B:5bit; 共16位,2个字节;
RGB颜色表示:
RGB565常用颜色对照表:
#define BLACK 0x0000 // 黑色 0000 0000 0000 0000
#define RED 0xF800 // 红色 1111 1000 0000 0000
#define GREEN 0x07E0 // 绿色 0000 0111 1110 0000
#define BLUE 0x001F // 蓝色 0000 0000 0001 1111
#define WHITE 0xFFFF // 白色 1111 1111 1111 1111
#define NAVY 0x000F // 深蓝色
#define DGREEN 0x03E0 // 深绿色
#define DCYAN 0x03EF // 深青色
#define MAROON 0x7800 // 深红色
#define PURPLE 0x780F // 紫色
#define OLIVE 0x7BE0 // 橄榄绿
#define LGRAY 0xC618 // 灰白色
#define DGRAY 0x7BEF // 深灰色
#define CYAN 0x07FF // 青色
#define MAGENTA 0xF81F // 品红
#define YELLOW 0xFFE0 // 黄色
3.5> Command常用指令
4> FSMC
FSMC灵活的静态存储器控制器
4.1> FSMC硬件方框图
4.2> FSMC内存映射
FSMC管理4个256Byte的存储块(Bank1~4);
存储块1(Bank1)可以访问4个Nor-Flash或PSRAM,并配置4个片选;
4.2> AHB的HADDR[31:0]
HADDR[27:26] NOR/PSRAM 存储块 选择
HADDR[25:0] 存储器寻址范围
HADDR[25:1], 25bit;
寻址范围: 2^32 = 【4,294,967,296】Byte = 【32】MByte
可访问存储空间:32MByte * 16bit = 512Mbit = 64MByte;
图形表示:
4.3> FSMC-模式A读时序
4.4> FSMC-模式A写时序
注意事项:
1》 STM32F1, HCLK算的时间可能不准,根据实测进行设置;
2》 EXTMOD: 扩展模式使能 (Extended mode enable)
该位允许FSMC使用FSMC_BWTR寄存器,即允许读和写使用不同的时序。
设置为1;
5> 程序设计
5.1> 初始化程序
5.2> 底层驱动
void LCD_WriteCmd(uint16_t cmd)
{
GPIO_ResetBits(GPIOG, GPIO_Pin_0); //RS(D/CX) = 0; 传输命令
*((volatile uint16_t *)0x6C000000) = cmd;
}
void LCD_WriteData(uint16_t dat)
{
GPIO_SetBits(GPIOG, GPIO_Pin_0); //RS = 1; 传输数据
*((volatile uint16_t *)0x6C000000) = dat;
}
uint16_t LCD_ReadData(void)
{
uint16_t ret;
GPIO_SetBits(GPIOG, GPIO_Pin_0); //RS = 1; 传输数据
ret = *((volatile uint16_t *)0x6C000000);
return ret;
}
可以看到使用FSMC模块后,比自己软件模拟时序要简单多了;
注意:volatile关键字,不能少,每次必须读写硬件地址的值,避免编译器优化;
5.3> 功能命令
5.3.1> 读显示模式
uint8_t LCD_ReadDPF(void)
{
uint8_t ret;
LCD_WriteCmd(0x0c);
LCD_ReadData(); // 第1字节无效
ret = LCD_ReadData();
return ret;
}
5.3.2> 起始行列坐标设置
/* column address control set */
LCD_WriteCmd ( 0x2A );
LCD_WriteData ( 0x00 );
LCD_WriteData ( 0x00 ); // SC=0x00
LCD_WriteData ( 0x00 );
LCD_WriteData ( 0xEF ); // EC=0xEF=239
/* page address control set */
LCD_WriteCmd ( 0x2B ); // 设置Y坐标
LCD_WriteData ( 0x00 );
LCD_WriteData ( 0x00 ); // SP=0x00
LCD_WriteData ( 0x01 );
LCD_WriteData ( 0x3F ); // EP=0x013F = 319
SC = 0; EC = 239;
SP = 0; EP = 319;
正好就是整个液晶屏的大小320 * 240;