FSMC接口介紹
大容量,且引腳數(shù)在 100 腳以上的 STM32F103 芯片都帶有 FSMC 接口。
FSMC,即靈活的靜態(tài)存儲(chǔ)控制器flexible static memory controller。
擴(kuò)展內(nèi)存
- STM32 的 FSMC 接口支持包括 SRAM、NAND FLASH、NOR FLASH 和 PSRAM 等存儲(chǔ)器。
何為PSRAM
- FSMC就是一個(gè)MCU與外部存儲(chǔ)器(SRAM,FLASH等)讀寫數(shù)據(jù)的一個(gè)接口
FSMC內(nèi)部原理
FSMC 的框圖
- NE[4-1] 片選,用來區(qū)分不同設(shè)備
- NWE為寫。
- NOE為讀
- n低電平有效
- o output
- e 使能
驅(qū)動(dòng)SRAM
- FSMC驅(qū)動(dòng)外部SRAM時(shí),外部SRAM的控制一般有
- 地址線(如A0-A25)
- 數(shù)據(jù)線(如D0-D15)
- 寫信號(hào)(WE,即WR)
- 讀信號(hào)(OE,即RD)
- 片選信號(hào)(CS)
- 如果SRAM支持字節(jié)控制,那么還有UB/LB信號(hào)。
驅(qū)動(dòng)TFTLCD
-
真正在操作LCD的時(shí)候需要用到的就只有:
- RS、D0~D15、WR、RD和CS。
-
其操作時(shí)序和SRAM的控制完全類似,唯一不同就是TFTLCD有RS信號(hào),但是沒有地址信號(hào)。(所以將RS當(dāng)做地址線來用)
(該表格為F407的,與103不太一樣,僅看個(gè)大概意思) -
TFTLCD通過RS信號(hào)來決定傳送的數(shù)據(jù)是數(shù)據(jù)還是命令,本質(zhì)上可以理解為一個(gè)地址信號(hào)
- 比如我們把*RS接在A0上面
- 那么當(dāng)FSMC控制器寫地址0的時(shí)候,會(huì)使得A0變?yōu)?,對(duì)TFTLCD來說,就是寫命令。而FSMC寫地址1的時(shí)候,A0將會(huì)變?yōu)?,對(duì)TFTLCD來說,就是寫數(shù)據(jù)了。
- 當(dāng)然RS也可以接在其他地址線上,而探索者STM32F4把RS接在A6上面。
-
因此,可以把TFTLCD當(dāng)成一個(gè)SRAM來用,只不過這個(gè)SRAM有2個(gè)地址,這就是FSMC可以驅(qū)動(dòng)LCD的原理。
FSMC內(nèi)存劃分
FSMC的分塊
STM32的 FSMC將外部存儲(chǔ)器劃分為固定大小為 256M 字節(jié)的四個(gè)存儲(chǔ)塊(Bank),F(xiàn)SMC 總共管理 1GB 空間.
如下為FSMC在CPU中的地址映射劃分。
各模塊配置的地址范圍
存儲(chǔ)塊1的介紹
每個(gè)區(qū)的地址范圍可看下文
存儲(chǔ)塊1的分區(qū)
STM32 的 FSMC 存儲(chǔ)塊 1(Bank1)被分為 4 個(gè)區(qū),每個(gè)區(qū)管理 64M 字節(jié)空間,每個(gè)區(qū)都有獨(dú)立的寄存器對(duì)所連接的存儲(chǔ)器進(jìn)行配置。(所以它有四個(gè)不同的片選,可以接不同的外設(shè))
存儲(chǔ)塊1的地址
Bank1 的 256M 字節(jié)空間由 28 根地址線(HADDR[27:0])尋址。
HADDR 是需要轉(zhuǎn)換到外部設(shè)備的內(nèi)部 AHB 總線地址,一個(gè)地址對(duì)應(yīng)八位數(shù)據(jù)。
其中 HADDR[25:0]來自外部存儲(chǔ)器地址FSMC_A[25:0],直接對(duì)應(yīng)地址總線 。
HADDR[27:26]位用于選擇四個(gè)存儲(chǔ)塊之一。
但[0:25]卻需要根據(jù)不同位寬討論。
不同區(qū)的地址范圍
不同數(shù)據(jù)寬度對(duì)存儲(chǔ)塊1尋址的影響
需要或者可以訪問的地址空間大小。
當(dāng)Bank1接的是16位寬度存儲(chǔ)器的時(shí)候:HADDR[25:1],F(xiàn)SMC_A[24:0]
- 當(dāng)psram地址為0x0001(16)時(shí),對(duì)應(yīng)ARMM地址0x000002(24)
- 當(dāng)psram地址為0x0002(16)時(shí),對(duì)應(yīng)ARMM地址0x000004(24)
當(dāng)Bank1接的是8位寬度存儲(chǔ)器的時(shí)候:HADDR[25:0],F(xiàn)SMC_A[25:0]
不論外部接8位/16位寬設(shè)備,F(xiàn)SMC_A[0]永遠(yuǎn)接在外部設(shè)備地址A[0]
可以區(qū)分一下,F(xiàn)SMC即為外部存儲(chǔ)器的地址,是FSMC端的,HADDR是AHB總線端的
CPU發(fā)出兩個(gè)地址,去接受一個(gè)16位的數(shù)據(jù),它不知道自己發(fā)出的兩個(gè)地址會(huì)落到同一個(gè)位置。因?yàn)楸挥乙屏藘晌弧?br> 不論外部存儲(chǔ)器的寬度是多少(16位或8位),F(xiàn)SMC_A[0]始終應(yīng)該連到外部存儲(chǔ)器的地址線A[0]
FSMC中地址與外設(shè)地址的對(duì)應(yīng)關(guān)系
FSMC中的1G空間存儲(chǔ)的是外設(shè)地址,當(dāng)我們?cè)诖鎯?chǔ)塊中的訪問單元序號(hào)+1,對(duì)應(yīng)的外設(shè)存儲(chǔ)單元的訪問地址就自加8(如果外設(shè)數(shù)據(jù)存儲(chǔ)的數(shù)據(jù)寬度為8b的話)
FSMC相關(guān)寄存器
SRAM/NOR 閃存片選控制寄存器:FSMC_BCRx
該寄存器有1-4。
14 EXTMOD 擴(kuò)展模式使能位
也就是是否允許讀寫不同的時(shí)序
○ 我們本章需要讀寫不同的時(shí)序,故該位需要設(shè)置為 1。
○ 當(dāng)該位設(shè)置為0,讀寫就公用BTRx寄存器。
12 WREN寫使能位。
我們需要向 TFTLCD 寫數(shù)據(jù),故該位必須設(shè)置為 1。
5-4 MWID[1:0]:存儲(chǔ)器數(shù)據(jù)總線寬度
00,表示 8 位數(shù)據(jù)模式;
01 表示 16 位數(shù)據(jù)模式;
10和 11 保留。
○ 我們的 TFTLCD 是 16 位數(shù)據(jù)線,所以設(shè)置 WMID[1:0]=01。
3-2 MTYP[1:0]:存儲(chǔ)器類型。
- 00 表示 SRAM、ROM;
- 01 表示 PSRAM;
- 10 表示 NOR FLASH;11保留。
0 MBKEN:存儲(chǔ)塊使能位
SRAM/NOR 閃存片選時(shí)序寄存器:FSMC_BTRx
BTRx寄存器介紹
該寄存器有1-4。
如果 FSMC_BCRx 寄存器中設(shè)置了 EXTMOD 位,則有兩個(gè)時(shí)序寄存器分別對(duì)應(yīng)讀(本寄存器)和寫操作(FSMC_BWTRx 寄存器)。
29-28 ACCMOD[1:0]:訪問模式。
00 表示訪問模式 A;01 表示訪問模式 B;
10 表示訪問模式 C;11 表示訪問模式 D
本章我們用到模式 A,故設(shè)置為 00。
15-8 DATAST[7:0]:數(shù)據(jù)保持時(shí)間。
0 為保留設(shè)置,其他設(shè)置則代表保持時(shí)間為:
DATAST 個(gè)HCLK 時(shí)鐘周期,最大為 255 個(gè) HCLK 周期。
數(shù)據(jù)保持時(shí)間,等于: DATAST(+1)個(gè)HCLK時(shí)鐘周期
DATAST最大為255。
對(duì)ILI9341來說,其實(shí)就是WR低電平持續(xù)時(shí)間,為15ns
不過ILI9320等則需要50ns。
考慮兼容性,對(duì)STM32F1,一個(gè)HCLK=13.8ns (1/72M),設(shè)置為3;
對(duì)STM32F4,一個(gè)HCLK=6ns(1/168M) ,設(shè)置為9。
F4不加1
3-0 ADDSET[3:0]:地址建立時(shí)間。
其建立時(shí)間為:ADDSET 個(gè) HCLK 周期,最大為 15 個(gè) HCLK周期,每個(gè)周期4ns(1/25M)。
表示:ADDSET+1個(gè)HCLK周期,ADDSET最大為15。
對(duì)ILI9341來說,這里相當(dāng)于WR高電平持續(xù)時(shí)間,為15ns。
同樣考慮兼容ILI9320,對(duì)STM32F1,這里即便設(shè)置為1,WR也有100ns的高電平,我們這里設(shè)置為1。
而對(duì)STM32F4,則設(shè)置為8。
F4不加1
地址建立時(shí)間
建立時(shí)間(Tsu:setuptime)是指在時(shí)鐘沿到來之前數(shù)據(jù)從不穩(wěn)定到穩(wěn)定所需的時(shí)間
用于從外設(shè),如TFTLCD讀取到穩(wěn)定的RS信號(hào)。
這段時(shí)間內(nèi),RDX和WRX均為無效電平。
數(shù)據(jù)保持時(shí)間
保持時(shí)間(Th:holdtime)是指數(shù)據(jù)穩(wěn)定后保持的時(shí)間,如果保持時(shí)間不滿足要求那么數(shù)據(jù)同樣也不能被穩(wěn)定的打入觸發(fā)器。
NT35510數(shù)據(jù)鎖存的時(shí)序圖:
數(shù)據(jù)鎖存可以讓NT35510芯片識(shí)別穩(wěn)定的數(shù)據(jù)。
為了我們識(shí)別到穩(wěn)定可靠的數(shù)據(jù),數(shù)據(jù)保持時(shí)間必須大于RDX低電平持續(xù)時(shí)間,即RDX的上升沿必須出現(xiàn)在地址保持時(shí)間之內(nèi)。
在計(jì)算的時(shí)候,應(yīng)該查看驅(qū)動(dòng)外設(shè)的讀寫最小時(shí)間,然后除時(shí)鐘周期即可。
ADDSET最小為250ns/HCLK,DATAST最小為150ns/HCLK。
SRAM/NOR 閃寫時(shí)序寄存器:FSMC_BWTRx
- 該寄存器在本章用作寫操作時(shí)序控制寄存器
ACCMOD
ACCMOD 設(shè)置同 FSMC_BTRx 一模一樣,同樣是選擇模式 A
- 另外 DATAST 和ADDSET 則對(duì)應(yīng)低電平和高電平持續(xù)時(shí)間
○ 對(duì) ILI9341 來說,這兩個(gè)時(shí)間只需要 15ns 就夠了,比讀操作快得多。
○ 所以我們這里設(shè)置 DATAST 為 3,即 4 個(gè) HCLK 周期,時(shí)間約為 55ns(因?yàn)?320 等控制器,這個(gè)時(shí)間要求比較長(zhǎng),要 50ns)。
○ ADDSET(也存在性能問題)設(shè)置為 0,即 1 個(gè) HCLK 周期,實(shí)際 WR 高電平時(shí)間大于 100ns。
寄存器組合
這里還要給大家做下科普,在 MDK 的寄存器定義里面,并沒有定義 FSMC_BCRx、FSMC_BTRx、FSMC_BWTRx 等這個(gè)單獨(dú)的寄存器,而是將他們進(jìn)行了一些組合。
FSMC_BCRx 和 FSMC_BTRx,組合成 BTCR[8]寄存器組,他們的對(duì)應(yīng)關(guān)系如下:
BTCR[0]對(duì)應(yīng) FSMC_BCR1,BTCR[1]對(duì)應(yīng) FSMC_BTR1
BTCR[2]對(duì)應(yīng) FSMC_BCR2,BTCR[3]對(duì)應(yīng) FSMC_BTR2
BTCR[4]對(duì)應(yīng) FSMC_BCR3,BTCR[5]對(duì)應(yīng) FSMC_BTR3
BTCR[6]對(duì)應(yīng) FSMC_BCR4,BTCR[7]對(duì)應(yīng) FSMC_BTR4
FSMC_BWTRx 則組合成 BWTR[7],他們的對(duì)應(yīng)關(guān)系如下:
BWTR[0]對(duì)應(yīng) FSMC_BWTR1,BWTR[2]對(duì)應(yīng) FSMC_BWTR2,
BWTR[4]對(duì)應(yīng) FSMC_BWTR3,BWTR[6]對(duì)應(yīng) FSMC_BWTR4,
BWTR[1]、BWTR[3]和 BWTR[5]保留,沒有用到。
FSMC的讀寫時(shí)序
模式
FSMC 的 NOR FLASH 控制器支持同步和異步突發(fā)兩種訪問方式。
- 選用同步突發(fā)訪問方式時(shí),F(xiàn)SMC 將 HCLK(系統(tǒng)時(shí)鐘)分頻后,發(fā)送給外部存儲(chǔ)器作為同步時(shí)鐘信號(hào) FSMC_CLK。此時(shí)需要的設(shè)置的時(shí)間參數(shù)有 2 個(gè):
- 1,HCLK 與 FSMC_CLK 的分頻系數(shù)(CLKDIV),可以為 2~16 分頻;
- 2,同步突發(fā)訪問中獲得第 1 個(gè)數(shù)據(jù)所需要的等待延遲(DATLAT)。
對(duì)于異步突發(fā)訪問方式,F(xiàn)SMC 主要設(shè)置 3 個(gè)時(shí)間參數(shù):地址建立時(shí)間(ADDSET)、數(shù)據(jù)建立時(shí)間(DATAST)和地址保持時(shí)間(ADDHLD)。
模式A與模式1的最大區(qū)別在于:模式1中讀寫速度一樣,模式A中讀寫速度不同。
模式A支持獨(dú)立的讀寫時(shí)序控制,這個(gè)對(duì)我們驅(qū)動(dòng)TFTLCD來說非常有用,因?yàn)門FTLCD在讀的時(shí)候,一般比較慢,而在寫的時(shí)候可以比較快,如果讀寫用一樣的時(shí)序,那么只能以讀的時(shí)序?yàn)榛鶞?zhǔn),從而導(dǎo)致寫的速度變慢。
FSMC與外設(shè)時(shí)序列保持一致
FSMC作為CPU與外部SRAM溝通的橋梁,那就得說他們兩個(gè)人都認(rèn)識(shí)的話——讀寫時(shí)序
對(duì)FSMC管理的變量Var進(jìn)行讀寫就會(huì)引起FSMC產(chǎn)生讀取SRAM中數(shù)據(jù)的時(shí)序,引發(fā)對(duì)SRAM的讀寫操作。
FSMC的模式A的讀時(shí)序
NOE為讀,NWE為寫。
n低電平有效
o output
e 使能
nex 片選cs
最后的2HCLK是用于存儲(chǔ)器將讀取到的數(shù)據(jù)存入鎖存器(即保存數(shù)據(jù))用的。
FSMC的模式A的寫時(shí)序
FSMC的配置步驟
TFTLCD液晶屏
屏幕介紹
TFTLCD即薄膜晶體管液晶顯示器。它與無源TN-LCD、STN-LCD的簡(jiǎn)單矩陣不同,它在液晶顯示屏的每一個(gè)象素上都設(shè)置有一個(gè)薄膜晶體管(TFT),可有效地克服非選通時(shí)的串?dāng)_,使顯示液晶屏的靜態(tài)特性與掃描線數(shù)無關(guān),因此大大提高了圖像質(zhì)量。
TFTLCD具有:亮度好、對(duì)比度高、層次感強(qiáng)、顏色鮮艷等特點(diǎn)。是目前最主流的LCD顯示器。廣泛應(yīng)用于電視、手機(jī)、電腦、平板等各種電子產(chǎn)品。
屏幕尺寸
ALIENTEK提供豐富的TFTLCD模塊型號(hào),供大家選擇,目前有以下型號(hào)可選:
1,ATK-2.8寸 TFTLCD模塊
分辨率:240320,驅(qū)動(dòng)IC:ILI9341,電阻觸摸屏,16位并口驅(qū)動(dòng)(在用)
2,ATK-3.5寸 TFTLCD模塊
分辨率:320480,驅(qū)動(dòng)IC:NT35310,電阻觸摸屏,16位并口驅(qū)動(dòng)
3,ATK-4.3寸 TFTLCD模塊
分辨率:480800,驅(qū)動(dòng)IC:NT35510,電容觸摸屏,16位并口驅(qū)動(dòng)
4,ATK-7寸 TFTLCD模塊(V1版本)
分辨率:480800,驅(qū)動(dòng)IC:CPLD+SDRAM,電容觸摸屏,16位并口驅(qū)動(dòng)
5,ATK-7寸 TFTLCD模塊(V2版本)
分辨率:480*800,驅(qū)動(dòng)IC:SSD1963,電容觸摸屏,8/9/12/16位并口驅(qū)動(dòng)
2.8寸屏介紹
240*320分辨率
16位真彩顯示(65536色)
自帶電阻觸摸屏
自帶背光電路
模塊是3.3V供電的,不支持5V電壓的MCU,如果是5V MCU,必須在信號(hào)線串接120R電阻使用。
屏幕原理圖
注意:DB1-DB8,DB10-DB17,總是按順序連接MCU的D0~D15
LCD_CS:LCD片選信號(hào)
LCD_WR:LCD寫信號(hào)
LCD_RD:LCD讀信號(hào)
DB[17:1]:16位雙向數(shù)據(jù)線。
LCD_RST:硬復(fù)位LCD信號(hào)
LCD_RS:命令/數(shù)據(jù)標(biāo)志 (0:命令,1:數(shù)據(jù))
BL_CTR:背光控制信號(hào)
T_MISO/T_MOSI/T_PEN/T_CS/T_CLK,觸摸屏接口信號(hào)
(該表格為F407的,與103不太一樣,僅看個(gè)大概意思)
- TFTLCD通過RS信號(hào)來決定傳送的數(shù)據(jù)是數(shù)據(jù)還是命令,本質(zhì)上可以理解為一個(gè)地址信號(hào)
- 比如我們把*RS接在A0上面
- 那么當(dāng)FSMC控制器寫地址0的時(shí)候,會(huì)使得A0變?yōu)?,對(duì)TFTLCD來說,就是寫命令。而FSMC寫地址1的時(shí)候,A0將會(huì)變?yōu)?,對(duì)TFTLCD來說,就是寫數(shù)據(jù)了。
- 當(dāng)然RS也可以接在其他地址線上,而探索者STM32F4把RS接在A6上面。
用到的主要的線
8080并口 驅(qū)動(dòng) 讀寫
介紹
讀寫
模塊的8080并口讀/寫的過程為:
1.讀數(shù)據(jù):在RD的上升沿, 讀取數(shù)據(jù)線上的數(shù)據(jù)(D[15:0]);
2.寫數(shù)據(jù):在WR的上升沿,使數(shù)據(jù)寫入到ILI9341里面
并口寫時(shí)序
并口讀時(shí)序
讀寫LCD本質(zhì)上是對(duì)尋址空間的某一個(gè)地址進(jìn)行讀寫操作:
讀:var=(uint32_t)0x6C000080;
寫:(uint32_t)0x6C000080=var;
RS選擇代碼
Bank1.sector4就是從地址0X6C000000開始,而0X000007FE,則是A[10]的偏移量。
以A[10]為例,A[10]相對(duì)于Bank1.sector4的地址0X7FE換成二進(jìn)制為:0b011111111110,而16位數(shù)據(jù)時(shí),地址右移一位對(duì)齊,對(duì)應(yīng)到地址引腳就是:A[10:0]=0b001111111111,此時(shí)A[10]是0
如果16位地址加1(對(duì)應(yīng)到8位地址是加2,即0X7FE+0X02),那么:A[10:0]=0b010000000000,此時(shí)A[10]就是1了,即實(shí)現(xiàn)了對(duì)RS的0和1的控制。
//LCD地址結(jié)構(gòu)體
typedefstruct
{
vu16LCD_REG;
vu16LCD_RAM;
}LCD_TypeDef;
//使用NOR/SRAM的Bank1.sector4,地址位HADDR[27,26]=11A10作為數(shù)據(jù)命令區(qū)分線
//注意設(shè)置時(shí)STM32內(nèi)部會(huì)右移一位對(duì)其!
#define LCD_BASE((u32)(0x6C000000|0x000007FE))
#define LCD((LCD_TypeDef*)LCD_BASE)
將這個(gè)地址強(qiáng)制轉(zhuǎn)換為L(zhǎng)CD_TypeDef結(jié)構(gòu)體地址,那么可以得到LCD->LCD_REG的地址就是0X6C00,07FE,對(duì)應(yīng)A[10]的狀態(tài)為0(即RS=0)
LCD->LCD_RAM的地址就是0X6C00,0800(結(jié)構(gòu)體地址自增),對(duì)應(yīng)A[10]的狀態(tài)為1(即RS=1),
驅(qū)動(dòng)時(shí)序
ILI9341_DS.pdf,232頁
重點(diǎn)時(shí)序:
讀ID低電平脈寬(trdl)
讀ID高電平脈寬(trdh)
讀FM低電平脈寬(trdlfm)
讀FM高電平脈寬(trdhfm)
寫控制低電平脈寬(twrl)
寫控制高電平脈寬(twrh)
注意:ID指LCD的ID號(hào)
FM指幀緩存,frame memory,即:GRAM
驅(qū)動(dòng)流程
指令說明
RGB565格式
模塊對(duì)外接口采用16位并口,顏色深度為16位,格式為RGB565,關(guān)系如下圖:
ILI9341指令
ILI9341所有的指令都是8位的(高8位無效),且參數(shù)除了讀寫GRAM的時(shí)候是16位,其他操作參數(shù),都是8位的。
ILI9341的指令很多,這里不一一介紹,僅介紹幾個(gè)重要的指令,他們是:0XD3,0X36,0X2A,0X2B,0X2C,0X2E等6條指令。
0XD3指令
該指令為讀ID4指令,用于讀取LCD控制器的ID 。因此,同一個(gè)代碼,可以根據(jù)ID的不同,執(zhí)行不同的LCD驅(qū)動(dòng)初始化,以兼容不同的LCD屏幕。
0X36指令
該指令為存儲(chǔ)訪問控制指令,可以控制ILI9341存儲(chǔ)器的讀寫方向,簡(jiǎn)單的說,就是在連續(xù)寫GRAM的時(shí)候,可以控制GRAM指針的增長(zhǎng)方向,從而控制顯示方式(讀GRAM也是一樣)。
0X2A指令
該指令是列地址設(shè)置指令,在從左到右,從上到下的掃描方式(默認(rèn))下面,該指令用于設(shè)置橫坐標(biāo)(x坐標(biāo))
在默認(rèn)掃描方式時(shí),該指令用于設(shè)置x坐標(biāo),該指令帶有4個(gè)參數(shù),實(shí)際上是2個(gè)坐標(biāo)值:SC和EC,即列地址的起始值和結(jié)束值,SC必須小于等于EC,且0≤SC/EC≤239。一般在設(shè)置x坐標(biāo)的時(shí)候,我們只需要帶2個(gè)參數(shù)即可,也就是設(shè)置SC即可,因?yàn)槿绻鸈C沒有變化,我們只需要設(shè)置一次即可(在初始化ILI9341的時(shí)候設(shè)置),從而提高速度。
0X2B指令
該指令是頁地址設(shè)置指令,在從左到右,從上到下的掃描方式(默認(rèn))下面,該指令用于設(shè)置縱坐標(biāo)(y坐標(biāo))
在默認(rèn)掃描方式時(shí),該指令用于設(shè)置y坐標(biāo),該指令帶有4個(gè)參數(shù),實(shí)際上是2個(gè)坐標(biāo)值:SP和EP,即頁地址的起始值和結(jié)束值,SP必須小于等于EP,且0≤SP/EP≤319。一般在設(shè)置y坐標(biāo)的時(shí)候,我們只需要帶2個(gè)參數(shù)即可,也就是設(shè)置SP即可,因?yàn)槿绻鸈P沒有變化,我們只需要設(shè)置一次即可(在初始化ILI9341的時(shí)候設(shè)置),從而提高速度。
0X2C指令
該指令是寫GRAM指令,在發(fā)送該指令之后,我們便可以往LCD的GRAM里面寫入顏色數(shù)據(jù)了,該指令支持連續(xù)寫 (地址自動(dòng)遞增)
在收到指令0X2C之后,數(shù)據(jù)有效位寬變?yōu)?6位,我們可以連續(xù)寫入LCD GRAM值,而GRAM的地址將根據(jù)MY/MX/MV設(shè)置的掃描方向進(jìn)行自增。
例如:假設(shè)設(shè)置的是從左到右,從上到下的掃描方式,那么設(shè)置好起始坐標(biāo)(通過SC,SP設(shè)置)后,每寫入一個(gè)顏色值,GRAM地址將會(huì)自動(dòng)自增1(SC++),如果碰到EC,則回到SC,同時(shí)SP++,一直到坐標(biāo):EC,EP結(jié)束,其間無需再次設(shè)置的坐標(biāo),從而大大提高寫入速度。
0X2E指令
該指令是讀GRAM指令,用于讀取ILI9341的顯存(GRAM),同0X2C指令,該指令支持連續(xù)讀 (地址自動(dòng)遞增)
ILI9341在收到該指令后,第一次輸出的是dummy數(shù)據(jù)(無效),第二次開始,讀取到的才是有效的GRAM數(shù)據(jù)(從坐標(biāo):SC,SP開始),輸出規(guī)律為:每個(gè)顏色分量占8個(gè)位,一次輸出2個(gè)顏色分量。比如:第一次輸出是R1G1,隨后的規(guī)律為:B1R2?G2B2?R3G3?B3R4?G4B4?R5G5… 以此類推
F407模式A讀寫時(shí)序與103略有不同
中文手冊(cè)1203
TFTLCD引腳
NBL用不到
A[25-0]用一個(gè)
NEx片選
NOE讀,NWE寫
D數(shù)據(jù)
根據(jù)驅(qū)動(dòng)時(shí)序時(shí)間設(shè)計(jì)ADDSET與DATASET
TFTLCD 顯示
需要的相關(guān)設(shè)置步驟如下:
初始化 FSMC
主要是初始化三個(gè)寄存器 FSMC_BCRx,F(xiàn)SMC_BTRx,F(xiàn)SMC_BWTRx。
固件庫提供了 3 個(gè) FSMC 初始化函數(shù)分別為
FSMC_NORSRAMInit();
FSMC_NANDInit();
FSMC_PCCARDInit();
- 設(shè)置 STM32F4 與 與 TFTLCD 模塊相連接的 IO 。
- 初始化 TFTLCD 模塊
- 探索者 STM32F4 開發(fā)板的LCD 接口,將 TFTLCD 的 RST 同 STM32F4 的 RESET 連接在一起了,只要按下開發(fā)板的 RESET鍵,就會(huì)對(duì) LCD 進(jìn)行硬復(fù)位。
- 初始化序列,就是向 LCD 控制器寫入一系列的設(shè)置值(比如伽馬校準(zhǔn)),這些初始化序列一般 LCD 供應(yīng)商會(huì)提供給客戶,我們直接使用這些序列即可,不需要深入研究。
- 通過函數(shù)將字符和數(shù)字顯示到 TFTLCD 模塊上
- 設(shè)置坐標(biāo)→寫 GRAM 指令→寫 GRAM 來實(shí)現(xiàn),但是這個(gè)步驟,只是一個(gè)點(diǎn)的處理,我們要顯示字符/數(shù)字,就必須要多次使用這個(gè)步驟,從而達(dá)到顯示字符/數(shù)字的目的,所以需要設(shè)計(jì)一個(gè)函數(shù)來實(shí)現(xiàn)數(shù)字/字符的顯示,之后調(diào)用該函數(shù),就可以實(shí)現(xiàn)數(shù)字/字符的顯示了。
LCD結(jié)構(gòu)體
定義如下 LCD 操作結(jié)構(gòu)體(在 lcd.h 里面定義):
//LCD 操作結(jié)構(gòu)體
typedef struct
{
vu16 LCD_REG;
vu16 LCD_RAM;
} LCD_TypeDef;
//使用 NOR/SRAM 的 Bank1.sector4,地址位 HADDR[27,26]=11 A6 作為數(shù)據(jù)命令區(qū)分線
//注意 16 位數(shù)據(jù)總線時(shí),STM32 內(nèi)部地址會(huì)右移一位對(duì)齊!
#define LCD_BASE ((u32)(0x6C000000 | 0x0000007E))
#define LCD ((LCD_TypeDef *) LCD_BASE)
有了這個(gè)定義,當(dāng)我們要往 LCD 寫命令/數(shù)據(jù)的時(shí)候,可以這樣寫:
LCD->LCD_REG=CMD; //寫命令
LCD->LCD_RAM=DATA; //寫數(shù)據(jù)
而讀的時(shí)候反過來操作就可以了,如下所示:
CMD= LCD->LCD_REG;//讀 LCD 寄存器
DATA = LCD->LCD_RAM;//讀 LCD 數(shù)據(jù)
這其中,CS、WR、RD 和 IO 口方向都是由 FSMC 控制,不需要我們手動(dòng)設(shè)置了。
LCD重要參數(shù)
介紹一下 lcd.h 里面的另一個(gè)重要結(jié)構(gòu)體:
//LCD 重要參數(shù)集
typedef struct
{
u16 width; //LCD 寬度
u16 height; //LCD 高度
u16 id; //LCD ID
u8 dir; //橫屏還是豎屏控制:0,豎屏;1,橫屏。
u16 wramcmd; //開始寫 gram 指令
u16 setxcmd; //設(shè)置 x 坐標(biāo)指令
u16 setycmd; //設(shè)置 y 坐標(biāo)指令
}_lcd_dev;
//LCD 參數(shù)
extern _lcd_dev lcddev; //管理 LCD 重要參數(shù)
該結(jié)構(gòu)體用于保存一些 LCD 重要參數(shù)信息
這個(gè)結(jié)構(gòu)體雖然占用了十幾個(gè)字節(jié)的內(nèi)存,但是卻可以讓我們的驅(qū)動(dòng)函數(shù)支持不同尺寸的 LCD,同時(shí)可以實(shí)現(xiàn) LCD 橫豎屏切換等重要功能,所以還是利大于弊的。
幾個(gè)重要函數(shù)
寫寄存器命令
//寫寄存器函數(shù)
//regval:寄存器值
void LCD_WR_REG(vu16 regval)
{ regval=regval; //使用-O2 優(yōu)化的時(shí)候,必須插入的延時(shí)
LCD->LCD_REG=regval;//寫入要寫的寄存器序號(hào)
}
寫LCD數(shù)據(jù)
//寫 LCD 數(shù)據(jù)
//data:要寫入的值
void LCD_WR_DATA(vu16 data)
{ data=data; //使用-O2 優(yōu)化的時(shí)候,必須插入的延時(shí)
LCD->LCD_RAM=data;
}
讀LCD數(shù)據(jù)
//讀 LCD 數(shù)據(jù)
//返回值:讀到的值
u16 LCD_RD_DATA(void)
{ vu16 ram; //防止被優(yōu)化
ram=LCD->LCD_RAM;
return ram;
}
寫寄存器
//寫寄存器
//LCD_Reg:寄存器地址
//LCD_RegValue:要寫入的數(shù)據(jù)
void LCD_WriteReg(vu16 LCD_Reg, vu16 LCD_RegValue)
{ LCD->LCD_REG = LCD_Reg; //寫入要寫的寄存器序號(hào)
LCD->LCD_RAM = LCD_RegValue; //寫入數(shù)據(jù)
}
讀寄存器
//讀寄存器
//LCD_Reg:寄存器地址
//返回值:讀到的數(shù)據(jù)
u16 LCD_ReadReg(vu16 LCD_Reg)
{ LCD_WR_REG(LCD_Reg); //寫入要讀的寄存器序號(hào)
delay_us(5);
return LCD_RD_DATA(); //返回讀到的值
}
寫GRAM
//開始寫 GRAM
void LCD_WriteRAM_Prepare(void)
{ LCD->LCD_REG=lcddev.wramcmd;
}
//LCD 寫 GRAM
//RGB_Code:顏色值
void LCD_WriteRAM(u16 RGB_Code)
{ LCD->LCD_RAM = RGB_Code;//寫十六位 GRAM
}
坐標(biāo)設(shè)置函數(shù)
該函數(shù)代碼如下:
//設(shè)置光標(biāo)位置
//Xpos:橫坐標(biāo)
//Ypos:縱坐標(biāo)
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
if(lcddev.id==0X9341||lcddev.id==0X5310)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos>>8);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_DATA(Ypos&0XFF);
}else if(lcddev.id==0X6804)
{
if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//橫屏?xí)r處理
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos>>8);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_DATA(Ypos&0XFF);
}else if(lcddev.id==0X5510)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos>>8);
LCD_WR_REG(lcddev.setxcmd+1);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_REG(lcddev.setycmd+1);
LCD_WR_DATA(Ypos&0XFF);
}else
{
if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//橫屏其實(shí)就是調(diào)轉(zhuǎn) x,y 坐標(biāo)
LCD_WriteReg(lcddev.setxcmd, Xpos);
LCD_WriteReg(lcddev.setycmd, Ypos);
}
}
該函數(shù)實(shí)現(xiàn)將 LCD 的當(dāng)前操作點(diǎn)設(shè)置到指定坐標(biāo)(x,y)。因?yàn)?9341/5310/6804/5510 等的設(shè)置同其他屏有些不太一樣,所以進(jìn)行了區(qū)別對(duì)待。文章來源:http://www.zghlxwxcb.cn/news/detail-781657.html
畫點(diǎn)函數(shù)
//畫點(diǎn)
//x,y:坐標(biāo)
//POINT_COLOR:此點(diǎn)的顏色
void LCD_DrawPoint(u16 x,u16 y)
{
LCD_SetCursor(x,y); //設(shè)置光標(biāo)位置
LCD_WriteRAM_Prepare(); //開始寫入 GRAM
LCD->LCD_RAM=POINT_COLOR;
}
該函數(shù)實(shí)現(xiàn)比較簡(jiǎn)單,就是先設(shè)置坐標(biāo),然后往坐標(biāo)寫顏色。其中 POINT_COLOR 是我們定義的一個(gè)全局變量,用于存放畫筆顏色,順帶介紹一下另外一個(gè)全局變量:BACK_COLOR,該變量代表 LCD 的背景色。LCD_DrawPoint 函數(shù)雖然簡(jiǎn)單,但是至關(guān)重要,其他幾乎所有上層函數(shù),都是通過調(diào)用這個(gè)函數(shù)實(shí)現(xiàn)的。文章來源地址http://www.zghlxwxcb.cn/news/detail-781657.html
TFTLCD 模塊的初始化函數(shù) LCD_Init
//初始化lcd
//該初始化函數(shù)可以初始化各種ILI93XX液晶,但是其他函數(shù)是基于ILI9320的!!!
//在其他型號(hào)的驅(qū)動(dòng)芯片上沒有測(cè)試!
void LCD_Init(void)
{
vu32 i=0;
GPIO_InitTypeDef GPIO_InitStructure;
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef readWriteTiming;
FSMC_NORSRAMTimingInitTypeDef writeTiming;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOG, ENABLE);//使能PD,PE,PF,PG時(shí)鐘
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);//使能FSMC時(shí)鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PB15 推挽輸出,控制背光
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通輸出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化 //PB15 推挽輸出,控制背光
GPIO_InitStructure.GPIO_Pin = (3<<0)|(3<<4)|(7<<8)|(3<<14);//PD0,1,4,5,8,9,10,14,15 AF OUT
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//復(fù)用輸出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化
GPIO_InitStructure.GPIO_Pin = (0X1FF<<7);//PE7~15,AF OUT
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//復(fù)用輸出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PF12,FSMC_A6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//復(fù)用輸出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PF12,FSMC_A6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//復(fù)用輸出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化
GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_FSMC);//PD0,AF12
GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_FSMC);//PD1,AF12
GPIO_PinAFConfig(GPIOD,GPIO_PinSource4,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource8,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource9,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource10,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource14,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource15,GPIO_AF_FSMC);//PD15,AF12
GPIO_PinAFConfig(GPIOE,GPIO_PinSource7,GPIO_AF_FSMC);//PE7,AF12
GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource15,GPIO_AF_FSMC);//PE15,AF12
GPIO_PinAFConfig(GPIOF,GPIO_PinSource12,GPIO_AF_FSMC);//PF12,AF12
GPIO_PinAFConfig(GPIOG,GPIO_PinSource12,GPIO_AF_FSMC);
readWriteTiming.FSMC_AddressSetupTime = 0XF; //地址建立時(shí)間(ADDSET)為16個(gè)HCLK 1/168M=6ns*16=96ns
readWriteTiming.FSMC_AddressHoldTime = 0x00; //地址保持時(shí)間(ADDHLD)模式A未用到
readWriteTiming.FSMC_DataSetupTime = 60; //數(shù)據(jù)保存時(shí)間為60個(gè)HCLK =6*60=360ns
readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
readWriteTiming.FSMC_CLKDivision = 0x00;
readWriteTiming.FSMC_DataLatency = 0x00;
readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A; //模式A
writeTiming.FSMC_AddressSetupTime =9; //地址建立時(shí)間(ADDSET)為9個(gè)HCLK =54ns
writeTiming.FSMC_AddressHoldTime = 0x00; //地址保持時(shí)間(A
writeTiming.FSMC_DataSetupTime = 8; //數(shù)據(jù)保存時(shí)間為6ns*9個(gè)HCLK=54ns
writeTiming.FSMC_BusTurnAroundDuration = 0x00;
writeTiming.FSMC_CLKDivision = 0x00;
writeTiming.FSMC_DataLatency = 0x00;
writeTiming.FSMC_AccessMode = FSMC_AccessMode_A; //模式A
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;// 這里我們使用NE4 ,也就對(duì)應(yīng)BTCR[6],[7]。
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; // 不復(fù)用數(shù)據(jù)地址
FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;// FSMC_MemoryType_SRAM; //SRAM
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;//存儲(chǔ)器數(shù)據(jù)寬度為16bit
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;// FSMC_BurstAccessMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; // 存儲(chǔ)器寫使能
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable; // 讀寫使用不同的時(shí)序
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming; //讀寫時(shí)序
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &writeTiming; //寫時(shí)序
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); //初始化FSMC配置
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE); // 使能BANK1
delay_ms(50); // delay 50 ms
LCD_WriteReg(0x0000,0x0001);
delay_ms(50); // delay 50 ms
lcddev.id = LCD_ReadReg(0x0000);
if(lcddev.id<0XFF||lcddev.id==0XFFFF||lcddev.id==0X9300)//讀到ID不正確,新增lcddev.id==0X9300判斷,因?yàn)?341在未被復(fù)位的情況下會(huì)被讀成9300
{
//嘗試9341 ID的讀取
LCD_WR_REG(0XD3);
lcddev.id=LCD_RD_DATA(); //dummy read
lcddev.id=LCD_RD_DATA(); //讀到0X00
lcddev.id=LCD_RD_DATA(); //讀取93
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA(); //讀取41
if(lcddev.id!=0X9341) //非9341,嘗試是不是6804
{
LCD_WR_REG(0XBF);
lcddev.id=LCD_RD_DATA(); //dummy read
lcddev.id=LCD_RD_DATA(); //讀回0X01
lcddev.id=LCD_RD_DATA(); //讀回0XD0
lcddev.id=LCD_RD_DATA(); //這里讀回0X68
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA(); //這里讀回0X04
if(lcddev.id!=0X6804) //也不是6804,嘗試看看是不是NT35310
{
LCD_WR_REG(0XD4);
lcddev.id=LCD_RD_DATA();//dummy read
lcddev.id=LCD_RD_DATA();//讀回0X01
lcddev.id=LCD_RD_DATA();//讀回0X53
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA(); //這里讀回0X10
if(lcddev.id!=0X5310) //也不是NT35310,嘗試看看是不是NT35510
{
LCD_WR_REG(0XDA00);
lcddev.id=LCD_RD_DATA(); //讀回0X00
LCD_WR_REG(0XDB00);
lcddev.id=LCD_RD_DATA(); //讀回0X80
lcddev.id<<=8;
LCD_WR_REG(0XDC00);
lcddev.id|=LCD_RD_DATA(); //讀回0X00
if(lcddev.id==0x8000)lcddev.id=0x5510;//NT35510讀回的ID是8000H,為方便區(qū)分,我們強(qiáng)制設(shè)置為5510
if(lcddev.id!=0X5510) //也不是NT5510,嘗試看看是不是SSD1963
{
LCD_WR_REG(0XA1);
lcddev.id=LCD_RD_DATA();
lcddev.id=LCD_RD_DATA(); //讀回0X57
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA(); //讀回0X61
if(lcddev.id==0X5761)lcddev.id=0X1963;//SSD1963讀回的ID是5761H,為方便區(qū)分,我們強(qiáng)制設(shè)置為1963
}
}
}
}
}
if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X5510||lcddev.id==0X1963)//如果是這幾個(gè)IC,則設(shè)置WR時(shí)序?yàn)樽羁?/span>
{
//重新配置寫時(shí)序控制寄存器的時(shí)序
FSMC_Bank1E->BWTR[6]&=~(0XF<<0);//地址建立時(shí)間(ADDSET)清零
FSMC_Bank1E->BWTR[6]&=~(0XF<<8);//數(shù)據(jù)保存時(shí)間清零
FSMC_Bank1E->BWTR[6]|=3<<0; //地址建立時(shí)間(ADDSET)為3個(gè)HCLK =18ns
FSMC_Bank1E->BWTR[6]|=2<<8; //數(shù)據(jù)保存時(shí)間(DATAST)為6ns*3個(gè)HCLK=18ns
}else if(lcddev.id==0X6804||lcddev.id==0XC505) //6804/C505速度上不去,得降低
{
//重新配置寫時(shí)序控制寄存器的時(shí)序
FSMC_Bank1E->BWTR[6]&=~(0XF<<0);//地址建立時(shí)間(ADDSET)清零
FSMC_Bank1E->BWTR[6]&=~(0XF<<8);//數(shù)據(jù)保存時(shí)間清零
FSMC_Bank1E->BWTR[6]|=10<<0; //地址建立時(shí)間(ADDSET)為10個(gè)HCLK =60ns
FSMC_Bank1E->BWTR[6]|=12<<8; //數(shù)據(jù)保存時(shí)間(DATAST)為6ns*13個(gè)HCLK=78ns
}
printf(" LCD ID:%x\r\n",lcddev.id); //打印LCD ID
if(lcddev.id==0X9341) //9341初始化
{
LCD_WR_REG(0xCF);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0xC1);
LCD_WR_DATA(0X30);
LCD_WR_REG(0xED);
LCD_WR_DATA(0x64);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0X12);
LCD_WR_DATA(0X81);
LCD_WR_REG(0xE8);
LCD_WR_DATA(0x85);
LCD_WR_DATA(0x10);
LCD_WR_DATA(0x7A);
LCD_WR_REG(0xCB);
LCD_WR_DATA(0x39);
LCD_WR_DATA(0x2C);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x34);
LCD_WR_DATA(0x02);
LCD_WR_REG(0xF7);
LCD_WR_DATA(0x20);
LCD_WR_REG(0xEA);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_REG(0xC0); //Power control
LCD_WR_DATA(0x1B); //VRH[5:0]
LCD_WR_REG(0xC1); //Power control
LCD_WR_DATA(0x01); //SAP[2:0];BT[3:0]
LCD_WR_REG(0xC5); //VCM control
LCD_WR_DATA(0x30); //3F
LCD_WR_DATA(0x30); //3C
LCD_WR_REG(0xC7); //VCM control2
LCD_WR_DATA(0XB7);
LCD_WR_REG(0x36); // Memory Access Control
LCD_WR_DATA(0x48);
LCD_WR_REG(0x3A);
LCD_WR_DATA(0x55);
LCD_WR_REG(0xB1);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x1A);
LCD_WR_REG(0xB6); // Display Function Control
LCD_WR_DATA(0x0A);
LCD_WR_DATA(0xA2);
LCD_WR_REG(0xF2); // 3Gamma Function Disable
LCD_WR_DATA(0x00);
LCD_WR_REG(0x26); //Gamma curve selected
LCD_WR_DATA(0x01);
LCD_WR_REG(0xE0); //Set Gamma
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x2A);
LCD_WR_DATA(0x28);
LCD_WR_DATA(0x08);
LCD_WR_DATA(0x0E);
LCD_WR_DATA(0x08);
LCD_WR_DATA(0x54);
LCD_WR_DATA(0XA9);
LCD_WR_DATA(0x43);
LCD_WR_DATA(0x0A);
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_REG(0XE1); //Set Gamma
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x15);
LCD_WR_DATA(0x17);
LCD_WR_DATA(0x07);
LCD_WR_DATA(0x11);
LCD_WR_DATA(0x06);
LCD_WR_DATA(0x2B);
LCD_WR_DATA(0x56);
LCD_WR_DATA(0x3C);
LCD_WR_DATA(0x05);
LCD_WR_DATA(0x10);
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x3F);
LCD_WR_DATA(0x3F);
LCD_WR_DATA(0x0F);
LCD_WR_REG(0x2B);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x3f);
LCD_WR_REG(0x2A);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0xef);
LCD_WR_REG(0x11); //Exit Sleep
delay_ms(120);
LCD_WR_REG(0x29); //display on
}
LCD_Display_Dir(0); //默認(rèn)為豎屏
LCD_LED=1; //點(diǎn)亮背光
LCD_Clear(WHITE);
}
主函數(shù)代碼
int main(void)
{
u8 x=0;
u8 lcd_id[12]; //存放LCD ID字符串
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置系統(tǒng)中斷優(yōu)先級(jí)分組2
delay_init(168); //初始化延時(shí)函數(shù)
uart_init(115200); //初始化串口波特率為115200
LED_Init(); //初始化LED
LCD_Init(); //初始化LCD FSMC接口
POINT_COLOR=BLACK; //畫筆顏色:紅色
sprintf((char*)lcd_id,"LCD ID:%04X",lcddev.id);//將LCD ID打印到lcd_id數(shù)組。
while(1)
{
switch(x)
{
case 0:LCD_Clear(WHITE);break;
case 1:LCD_Clear(BLACK);break;
case 2:LCD_Clear(BLUE);break;
case 3:LCD_Clear(RED);break;
case 4:LCD_Clear(MAGENTA);break;
case 5:LCD_Clear(GREEN);break;
case 6:LCD_Clear(CYAN);break;
case 7:LCD_Clear(YELLOW);break;
case 8:LCD_Clear(BRRED);break;
case 9:LCD_Clear(GRAY);break;
case 10:LCD_Clear(LGRAY);break;
case 11:LCD_Clear(BROWN);break;
}
POINT_COLOR=RED;
LCD_ShowString(30,40,210,16,24,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"we will be happiness");
LCD_ShowString(30,90,200,16,16,"it is ok");
LCD_ShowString(30,110,200,16,16,lcd_id); //顯示LCD ID
LCD_ShowString(30,130,200,12,12,"2014/5/4");
x++;
if(x==12)x=0;
LED0=!LED0;
delay_ms(1000);
}
}
SRAM
到了這里,關(guān)于STM32的FSMC的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!