【12】、STM32F767——————>FMC之LCD屏

  1. FMC介绍:LTDC章节已经介绍过,此处省略; 
  2. 框图:
    1. FMC把外部设备分为:NOR/PSRAM、NAND、SDRAM,共用地址、数据线和若干信号线;
    2. 液晶屏介绍LTDC章节介绍过,从简,不写;
  3. 屏幕参数:
    1. 3.5寸屏
    2. 芯片NT35310,337.5Kb显存; 
    3. 分辨率480*320
    4. 16位数据565格式
    5. 触摸芯片XPT2046;
  4. 电气链接:
    1. CS:片选信号
    2. WR:写入数据
    3. RD:读取数据
    4. D[15:0]:16位双向数据线
    5. RST:复位,与MCU复位接一块儿; 
    6. RS:命令/数据标志(0:读写命令,1:读写数据)------------->链接在:FMC_A18 / PD13,注意地址偏移量的计算:A18; 简单的公式:2^19=0x80000; 起始基地址就是:0x80000 - 0x02(2个字节) = 0x7fffe;
    7. 背光信号:------------->链接在:PB5
  5. 控制原理:
    1. SRAM控制线;
      1. 地址线:A0~A18;
      2. 数据线:D0~D15;------------->LCD_D[15:0]链接在:FMC_D[15:0]
      3. 写信号:WE------------->LCD_WR链接在:FMC_NWE / PD5
      4. 读信号:OE------------->LCD_RD链接在:FMC_NOE / PD4
      5. 片选信号:CS------------->LCD_CS 链接在:FMC_NE1 / PD7(此节用的SRAM块1)
      6. 字节控制:UB/LB------------->NC
    2. 与TFT信号线区别:二者只是没有地址线的区别
    3. TFT用SRAM控制实现方式:
      1. LCD的RS信号决定了传送给LCD的数据是命令or数据,本质上能够理解为一个地址信号;
      2. 好比咱们把RS接在地址A0上;
        1. 当FMC控制写地址0的时候,A0 = 0; 对于LCD来讲就是写命令; 
        2. -------------------------1---------,-------1,-----------------------写数据;
      3. 这样数据和命令就区分开了,对于SRAM也就是操做连续2个地址(定义个结构体,地址自增);
  6. 存储器映射:
    1. 框图:
    2. 上图中,FMC有6个存储块(BANK)管理1536MB空间,本节只介绍bank1的相关配置;
  7. Bank1简述:
    1. 每一个块被分为4个区,每一个区管理64M空间,都有独立的寄存器进行相应配置;
    2. Bank1的256M空间由28根地址线(HADDR[27:0])寻址;
    3. 存储器地址映射表:
    4. FMC各bank配置寄存表:
    5. 经过FMC_BCRx、FMC_BTRx、FMC_BWTRx这3个寄存器,能够设置外部存储器的时序参数、速度范围;
    6. 访问模式:
      1. 同步突发访问:主要参数:
        1. 分频系数:HCLK系统时钟分频,给外部存储器作同步信号
        2. 等待延迟:DATLAT,同步突发访问中得到第1个数据所需的等待延时; 
      2. 异步突发访问:(本节选用方式)
        1. 地址创建时间:ADDSET
        2. 数据创建时间:DATAST
        3. 地址保持时间:ADDHLD
      3. 时序模型:本节选用异步模式A
      4. 模式A的读写时序是分开的:
        1. 一般读数据较慢,写较快;
        2. 若是两个时序相同,会致使写的时序也变慢;
        3. 虽然能够在写or读的时候,从新配置FMC延时,操做完成后,再配置成读or 写操做,频繁配置,过于麻烦;
      5. 模式A读操做时序 :
      6. 模式A写操做时序:
      7. 注意:中文参考手册中翻译误,读/写都译成读操做时序;
      8. 液晶芯片NT35310读/写时序表:
      9. 读操做时间参数配置:
        1. 地址创建时间:ADDSET————>RD低电平持续时间:150ns
        2. 数据创建时间:DATAST————>RD高电平持续时间:250ns
        3. 地址保持时间:ADDHLD————>用的模式A不包含此项,直接设置为:0;
      10. 写操做时间参数配置:
        1. 地址保持时间:ADDHLD————>用的模式A不包含此项,直接设置为:0;
        2. 数据创建时间:DATAST————>WR高电平持续时间:19ns
        3. 地址创建时间:ADDSET————>WR低电平持续时间:19ns
      11. 初始化流程:
        1. 打开GPIO、FMC时钟;
        2. 初始化相应I/O,配置模式,速度,映射关系; 
        3. FMC接口时序参数初始化,选择SRAM接口(LCD)
        4. LCD芯片初始化(向厂家索取初始化例程)
      12. 初始化例程:
        /*********************************************************
         * 函数名: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);     //清屏
        }

         

      13. 快速打点/写某点颜色函数:
        /*********************************************************
         * 函数名: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; 
        }

         

      14. 填充函数:
        /*********************************************************
         * 函数名: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;	//显示颜色 	    
        	}  
        }

         

      15. 读某点颜色函数:
        /*********************************************************
         * 函数名: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须要公式转换一下
        }

         

      16. 测试程序:
      17. 总结:上述几个函数移植emwin的时候要用到,细细品;
      18. 参考资料:
        1. 正点原子:STM32F7 开发指南(HAL 库版)
        2. 野火:STM32 HAL 库开发实战指南
        3. 官方例程