- FMC介绍:LTDC章节已经介绍过,此处省略;
- 框图:
- FMC把外部设备分为:NOR/PSRAM、NAND、SDRAM,共用地址、数据线和若干信号线;
- 液晶屏介绍LTDC章节介绍过,从简,不写;
- 屏幕参数:
- 3.5寸屏
- 芯片NT35310,337.5Kb显存;
- 分辨率480*320
- 16位数据565格式
- 触摸芯片XPT2046;
- 电气连接:
- CS:片选信号
- WR:写入数据
- RD:读取数据
- D[15:0]:16位双向数据线
- RST:复位,与MCU复位接一起;
- RS:命令/数据标志(0:读写命令,1:读写数据)------------->连接在:FMC_A18 / PD13,注意地址偏移量的计算:A18; 简单的公式:2^19=0x80000; 起始基地址就是:0x80000 - 0x02(2个字节) = 0x7fffe;
- 背光信号:------------->连接在:PB5
- 控制原理:
- SRAM控制线;
- 地址线:A0~A18;
- 数据线:D0~D15;------------->LCD_D[15:0]连接在:FMC_D[15:0]
- 写信号:WE------------->LCD_WR连接在:FMC_NWE / PD5
- 读信号:OE------------->LCD_RD连接在:FMC_NOE / PD4
- 片选信号:CS------------->LCD_CS 连接在:FMC_NE1 / PD7(此节用的SRAM块1)
- 字节控制:UB/LB------------->NC
- 与TFT信号线区别:两者只是没有地址线的区别
- TFT用SRAM控制实现方式:
- LCD的RS信号决定了传送给LCD的数据是命令or数据,本质上可以理解为一个地址信号;
- 比如我们把RS接在地址A0上;
- 当FMC控制写地址0的时候,A0 = 0; 对于LCD来说就是写命令;
- -------------------------1---------,-------1,-----------------------写数据;
- 这样数据和命令就区分开了,对于SRAM也就是操作连续2个地址(定义个结构体,地址自增);
- SRAM控制线;
- 存储器映射:
- 框图:
- 上图中,FMC有6个存储块(BANK)管理1536MB空间,本节只介绍bank1的相关配置;
- Bank1简述:
- 每个块被分为4个区,每个区管理64M空间,都有独立的寄存器进行相应配置;
- Bank1的256M空间由28根地址线(HADDR[27:0])寻址;
- 存储器地址映射表:
- FMC各bank配置寄存表:
- 通过FMC_BCRx、FMC_BTRx、FMC_BWTRx这3个寄存器,可以设置外部存储器的时序参数、速度范围;
- 访问模式:
- 同步突发访问:主要参数:
- 分频系数:HCLK系统时钟分频,给外部存储器做同步信号
- 等待延迟:DATLAT,同步突发访问中获得第1个数据所需的等待延时;
- 异步突发访问:(本节选用方式)
- 地址建立时间:ADDSET
- 数据建立时间:DATAST
- 地址保持时间:ADDHLD
- 时序模型:本节选用异步模式A
- 模式A的读写时序是分开的:
- 通常读数据较慢,写较快;
- 如果两个时序相同,会导致写的时序也变慢;
- 虽然可以在写or读的时候,重新配置FMC延时,操作完成后,再配置成读or 写操作,频繁配置,过于麻烦;
- 模式A读操作时序 :
- 模式A写操作时序:
- 注意:中文参考手册中翻译误,读/写都译成读操作时序;
- 液晶芯片NT35310读/写时序表:
- 读操作时间参数配置:
- 地址建立时间:ADDSET————>RD低电平持续时间:150ns
- 数据建立时间:DATAST————>RD高电平持续时间:250ns
- 地址保持时间:ADDHLD————>用的模式A不包含此项,直接设置为:0;
- 写操作时间参数配置:
- 地址保持时间:ADDHLD————>用的模式A不包含此项,直接设置为:0;
- 数据建立时间:DATAST————>WR高电平持续时间:19ns
- 地址建立时间:ADDSET————>WR低电平持续时间:19ns
- 初始化流程:
- 打开GPIO、FMC时钟;
- 初始化相应I/O,配置模式,速度,映射关系;
- FMC接口时序参数初始化,选择SRAM接口(LCD)
- LCD芯片初始化(向厂家索取初始化例程)
- 初始化例程:
/********************************************************* * 函数名:BSP_LCD_Init() * 描述 : * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **********************************************************/ void BSP_LCD_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; FMC_NORSRAM_TimingTypeDef FMC_NORSRAM_TimingWrite; //写时序 FMC_NORSRAM_TimingTypeDef FMC_NORSRAM_TimingRead; //读时序 __HAL_RCC_GPIOB_CLK_ENABLE(); //开启GPIOB时钟 GPIO_InitStruct.Pin=GPIO_PIN_5; //PB5,背光控制 GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出 GPIO_InitStruct.Pull=GPIO_PULLUP; //上拉 GPIO_InitStruct.Speed=GPIO_SPEED_HIGH; //高速 HAL_GPIO_Init(GPIOB,&GPIO_InitStruct); BSP_LCD_MPU_Config(); SRAM_Handle.Instance=FMC_NORSRAM_DEVICE; SRAM_Handle.Extended=FMC_NORSRAM_EXTENDED_DEVICE; SRAM_Handle.Init.NSBank=FMC_NORSRAM_BANK1; //使用NE1 SRAM_Handle.Init.DataAddressMux=FMC_DATA_ADDRESS_MUX_DISABLE; //不复用数据线 SRAM_Handle.Init.MemoryType=FMC_MEMORY_TYPE_SRAM; //SRAM SRAM_Handle.Init.MemoryDataWidth=FMC_NORSRAM_MEM_BUS_WIDTH_16; //16位数据宽度 SRAM_Handle.Init.WriteOperation=FMC_WRITE_OPERATION_ENABLE; //存储器写使能 SRAM_Handle.Init.ExtendedMode=FMC_EXTENDED_MODE_ENABLE; //读写使用不同的时序 //FSMC读时序控制寄存器 FMC_NORSRAM_TimingRead.AddressSetupTime=15; //地址建立时间(ADDSET)为15个HCLK 1/216M=4.6ns*15=69ns FMC_NORSRAM_TimingRead.AddressHoldTime=0x00; FMC_NORSRAM_TimingRead.DataSetupTime=80; //数据保存时间(DATAST)为85个HCLK =4.6*80=368ns FMC_NORSRAM_TimingRead.AccessMode=FMC_ACCESS_MODE_A; //模式A //FSMC写时序控制寄存器 FMC_NORSRAM_TimingWrite.AddressSetupTime=15; //地址建立时间(ADDSET)为15个HCLK=69ns FMC_NORSRAM_TimingWrite.AddressHoldTime=0x00; FMC_NORSRAM_TimingWrite.DataSetupTime=15; //数据保存时间(DATAST)为4.6ns*15个HCLK=69ns FMC_NORSRAM_TimingWrite.AccessMode=FMC_ACCESS_MODE_A; //模式A HAL_SRAM_Init(&SRAM_Handle,&FMC_NORSRAM_TimingRead,&FMC_NORSRAM_TimingWrite); delay_ms(50); // delay 50 ms BSP_LCD_InitID(); //芯片指令初始化; BSP_LCD_Display_Dir(0); //默认为竖屏 BSP_LCD_BL_LED(1); //点亮背光 BSP_LCD_Clear(RED); //清屏 }
- 快速打点/写某点颜色函数:
/********************************************************* * 函数名:BSP_LCD_Fast_DrawPoint(u16 x,u16 y,u32 color) * 描述 :将X,Y坐标的颜色,设置成color所表示的颜色值; * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **********************************************************/ void BSP_LCD_Fast_DrawPoint(u16 x,u16 y,u32 color) { if(BSP_LCD_InitStructure.id==0X5310) { BSP_LCD_WR_REG(BSP_LCD_InitStructure.setxcmd); BSP_LCD_WR_DATA(x>>8); BSP_LCD_WR_DATA(x&0XFF); BSP_LCD_WR_REG(BSP_LCD_InitStructure.setycmd); BSP_LCD_WR_DATA(y>>8); BSP_LCD_WR_DATA(y&0XFF); } BSP_LCD->LCD_REG=BSP_LCD_InitStructure.gramcmd; BSP_LCD->LCD_RAM=color; }
- 填充函数:
/********************************************************* * 函数名:BSP_LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u32 color) * 描述 :在指定区域内填充成指定的color颜色, (sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1); * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **********************************************************/ void BSP_LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u32 color) { u16 i,j; u16 xlen=0; xlen=ex-sx+1; for(i=sy;i<=ey;i++) { BSP_LCD_SetCursor(sx,i); //设置光标位置 BSP_LCD_WriteRAM_Prepare(); //开始写入GRAM for(j=0;j<xlen;j++) BSP_LCD->LCD_RAM=color; //显示颜色 } }
- 读某点颜色函数:
/********************************************************* * 函数名:BSP_LCD_ReadPoint(u16 x,u16 y) * 描述 :读取X,Y坐标的颜色,并返回; * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **********************************************************/ u32 BSP_LCD_ReadPoint(u16 x,u16 y) { u16 r=0,g=0,b=0; if(x>=BSP_LCD_InitStructure.width||y>=BSP_LCD_InitStructure.height) return 0; //超过了范围,直接返回 BSP_LCD_SetCursor(x,y); if(BSP_LCD_InitStructure.id==0X5310) BSP_LCD_WR_REG(0X2E);// 发送读GRAM指令 r=BSP_LCD_RD_DATA(); //dummy Read __NOP();__NOP();__NOP(); //NT35510要分2次读出 r=BSP_LCD_RD_DATA(); //实际坐标颜色 __NOP();__NOP();__NOP(); b=BSP_LCD_RD_DATA(); g=r&0XFF; //对于9341/5310/5510,第一次读取的是RG的值,R在前,G在后,各占8位 g<<=8; return (((r>>11)<<11)|((g>>10)<<5)|(b>>11)); //ILI9341/NT35310/NT35510需要公式转换一下 }
- 测试程序:
- 无
- 总结:上述几个函数移植emwin的时候要用到,细细品;
- 参考资料:
- 正点原子:STM32F7 开发指南(HAL 库版)
- 野火:STM32 HAL 库开发实战指南
- 官方例程
- 同步突发访问:主要参数:
【12】、STM32F767——————>FMC之LCD屏
最新推荐文章于 2024-07-24 15:46:43 发布