STM32CubeMx之FSMC灵活静态存储器控制器
1.简介
??FSMC模块能够与同步或异步存储器和16位PC存储器卡接口,它的主要作用是: ??● 将AHB传输信号转换到适当的外部设备协议 ??● 满足访问外部设备的时序要求 ??所有的外部存储器共享控制器输出的地址、数据和控制信号,每个外部设备可以通过一个唯一的片选信号加以区分。FSMC在任一时刻只访问一个外部设备。 ??FSMC具有下列主要功能: ??● 具有静态存储器接口的器件包括: ???─ 静态随机存储器(SRAM) ???─ 只读存储器(ROM) ???─ NOR闪存 ???─ PSRAM(4个存储器块) ??● 两个NAND闪存块,支持硬件ECC并可检测多达8K字节数据 ??● 16位的PC卡兼容设备 ??● 支持对同步器件的成组(Burst)访问模式,如NOR闪存和PSRAM ??● 8或16位数据总线 ??FSMC管理1GB空间,拥有4个Bank连接外部存储器,每个Bank有独立的片选信号,每个Bank有独立的时序配置,同步批量传输访问最高频率可达60MHz ??支持的存储器类型: ??静态地址映射存储器:SRAM、PSRAM、NOR/ONENAND、ROM ??LCD接口:支持8080和6800模式 ??NANDFlash和16位PCCard
2.外挂设备地址映射
??NOR/PSRAM是”static memory map”设备: 256M字节的空间需要28根地址线寻址,HADDR表示内部AHB地址线; ??HADDR[27:26]用来对4个region寻址; ??HADDR[25:0]用来对外部地址FSMC[25:0]; ??无论8位/16位宽度,FSMC_A[0]始终连接外部设备地址A[0] ??当外接设备16位数据宽度:HADDR[25:1]–>FSMC_A[24:0] ??当外接设备8位数据宽度:HADDR[25:0]–>FSMC_A[25:0]
3.LCD硬件接口
??LCD屏 ?分辨率:320*480;3.5寸; ?驱动方式:8080并口时序(Intel公司),16位真彩色(RGB565); ?屏幕驱动IC:NT35310; ??硬件接口
LCD引脚 | GPIO脚 | 说明 |
---|
LCD_CS(FSMC_NE4) | PG12 | 片选,低电平选中,高电平取消选中 | RS (FSMC_A10 ) | PG0 | 数据命令选择线,低电平读写命令,高电平读写数据 | WR (FSMC_NWE) | PD5 | 写使能,低电平开始写,高电平写完成 | RD (FSMC_NOE ) | PD4 | 读使能,低电平开始读,高电平读完成 | BL (LCD_BL ) | PB0 | 背光,1点亮,0熄灭 | FSMC_D0~ D1 | PD14~PD15 | 双向数据线 | FSMC_D2~ D3 | PD0~PD1 | 双向数据线 | FSMC_D13~ D15 | PD8~PD10 | 双向数据线 |
4.软件设置
?1.芯片选择 ?2. 时钟配置 ?3.FSMC配置 ?根据LCD硬件接口可知LCD接在FSMC_Blank1的region4上。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/1d913aa05caf45bca6194c24055b8dd6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASVRf6Zi_5rC0,size_20,color_FFFFFF,t_70,g_se,x_16
5 代码生成
?1.FSMC配置代码 ?FSMC寄存器配置可参考STM32中文参考手册第19章灵活静态存储器控制器(FSMC)。 ?2.LCD显示图片和显示汉字示例 ??(1) 根据LCD硬件接口时序8080,要想实现对LCD屏数据显示则需要完成LCD写数据和写寄存器,LCD接在FSMC_Blank1的region4上,通过地址线FSMC_A10作为数据命令选择线,通过FSMC地址映射关系可知: ??读写寄存器地址:0x6c000000 ??读写数据地址:0x6c000800 ??写寄存器和写数据代码如下:
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#define LCD_WR_REG *((volatile u16 *)0x6c000000)
#define LCD_WR_DAT *((volatile u16 *)0x6c000800)
static void LcdWriteReg(u16 reg)
{
LCD_WR_REG=reg;
}
static void LcdWriteData(u16 dat)
{
LCD_WR_DAT=dat;
}
??(2)设置光标指令0X2A 和0X2B ??该指令是页地址设置指令,在从左到右,从上到下的扫描方式(默认)下面,该指令用于设置纵坐标( x 坐标) ??在默认扫描方式时,该指令用于设置 x 坐标,该指令带有 4 个参数,实际上是 2 个坐标值: SC 和 EC,即列地址的起始值和结束值, SC 必须小于等于 EC,且 0≤SC/EC≤239。一般在设置 x 坐标的时候,我们只需要带 2个参数即可,也就是设置 SC 即可,因为如果 EC 没有变化,我们只需要设置一次即可,从而提高速度。 ??0X2B 指令,该指令是页地址设置指令,在从左到右,从上到下的扫描方式(默认)下面,该指令用于设置纵坐标( y 坐标)。 ??代码如下:
static void LCD_SetCursor(u16 x,u16 y)
{
LcdWriteReg(0x2A);
LcdWriteData(x>>8);
LcdWriteData(x&0xff);
LcdWriteReg(0x2B);
LcdWriteData(y>>8);
LcdWriteData(y&0xff);
}
??(3)写入数据到GRAM指令0x2C ??该指令是写 GRAM 指令,在发送该指令之后,我们便可以往 LCD 的 GRAM 里面写入颜色数据了,该指令支持连续写 (地址自动递增)。
void LCD_Clear(u16 c)
{
u32 i=0;
LCD_SetCursor(0,0);
LcdWriteReg(0x2c);
for(i=0;i<320*480;i++)
{
LcdWriteData(c);
}
}
??(4)显示图片 ??通过图片取模工具Img2Lcd进行图片取模: ??将生成的图片数据放到工程中:
void LCD_DrawBMP(u16 x,u16 y,u16 w,u16 h,const u8 *buff)
{
u16 i,j;
u16 temp;
LcdWriteReg(0x2A);
LcdWriteData(x>>8);
LcdWriteData(x&0xff);
LcdWriteData((x+w)>>8);
LcdWriteData((x+w)&0xff);
LcdWriteReg(0x2B);
LcdWriteData(y>>8);
LcdWriteData(y&0xff);
LcdWriteData((y+h)>>8);
LcdWriteData((y+h)&0xff);
LcdWriteReg(0x2c);
for(i=0;i<h;i++)
{
for(j=0;j<w;j++)
{
temp=(*buff<<8)|*(buff+1);
buff+=2;
LcdWriteData(temp);
}
}
LcdWriteReg(0x2A);
LcdWriteData(0>>8);
LcdWriteData(0);
LcdWriteData(320>>8);
LcdWriteData(320&0xff);
LcdWriteReg(0x2B);
LcdWriteData(0>>8);
LcdWriteData(0);
LcdWriteData(480>>8);
LcdWriteData(480&0xff);
}
??(5)汉字显示 ??通过PCtoLCD2002进行汉字取模,取模方式:高位在前,逐行式。
void LCD_Display_Font(u16 x,u16 y,u8 size,u8 *font,u16 c)
{
u16 i,j;
u8 temp;
u16 x0=x;
for(i=0;i<size*size/8;i++)
{
temp=font[i];
for(j=0;j<8;j++)
{
if(temp&0x80)LCD_DrawPoint(x0,y,c);
x0++;
temp<<=1;
}
if(x0-x==size)
{
x0=x;
y++;
}
}
6 示例效果
??主函数:
7.参考示例
https://download.csdn.net/download/weixin_44453694/85014208
|