介绍下如何使用库函数对 FSMC 进行配置。这个也是在编写程序中必须要了解的。具体步骤如下:(FSMC 相关库函数在 stm32f10x_fsmc.c 和stm32f10x_fsmc.h 文件中) (1)FSMC 初始化 FSMC 的初始化主要是配置 FSMC_BCRx, FSMC_BTRx,FSMC_BWTRx 这三个寄存器,固件库内提供了 3 个初始化函数对这些寄存器配置。FSMC 初始化库函数如下: - FSMC_NORSRAMInit();
: d1 `: w+ W' p9 p' L - FSMC_NANDInit();9 J- z4 [. u2 r- o
- FSMC_PCCARDInit();
复制代码
2 T, T& N% q1 _. X5 X* j" ] I, U
这三个函数分别用来初始化 4 种类型存储器。这里根据名字就很好判断对 应关系。用来初始化 NOR 和 SRAM 使用同一个函数FSMC_NORSRAMInit()。所以我们之后使用的 FSMC 初始化函数为 FSMC_NORSRAMInit()。该初始化函数原型是: - void FSMC_NORSRAMInit(FSMC_NORSRAMInitTypeDef*FSMC_NORSRAMInitStruct);
复制代码
V- K, a; G7 T4 F 这个函数只有一个参数,是一个结构体指针变量,结构体类型是FSMC_NORSRAMInitTypeDef,其内成员变量非常多,因为 FSMC 相关的配置项非常多。下面我们简单介绍下它的成员: - typedef struct
8 I% D5 [* y9 T; X - {
& c/ b$ s$ q2 a$ q a5 a: F - uint32_t FSMC_Bank;% v5 ]- P! L D( ^# T5 b0 A) R$ }) ^: I
- uint32_t FSMC_DataAddressMux;
/ l& g& b0 ?$ K - uint32_t FSMC_MemoryType;
) A2 ]& ?8 K3 q# z - uint32_t FSMC_MemoryDataWidth;9 v, D k/ I) i/ i9 g5 s
- uint32_t FSMC_BurstAccessMode;
! K& C: l% n4 s# a4 `0 s6 I0 b - uint32_t FSMC_AsynchronousWait;
$ N* a9 G8 q+ J9 N# \7 C - uint32_t FSMC_WaitSignalPolarity;" B" m+ g5 X3 [" z% T
- uint32_t FSMC_WrapMode;! O, F; t' D- f0 {3 Z6 z0 v
- uint32_t FSMC_WaitSignalActive;
* L6 H) A( j+ d; j! L - uint32_t FSMC_WriteOperation;4 @1 g8 Z# @ U+ A3 t
- uint32_t FSMC_WaitSignal;* o9 Z: D& s" E9 q2 h! G1 h
- uint32_t FSMC_ExtendedMode;: a# h5 I( ^$ c. s! u2 m7 e
- uint32_t FSMC_WriteBurst;; Y; N& p! d* E' t; T* n
- FSMC_NORSRAMTimingInitTypeDef* FSMC_ReadWriteTimingStruct;" u5 l0 M# C2 X+ c9 D- R$ X/ A
- FSMC_NORSRAMTimingInitTypeDef* FSMC_WriteTimingStruct;
% z- g) D! q: I- T& P/ J+ L - }FSMC_NORSRAMInitTypeDef;
复制代码
; P* g% A$ Y1 u' ^ J$ M1 u8 o
从这个结构体我们可以看出,前面有 13 个基本类型( unit32_t)的成员 变量,这 13 个参数是用来配置片选控制寄存器 FSMC_BCRx。最后面还有两个SMC_NORSRAMTimingInitTypeDef 指针类型的成员变量。前面我们讲到,FSMC 有读时序和写时序之分,所以这里就是用来设置读时序和写时序的参数了,也就是说,这两个参数是用来配置寄存器 FSMC_BTRx 和 FSMC_BWTRx,后面我们会讲解到。下面我们就来看看这些成员: FSMC_Bank:用来设置使用到的存储块标号和区号,本章实验我们是使用的 存储块 1 区号 4,所以选择值为 FSMC_Bank1_NORSRAM4。 FSMC_DataAddressMux:用于配置 FSMC 的数据线与地址线是否复用。FSMC支持数据与地址线复用或非复用两种模式。在非复用模式下 16 位数据线及 26位地址线分开始用;复用模式则低 16 位数据/地址线复用,仅对 NOR 和 PSRAM有效。在复用模式下,推荐使用地址锁存器以区分数据与地址。本实验使用FSMC模拟 8080 时序,仅使用一根地址线 A10 提供 8080 的 RS 信号,所以不需要复用,即设置为 - FSMC_DataAddressMux_Disable
复制代码
! S0 f6 h7 S) x* w" [" hFSMC_MemoryType:用来设置FSMC外接的存储器类型, 可选类型为 NOR FLASH模式、PSARM 模式及 SRAM 模式。我们这里把 TFTLCD当做 SRAM 使用,所以选择值为 FSMC_MemoryType_SRAM。 FSMC_MemoryDataWidth:用来设置 FSMC 接口的数据宽度,可选择 8 位还是16 位, 这里我们是 16 位数据宽度, 所以选择值为 FSMC_MemoryDataWidth_16b。 FSMC_WriteOperation:用于配置写操作使能,如果禁止了写操作,FSMC 不会产生写时序,但仍可从存储器中读出数据。本实验需要向 TFTLCD内写数据,所以要写使能,配置为 FSMC_WriteOperation_Enable(写使能)。 FSMC_ExtendedMode:用于配置是否使用扩展模式,在扩展模式下,读时序和写时序可以使用独立时序模式。如读时序使用模式 A,写时序使用模式 B,这些 A、B、C、D 模式实际上差别不大,主要是在使用数据/地址线复用的情况下,FSMC 信号产生的时序不一样。 FSMC_BurstAccessMode:用于配置访问模式。FSMC 对存储器的访问分为异步模式和突发模式(同步模式)。在异步模式下,每次传送数据都需要产生一个确定的地址, 而突发模式可以在开始时提供一个地址之后, 把数据成组地连续写入。 本实验使用异步模式 FSMC_BurstAccessMode_Disable。 FSMC_WaitSignalPolarity(配置等待信号极性)、FSMC_WrapMode(配置是否使用非对齐方式)、FSMC_WaitSignalActive(配置等待信号什么时期产生)、FSMC_WaitSignal(配置是否使用等待信号)、FSMC_WriteBurst(配置是否允许突发写操作),这些成员均需要在突发模式开启后配置才有效。本实验使用的是异步模式,所以这些成员的参数没有意义。 FSMC_ReadWriteTimingStruct 和 FSMC_WriteTimingStruct:用于设置读写时序。这两个变量都是 FSMC_NORSRAMTimingInitTypeDef 结构体指针类型。这两个参数在初始化的时候分别用来初始化片选控制寄存器 FSMC_BTRx 和写操作时序控制寄存器 FSMC_BWTRx。 FSMC_NORSRAMTimingInitTypeDef结构体如下: - typedef struct: F/ n0 u7 W2 X2 d) N
- {
7 l7 U1 {4 Z2 P9 e# `. M" Z, Y Q3 X - uint32_t FSMC_AddressSetupTime;//地址建立时间& O, W, y Z5 l$ W& i
- uint32_t FSMC_AddressHoldTime;//地址保持时间
! |5 c1 |7 r4 L( W - uint32_t FSMC_DataSetupTime;//数据建立时间" q- E+ V2 O; C' k7 f; B4 K( O
- uint32_t FSMC_BusTurnAroundDuration;//总线恢复时间
1 R& S0 l& m) }6 Q/ }8 Z3 f+ N. F - uint32_t FSMC_CLKDivision;//时钟分频8 ~/ r, s0 f: ~+ b7 N: ^
- uint32_t FSMC_DataLatency;//数据保持时间, ~& }! [; f# ^" ]" z6 n
- uint32_t FSMC_AccessMode;//访问模式
, s. R" @5 g5 ?, f: K* y - }FSMC_NORSRAMTimingInitTypeDef;
复制代码
! e# B+ F3 ?5 c1 v
这些成员主要用于设计地址建立保持时间,数据建立时间等配置,这些时间是由 HCLK 经过成员时钟分频得来的, 该分频值在成员 FSMC_CLKDivision(时钟分频)中设置,其中 FSMC_AccessMode(访问模式)成员的设置只在开启了扩展模式才有效,而且开启了扩展模式后,读时序和写时序的设置可以是独立的。本实验中我们需要读写速度不一样,所以开启了扩展模式并且对于参数FSMC_DataSetupTime 设置了不同的值。此结构体其实就是对 FSMC_BTRx 和FSMC_BWTRx 寄存器操作,大家可以查看中文参考手册寄存器说明。 本实验中的时序设置是根据 R61509V3 的数据手册设置的, 调试的时候可以先把这些值设置得大一些,然后慢慢靠近数据手册要求的最小值,这样会取得比较好的效果。时序的参数设置对 LCD 的显示效果有一定的影响。 了解结构体成员功能后,就可以进行配置,本章实验配置代码如下: - FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
7 P/ y6 \' k0 \ - FSMC_NORSRAMTimingInitTypeDef FSMC_ReadNORSRAMTiming;: W. T% g# l8 s: N
- FSMC_NORSRAMTimingInitTypeDef FSMC_WriteNORSRAMTiming;5 `0 W7 M; X4 q: o( {! }7 Q9 W
- FSMC_ReadTimingInitStructure.FSMC_AddressSetupTime = 0x01; // 地址建立时间(ADDSET)为2个HCLK 1/36M=27ns) m' h4 s3 Q7 A8 s
- FSMC_ReadTimingInitStructure.FSMC_AddressHoldTime = 0x00; // 地址保持时间(ADDHLD)模式A未用到
) @( a% ]& F: V8 r R5 @( e1 ? - FSMC_ReadTimingInitStructure.FSMC_DataSetupTime = 0x0f; // 数据保存时间为 16 个 HCLK,因为液晶驱动 IC 的读数据的时候,速度不能太快,尤其对 1289 这个 IC。& s4 r4 ]7 U$ J
- FSMC_ReadTimingInitStructure.FSMC_BusTurnAroundDuration = 0x00;
( M1 f$ X# d, l1 o5 _7 g" R9 w - FSMC_ReadNORSRAMTiming.FSMC_CLKDivision = 0x00;3 J! L+ e- Z7 N2 I
- FSMC_ReadNORSRAMTiming.FSMC_DataLatency = 0x00;6 _$ j& ]; k/ @; l$ v
- FSMC_ReadNORSRAMTiming.FSMC_AccessMode = FSMC_AccessMode_A;
' V8 A Z; o' g" ^1 e - //模式A8 m/ x0 m4 Y4 Q- r2 z4 r/ D
- FSMC_WriteNORSRAMTiming.FSMC_AddressSetupTime =0x00; //地址建立时间(ADDSET)为1个HCLK
7 m& E8 R0 E$ Z4 W! ^ - FSMC_WriteNORSRAMTiming.FSMC_AddressHoldTime = 0x00; //地址保持时间(A
: q c( `! L2 f) a - FSMC_WriteNORSRAMTiming.FSMC_DataSetupTime = 0X03; //数据保存时间为 4 个 HCLK5 d8 h: P' y+ Y$ `( q, o( F p
- FSMC_WriteNORSRAMTiming.FSMC_BusTurnAroundDuration = 0x00;" R9 c: B5 F; r; g, k, a
- FSMC_WriteNORSRAMTiming.FSMC_CLKDivision = 0x00;; t9 e% L% G0 R; Q7 V+ C9 }
- FSMC_WriteNORSRAMTiming.FSMC_DataLatency = 0x00;
6 H2 Q; ^ x5 `) X8 ]7 A' U; v - FSMC_WriteNORSRAMTiming.FSMC_AccessMode = FSMC_AccessMode_A;
7 n( B$ ]% Y& O* D% u - //模式A& L& @1 u+ M+ _. P* Q5 P" e# [
- FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;// 这里我们使用 NE4 ,也就对应BTCR[6],[7]。
2 Y7 ]# k9 ~( m - FSMC_NORSRAMInitStructure.FSMC_DataAddressMux =
9 j K: S0 M6 n. V6 ?# b - FSMC_DataAddressMux_Disable; // 不复用数据地址1 m' T0 J! W1 m2 B
- FSMC_NORSRAMInitStructure.FSMC_MemoryType=FSMC_MemoryType_SRAM;// FSMC_MemoryType_SRAM; //SRAM# R4 ]6 G: o9 b+ B- B* A
- FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth =FSMC_MemoryDataWidth_16b;//存储器数据宽度为 16bit
1 W! ?* L% Y9 |, S. Q - FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode=FSMC_BurstAccessMode_Disable;// FSMC_BurstAccessMode_Disable;
; t: h! C' V6 I0 Q& j$ c - FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity =FSMC_WaitSignalPolarity_Low;
& L- ^5 J; X/ K+ K% B) ^6 ^ - FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;% ?; [0 N, H$ Q' _- \$ I
- FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
) ~& i# i- C6 w7 {5 Q% `& Q9 Z+ Z - FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive =FSMC_WaitSignalActive_BeforeWaitState;
, E0 B5 D) _9 }2 {$ m( M: L2 n& W - FSMC_NORSRAMInitStructure.FSMC_WriteOperation =FSMC_WriteOperation_Enable; // 存储器写使能
! ~9 T- K, z9 A2 _, u, R - FSMC_NORSRAMInitStructure.FSMC_WaitSignal =FSMC_WaitSignal_Disable;
, ?: x/ g# r+ u# ]' [% j/ l3 A$ X" b6 ?+ } - FSMC_NORSRAMInitStructure.FSMC_ExtendedMode =FSMC_ExtendedMode_Enable; // 读写使用不同的时序& v4 Y1 m! w$ `' r- e: W
- FSMC_NORSRAMInitStructure.FSMC_WriteBurst =FSMC_WriteBurst_Disable;8 o, Q3 _* ~, d8 T
- FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct =&FSMC_ReadNORSRAMTiming; //读写时序
6 _; q7 A* B1 l+ J0 M - FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct =&FSMC_WriteNORSRAMTiming; //写时序: s: W8 y! W/ o) _- t* D
- FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); //初始化FSMC配置
复制代码' |6 q( f" _4 f# h( ^2 k
(2)使能(开启)FSMC 固件库提供了不同的库函数来初始化各种存储器, 同样也提供了不同类型的存储器使能函数,如下: - void FSMC_NORSRAMCmd(uint32_t FSMC_Bank, FunctionalState NewState);2 V- f+ ?, E9 z! x
- void FSMC_NANDCmd(uint32_t FSMC_Bank, FunctionalState NewState);
! m y, T* V, ` R3 H - void FSMC_PCCARDCmd(FunctionalState NewState);
复制代码 这 3 个函数支持不同种类的存储器,从函数名来看也非常好理解。我们把
! E8 V; @! q+ x4 n5 N9 s TFTLCD当作 SRAM 使用,即使用第一个函数。该函数第一个参数用来选择存储器的区域,第二个参数用来使能或者失能。 将以上几步全部配置好后,我们就可以使用 STM32F1 的 FSMC了。 : G+ @; D3 Z' b' q
|