STM32FMSC LCD難點解析:
以下是網上和自己整理的:感覺應該可以把STM32 ----FSMCLCD中的關鍵RS說清楚~
----------------------------------------------------------------------------------------------------------------------
第一個角度理解STM32有FSMC(其實其他芯片基本都有類似的總線功能),FSMC的好處就是你一旦設置好之後,WR(寫)、RD(讀)、DB0-DB15這些控制線和數據線,
都是FSMC自動控制的。打個比方,當你在程序中寫到:
*(volatile unsigned short int*)(0x60000000)=val;
那麼FSMC就會自動執行一個寫的操作,其對應的主控芯片的WE、RD這些腳,就會呈現出寫的時序出來(即WE=0,RD=1),數據val的值也
會通過DB0-15自動呈現出來(即FSMC-D0:FSMC-D15=val )。地址0x60000000會被呈現在數據線上(即A0-A25=0,地址線的對應最麻煩,要根據具體情況來,好好看看FSMC手冊)。
那麼在硬件上面,我們需要做的,僅僅是MCU和LCD控制芯片的連接關係:
WE-WR,均爲低電平有效
RD-RD,均爲低電平有效
FSMC-D0-15接LCD DB0-15
FSMC_NE1--CS接PD7
連接好之後,讀寫時序都會被FSMC自動完成。但是還有一個很關鍵的問題,就是RS沒有接因爲在FSMC裏面,根本就沒有對應RS。怎麼辦呢?這個時候,有一個好方法,就是用某一根地址線來接RS。比如我們選擇了A16這根地址線來接,那麼當我們要寫寄
存器的時候,我們需要RS,也就是A16(RS爲高)置高。軟件中怎麼做呢?也就是將FSMC要寫的地址改成0x60020000,如下:
*(volatile unsigned short int*)(0x60020000)=val;
這個時候,A16在執行其他FSMC的同時會被拉高,因爲A0-A18要呈現出地址0x60020000。0x60020000裏面的Bit17=1,就會導致A16爲1。
當要讀數據時,地址由0x60020000改爲了0x60000000,這個時候A16就爲0了。
那麼有朋友就會有疑問,第一,爲什麼地址是0x6xxxxxxx而不是0x0xxxxxxx;第二,CS怎麼接;第三,爲什麼Bit17對應A16?
RS問題:RS爲0表示;讀寫寄存器;RS爲1,讀寫數據RAM;
先來看前兩個問題,大家找到STM32的FSMC手冊,在FSMC手冊裏面,我們很容易找到,FSMC將0x60000000-0x6fffffff的地址用作NOR/PRAM(
共256M地址範圍)。而這個存儲塊,又被分成了四部分,每部分64M地址範圍。當對其中某個存儲塊進行讀寫時,對應的NEx就會置低。這裏,
就解決了我們兩個問題,第一,LCD的操作時序,和NOR/PRAM是一樣的(爲什麼一樣自己找找NOR/PRAM的時序看看),所以我們選擇0x6xxxxxxx
這個地址範圍(選擇這個地址範圍,操作這個地址時,FSMC就會呈現出NOR/PRAM的時序)。第二,我們可以將NEx連接到LCD的CS,只要我們操作
的地址是第一個存儲塊內即可(即0-0x3ffffff地址範圍)。
第三個問題再來看一看FSMC手冊關於存儲器字寬的描述,我們發現,當外部存儲器是16位時,硬件管腳A0-A24表示的是地址線A1-A25的值,所以
我們要位移一下,Bit17的值,實際會被反應到A16這根IO來。關於數據寬度及位移的問題,初學的朋友可能會比較疑惑,當你接觸了多NOR/PRAM
這樣的器件後,你會發現,很多芯片的總線,都是這樣設計的,爲的是節省地址線。
第二個角度理解:
FSMC總線上看,LCD只有2個地址.
Bank1_LCD_C是寫寄存器,此時RS=1,告訴LCD我在總線上輸出數據的是寄存器的地址
Bank1_LCD_D是寫數據,此時RS=0,告訴LCD我在總線上輸出地數據是寄存器的數據或者GRAM的數據.
寫寄存器數據按2步來:
第一步先往Bank1_LCD_C(對應RS=1),送寄存器的地址:*(__IOuint16_t *) (Bank1_LCD_C)=index; 接着在Bank1_LCD_D這個地址(對應RS=0),寫入剛指向的寄存器的數據:*(__IO uint16_t *) (Bank1_LCD_D)= val;
爲什麼*(__IO uint16_t *) (Bank1_LCD_C)=index; 就是往LCD 寫寄存器呢?
這是一個16位的IO賦值操作,地址是Bank1_LCD_C,這個地址就是指向FSMC的Bank1的NE1對應的地址空間。而LCD片選正是連接到NE1,具體地址要看RS接到哪一根地址線上。當CPU執行到這一條的時候,就會通過FSMC總線控制器在數據總線上進行一個地址爲Bank1_LCD_C的數據寫操作,此操作自動完成CS信號,
RD信號,WR信號,以及地址總線數據(RS信號)的輸出以及數據總線數據的輸出.
其他的操作都是這兩個操作組合完成。也就是我上面所說的,
"所有的寄存器地址和寄存器數據,以及GRAM數據都是通過IO0-IO15完成傳輸的,而不是FSMC的地址.這是容易搞混的一個地方.LCD的FSMC地址只有一根,就是RS."
----------------------------------------------------------------------------------------------------------------------第三個角度理解:
把TFT看做類似SRAM的存儲器,只能接在BANK1上。對應基地址是0x60000000.
而BANK1又有劃分爲四個片選,分別對應基地址:
NE1 0x600000000
NE2 0x640000000
NE3 0x680000000
NE4 0x6C0000000
所以每個NEx能尋址的空間大小爲64M,也就是對應了FSMC的A0到A25共26根地址線.
假如使用NE4接到爲LCD的片選CS上,那麼就對應基地址0x6C000000,
如果RS接到地址線的A0上,那麼當RS爲0時對應的地址就是 LCD_REG =0x6C000000,(其實你用0x6CFFFFF0是一樣的,因爲只用到一根地址線).
RS爲1時對應的地址就是 LCD_RAM=0x6C000001,(0x6CFFFFF1一樣對應LCD_RAM,因爲它一樣對應 RS=1).
如果RS接到 其他地址線上,情況是類似的。
比如接到An上,那麼
LCD_REG=0x6C000000,
LCD_RAM= 0x6C000000 |(1<<n)
注意這個地址不是唯一的,只要這個地址能尋址到BANK1 的NE4上而且使RS=0,那麼就是LCD_REG,使RS=1,就是LCD_RAM.
----------------------------------------------------------------------------------------------------------------------
對應Bank1_LCD_C的地址,FSMC總線控制器在RS接的那根地址線輸出的是1,而對應Bank1_LCD_D,輸出的0.
RS接的可不是GPIO,是FSMC地址總線的一根.FSMC進行讀寫操作的時候會在地址總線根據要讀寫的地址輸出電平的.
RS接哪一根地址線雖然沒有固定要求,但是一旦你確定要接哪一根,那麼Bank_LCD_C和Bank_LCD_D也要隨之確定,這可不是“自動的".
雖然沒有手動操作GPIO來操作RS,但是你敲代碼的時候可是手動指定Bank1_LCD_C 或者 Bank1_LCD_D,從而確定RS的電平.
所謂的“自動”是指:不是通過操作GPIO來操作RS,而是直接根據地址總線地址的不同來完成操作RS,這兩種方法的速度差別是非常大的.
如果是GPIO方式,先要通過操作GPIO分別輸出RS,CS,等的電平,然後再通過過GPIO操作輸出數據,然後還要通過GPIO再操作RD,WR,CS等的電平。
每操作一個GPIO都要好幾個週期,加起來就非常慢了.
而FSMC是在一個FSMC寫週期內就完成了這所有的動作。
*******************************************************************************
#defineBank1_LCD_R ((uint32_t)0x60000000) //disp Reg ADDR
#defineBank1_LCD_D ((uint32_t)0x60020000) //disp Data ADDR
從STM32FMSC系統手冊可以看到:
FSMC其實就相當於外部總線存儲器和內部AHB總線的接口:而AHB是32位的,當外接NOR/LCD時,而外部存儲器的數據寬度可以選擇8位和16位的,這時候就存在一個地址轉換的問題即32位和8位或者16位地址轉換的問題。解決這個問題STM32採用的HADDR[25:0],它的作用就是將外部存儲器地址轉換爲AHB地址線。
其中:
並且無論外部存儲器的寬度是多少位,FSMC_A[0]始終連接到外部存儲器的A[0];
|
|
|
FSMC_NE1(片選)
|
①HADDR[25:0]總共26位線,可以尋址64M的地址空間,而AHB總線是32位寬度,所以能尋址0x00000000~0xFFFF FFFF;在這裏我們只是指定了FMSC控制器塊1的地址爲0x60000000。尋址空間0x6000 0000~0x63ff ffff;
②LCD手冊相關知識:(9320或者hx8312都一樣)
RS引腳決定是寄存器命令還是顯示RAM數據。寄存器指令的輸入數據是16位,前8位是地址,後8位是數據。
不同的MPU類型寄存器命令和數據總線的格式不同。並且對應輸入總線:有一下對應關係:
對於SPI方式,則用以下對應關係:
(2)顯示RAM數據格式和系統接口輸入總線之間的聯繫
問題:RS如何選擇:
#defineBank1_LCD_R ((uint32_t)0x60000000) //disp Reg ADDR
#defineBank1_LCD_D ((uint32_t)0x60020000) //disp Data ADDR
這裏LCD選取的16位,將RS接在A16,則HADDR[25:1]對應FSMC_A[24:0];關鍵在於爲什麼???
從上面可以看出,LCD除了需要數據線之外,額外的地址線是不需要的~~~~~但是在STM32在進行FSMC總線操作時,所有的地址線還是會出現時序的,但是操縱LCD不需要額外的地址線了,也就是FSMC_A[16:25]可以解放了,但是要注意一旦配置了FSMC,這些管腳還是會出現時序的;
現在我們向0x60000000這個塊地址送出數據,當然這些數據肯定是16位的,因爲是16位的LCD,由於RS(A16)爲0,所以這個讀寫寄存器的操作;當向0x60020000寫數據時,由於總線時序是要有地址寫的,這時bit17就爲高了,也就是RS爲1了,這時所進行的操作就是讀寫RAM了!!!!
其中RS的選擇可以是任意的,但一般還是選擇,不用的地址線爲好~~~~~