zoukankan      html  css  js  c++  java
  • FSMC(STM32)

    

    (一个)FSMC:Flexible Static Memory Controller,变量(灵活)静态存储控制器

    小容量产品是指闪存存储器容量在1 6K32K字节之间的STM32F101xxSTM32F102xx

    STM32F103xx微控制器。 

    中容量产品是指闪存存储器容量在64K128K字节之间的STM32F101xxSTM32F102xx

    STM32F103xx微控制器。 

    容量产品是指闪存存储器容量在256K512K字节之间的STM32F101xxSTM32F103xx微控

    制器。 

    互联型产品是指STM32F105xxSTM32F107xx微控制器。

     

     

    对于M3来说

     

     然后将这1.0GB的外存分为4个大块

     

    1。为什么每一块中每一片是64M?

    答:我们知道地址线26跟,2的26次方等于64M,所以每一个块是64M,

    2。为什么每一块中是4片?

    答:它这里有一个非常巧妙的方法每个块有4个片选。以方便我们使用那一片;

     

    故:1.0GB =  (4*64)*4

     

    下面例程我们的液晶是接在Bank1中的第4片;

    先看下接口图(野火板子)

    1,为什么是片4?

    答:

     

    我们的LCD_CS接在了FSMC_NE4的片选4端(说白了是:液晶的内存与FSMC要相互相应)

    2,为什么是块1?

    答:由于液晶里面的RAM相当于NOR FLASH,或者PSRAM,所以最好用块1

    3,为什么低电平电量点亮屏幕呢?

    答:看下图

     

     对于38,39管脚的控制使用一个PNP三极管,当LIGHT低电平时 导通。

    为什么接PB1?

    答:PB1通过有PWM调制功能

    4,对于读写控制可參考图中注解,但主要对于不同的液晶控制芯片读写控制可能有所差异。

    如图9341

     

    RS 我们接的是FSMC_A23,那么我们控制FSMC的地址线23就能够控制发送命令还是数据了

     

    程序解说:

    1,载入ili9341驱动文件

    2,打开

    /* #include "stm32f10x_flash.h" */
    #include "stm32f10x_fsmc.h"
    

     3,port配置

     4。工作模式配置(參考ili9341手冊)

    void LCD_FSMC_Config(void)
    {
        FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
        FSMC_NORSRAMTimingInitTypeDef  p; 
        
        
        p.FSMC_AddressSetupTime = 0x02;	 //地址建立时间
        p.FSMC_AddressHoldTime = 0x00;	 //地址保持时间
        p.FSMC_DataSetupTime = 0x05;		 //数据建立时间
        p.FSMC_BusTurnAroundDuration = 0x00;
        p.FSMC_CLKDivision = 0x00;
        p.FSMC_DataLatency = 0x00;
        p.FSMC_AccessMode = FSMC_AccessMode_B;	 // 一般使用模式B来控制LCD
    
        FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;
        FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
        //FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
      FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;
        FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
        FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
        FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
        FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
        FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
        FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
        FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
        FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
        FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
        FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
        FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;  
        
        FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); 
        FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);
    }
    

    FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;//此处我们用到了bank1的第四片

    FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;//此处我们用到了bank1的第四片

    5。液晶软件复位(低电平复位,切记高电平要保持一下)

    void LCD_Rst(void)
    {			
    		GPIO_ResetBits(GPIOG, GPIO_Pin_11);	 //低电平复位
        Lcd_Delay(0xAFFf<<2); 					   
        GPIO_SetBits(GPIOG, GPIO_Pin_11);		 	 
        Lcd_Delay(0xAFFf<<2); 	
    }
    

     6。写命令、数据

    void LCD_REG_Config(void)

    这里介绍一下写命令与写数据函数

    	LCD_ILI9341_CMD(0xCF);      //写命令
    	LCD_ILI9341_Parameter(0x00);   //写数据
    

     例如以下:

    #define Bank1_LCD_C    ((u32)0x6C000000)	   //Disp Reg ADDR
    #define Bank1_LCD_D    ((u32)0x6D000000)       //Disp Data ADDR       // A23 PE2
    
    //选定LCD指定寄存器
    #define LCD_WR_REG(index)    ((*(__IO u16 *) (Bank1_LCD_C)) = ((u16)index))
    //往LCD GRAM写入数据
    #define LCD_WR_Data(val)       ((*(__IO u16 *) (Bank1_LCD_D)) = ((u16)(val)))
    
    #define LCD_ILI9341_CMD(index)       LCD_WR_REG(index)
    #define LCD_ILI9341_Parameter(val)	 LCD_WR_Data(val)
    

     解释例如以下:

     当主控对指针量(地址)0x6D000000操作,FSMC_A23为高电平,此时为写数据;

    操作顺序: CPU作用于FSMC外设。FSMC内存块作用于TFT的GRAM。

    可理解CPU向0x6C000000。0x6D000000该地址写入数据,即使操作FSMC的块1的片选4,后导致FSMC外设地址线和数据线管脚的变化。

     为什么2^23 还要*2 ?

    答:

     

     在外部设备是16位时。连接到内部地址总线 HADDR时 左移一位。0-1,,。,24-25;所以为了满足相应关系。我们要将指针量*2,才干找出正确的地址后与之相应;

    若连接其它的地址线,那么计算方式一样。

     7。扫描方式

    	DEBUG_DELAY();
    	LCD_ILI9341_CMD(0x36); 	
    	LCD_ILI9341_Parameter(0xC8);    //竖屏  左上角(起点)到右下角(终点)扫描方式
    	DEBUG_DELAY();
    

     向“36” 寄存器 写相应指令就成

    	/* column address control set */   X轴
    	LCD_ILI9341_CMD(0X2A); 
    	LCD_ILI9341_Parameter(0x00);    //低八位  0
    	LCD_ILI9341_Parameter(0x00);   //高八位
    	LCD_ILI9341_Parameter(0x00);  
    	LCD_ILI9341_Parameter(0xEF);       0XEF = 239
    	
    	/* page address control set */   Y轴
    	DEBUG_DELAY();
    	LCD_ILI9341_CMD(0X2B); 
    	LCD_ILI9341_Parameter(0x00);        0
    	LCD_ILI9341_Parameter(0x00);
    	LCD_ILI9341_Parameter(0x01);
    	LCD_ILI9341_Parameter(0x3F);       0X13F = 319  
    

     ---------------------------------------------------------------------------

    函数部分:

    ①清屏函数(源)

    void LCD_Clear(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color)
    

     如清掉整个屏幕

    LCD_Clear(0, 0, 240, 320, BACKGROUND);

    ②设置坐标点(源)

    void LCD_SetCursor(uint16_t x, uint16_t y)
    

    ③ 开窗(源)

    界限设置。不然就不会反过来写(第一行写完。然后从第二行写),调整地址指针

    void LCD_OpenWindow(uint16_t x, uint16_t y, uint16_t width, uint16_t height)
    

     ④画点(源)

    一切一切的本源

    void LCD_SetPoint(uint16_t x , uint16_t y , uint16_t color)	
    {	
    	LCD_SetCursor(x, y);
    	LCD_ILI9341_CMD(0x2c);	    
    	LCD_WR_Data(color);
    }
    

     ⑤颜色(源)

    uint16_t LCD_RD_data(void)	
    {	
    	uint16_t R=0, G=0, B=0 ;
    
    	R = *(__IO uint16_t *)Bank1_LCD_D; 	  /*FIRST READ OUT DUMMY DATA*/
    	R = *(__IO uint16_t *)Bank1_LCD_D;  	/*READ OUT RED DATA  */
    	B = *(__IO uint16_t *)Bank1_LCD_D;  	/*READ OUT BLACK DATA*/
    	G = *(__IO uint16_t *)Bank1_LCD_D;  	/*READ OUT GREEN DATA*/
          //将地址转换成指针,对指针进行操作
    	
        return (((R>>11)<<11) | ((G>>10)<<5) | (B>>11));  //转换成16位宽度
    }
    

     ⑥显示一个字符(源)

    void LCD_DispChar(uint16_t x, uint16_t y, uint8_t ascii, uint16_t color)
    

    如:LCD_DispChar(60, 60, 'A', RED); //相应有效的地方写该颜色,这个函数也是独立的。

    当然在用之前要有自己相应的的字库

     ⑦显示一个字符串

    void LCD_DispStr(uint16_t x, uint16_t y, uint8_t *pstr, uint16_t color)
    

     如:

     LCD_DispStr(10, 10, (uint8_t *)"This is a lcd demo to display ascii", RED); 

     

     ⑧显示数字

    这个说白还是用到LCD_DispChar

    void LCD_DisNum(uint16_t x, uint16_t y, uint32_t num, uint16_t color)
    

     

                                                                 瘋子笔录

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    Jenkins服务器磁盘空间爆满问题解决
    U3D GPU蒙皮
    关于STRUCT优化的一个点
    UNITY优化资料收集
    U3D的结构体堆分配栈分配
    【转】UGUI研究院之缓存策略让UI打开更快(三十)
    关于U3D场景烘焙的一个想法
    【摘】如果医生给你的孩子开这些药,请主动说不!
    【转】投影矩阵的推导
    Optimizing graphics performance
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4741900.html
Copyright © 2011-2022 走看看