STM32F1系列单片机有多种外设,外设配置方式比较一致,一般是使能外设所在GPIO口时钟、使能外设的时钟,在禁止外设的情况下配置外设的时序以及中断和DMA等。大部分的外设配置相对简单,但是FSMC接口因为配置比较复杂,往往让一些初学者一头雾水。本文记录了本人在STM32F103ZET6的FSMC接口配置调试TFT LCD屏相关注意事项。+ ^5 O; R- I' `" c5 l" G0 a
1 FSMC接口GPIO配置- 0 h2 h% i, m4 @; K& F0 a# C2 Z& q
- /** FSMC GPIOConfiguration 8 ?$ }3 L$ [; k0 i; { X! y
- PF0 ------> FSMC_A0 6 x, Q8 s( [6 e% V* u8 t. o
- ------> LCD_RS: 0: Reg,1:Data
9 {0 r% N1 R* V* r: G1 n: C - PE7 ------> FSMC_D4' R, u( _# \9 t) _' e P; m
- PE8 ------> FSMC_D59 i1 b" b& [" R0 C
- PE9 ------> FSMC_D6
2 V$ ~2 {4 s6 M - PE10 ------> FSMC_D7
. |7 P1 k: p6 B* Z- o; w - PE11 ------> FSMC_D8
2 f9 S% Q: r8 l/ o4 [ - PE12 ------> FSMC_D9! p3 P' B8 _' E+ r+ D3 \! K
- PE13 ------> FSMC_D10* x k; M% g( r4 f6 b
- PE14 ------> FSMC_D11
) y$ i8 q0 C- m. ] - PE15 ------> FSMC_D12
2 j! O( v8 ]5 ~$ d% r \) h - PD8 ------> FSMC_D13
6 r7 v+ Y2 Y7 a* p2 K! L - PD9 ------> FSMC_D145 y, @; K M8 T
- PD10 ------> FSMC_D15
4 ?0 v( z# ^; P2 h, K8 V6 T2 Z - PD14 ------> FSMC_D0- n2 ?, W: E* L; {! D
- PD15 ------> FSMC_D1' \( ` e& u4 F. q
- PD0 ------> FSMC_D2- d* I, h/ J( ?9 M
- PD1 ------> FSMC_D3
1 V# C2 x1 T, f" I% J- y - PD4 ------> FSMC_NOE
' K. ?+ }, c% M0 G; n - ------> LCD_RD Default:1,Value:0 % U* f x$ W( i8 ]
- PD5 ------> FSMC_NWE
$ I5 E- ?4 h' B% s. r* E8 E - ------> LCD_WR Default:1,Value:0! o2 ?5 }1 j1 h$ m* ^7 g4 J1 p; i
- PG12 ------> FSMC_NE4 @0 V/ S: b, X# N4 K9 |% V
- ------>LCD_CS Default:1,Value:0
复制代码
* x5 Z: D+ b* Z+ M0 {) @( j; g* A2 初始化FSMC时序; f* u7 _5 Y! E1 |" r: w3 G$ f! ^1 x
- 5 ^7 |! ^- n/ B% U/ g
- /* FSMC initializationfunction */5 w4 M' z& H) j( r
- FSMC_NORSRAM_TimingTypeDef Timing;
: k7 v3 L F( z) o - SRAM_HandleTypeDef hsram1;
, L1 K6 G$ e- F
/ S9 I2 C* z/ M, l) x9 T5 b& i7 N- hsram1.Instance = FSMC_NORSRAM_DEVICE;
6 ?! W- E, ]2 b. t- C - hsram1.Extended =FSMC_NORSRAM_EXTENDED_DEVICE;
O4 G6 t2 z5 [& p$ z) g1 H - /* hsram1.Init */
) {* z- \) v' C( p, x0 B, K - hsram1.Init.NSBank = FSMC_NORSRAM_BANK4;
0 a; P, ~. C$ ~ - hsram1.Init.DataAddressMux =FSMC_DATA_ADDRESS_MUX_DISABLE;
5 e. y) Q& h9 C3 f# B - hsram1.Init.MemoryType=FSMC_MEMORY_TYPE_NOR;: u3 N3 M- G1 \: j# Y' Y8 J) i) D
- hsram1.Init.MemoryDataWidth =FSMC_NORSRAM_MEM_BUS_WIDTH_16;( W' }8 F9 A, H$ ], j- j
- hsram1.Init.BurstAccessMode =FSMC_BURST_ACCESS_MODE_DISABLE;. ] I3 T" J! G( S$ Z: _
- hsram1.Init.WaitSignalPolarity =FSMC_WAIT_SIGNAL_POLARITY_LOW;
- J- [$ F" F" w - hsram1.Init.WrapMode =FSMC_WRAP_MODE_DISABLE;
- h8 Y- Z I$ z. K - hsram1.Init.WaitSignalActive =FSMC_WAIT_TIMING_BEFORE_WS;) s1 b, ~. b& Z9 t# _* S* p4 z& D
- hsram1.Init.WriteOperation =FSMC_WRITE_OPERATION_ENABLE;
. i* A- k1 u( H7 @3 _, \9 o8 m - hsram1.Init.WaitSignal =FSMC_WAIT_SIGNAL_DISABLE;* Q- L4 x3 g4 o$ g% [* {" T
- hsram1.Init.ExtendedMode =FSMC_EXTENDED_MODE_DISABLE;, r5 \3 h+ [) ~- ~8 \' s; b
- hsram1.Init.AsynchronousWait =FSMC_ASYNCHRONOUS_WAIT_DISABLE;, K2 @" ~2 c9 V; ?2 f1 P
- hsram1.Init.WriteBurst =FSMC_WRITE_BURST_DISABLE;
5 Z* n% Q5 ~/ I6 q" E& l, A - /* Timing */- G; V7 m# J+ q5 X4 ~' g c
- Timing.AddressSetupTime = 0x04;! d' h& ~) ^: u
- Timing.AddressHoldTime = 0x02;( `; Z" l# r& s. \0 z' C! n
- Timing.DataSetupTime = 0x08;$ S* W9 V* o+ D9 e# e) b: z' {
- Timing.BusTurnAroundDuration = 0x00;5 G% K& _( i' x7 f! d( L6 k
- Timing.CLKDivision = 0x00;( U8 Z5 [* \3 q# C! K0 p/ s( |
- Timing.DataLatency = 0x00;
: A# M H" m) l. g - Timing.AccessMode = FSMC_ACCESS_MODE_B; 后面数值决定读写屏快慢。
复制代码
5 y& ^! p3 F+ P' U* e3 H" N0 w9 K9 E8 f
注意点:- / Y" I' l3 A9 Q! r, a4 v+ J+ q
1 因为STM32的地址是32bit的,数据是按照8bit组织的,如果lcd的数据选择8bit的话,地址A0就是正常的输出,如0x60000000输出A0=0; 0x6000 0001输出A0=1;对应数据是byte;如果lcd的数据选择16bit的话,地址A0就,如0x60000000输出A0=0; 而0x60000002对应A0=1;对应数据是word,也就是说每两个原来基于byte结构的地址对应一个地址线上实际的word长度的地址;
- b/ S9 g5 H- N, v9 P
2 f. K' p8 I0 h3 l- #define Bank1_LCD_D ((uint32_t)0x6C000002) //DispData ADDR- w- ]- u3 E, K* Z1 Y
- #define Bank1_LCD_C ((uint32_t)0x6C000000) //DispReg ADDR/ x- S s. ^2 I' R6 q( g v
1 \/ O y4 ]. y8 R; @- void LCD_WR_REG(uint16_t index)0 I5 ]; j/ b( b! P
- { *(__IOuint16_t *) (Bank1_LCD_C) = index;}7 Z6 Y% t9 d3 O" O4 J: y
- 6 J0 t3 D1 w8 Q0 g5 m
- uint16_t LCD_READ_DATA(void)8 H0 K! n. V& W& \& n# h( z
- { uint16_ta = 0;4 D: h3 N3 t7 [3 m
- a=*(__IOuint16_t *) (Bank1_LCD_D); //L
0 m- m$ K4 ]3 k4 l - return a;) T0 N4 r; @' W+ x' g' v
- }
复制代码 2 Image2LCD软件转换时注意扫描方式和数据位宽度,以及高低为顺序。: e( Z. Y) p! f( T2 y; u; ^3 I/ x
l# E$ u1 q4 C实际效果:' J8 O" e g; g5 f+ O+ ]7 C
0 Q3 d2 K& S( q6 W$ ^& w ^2 Y- r/ }& V4 _/ `( Y! H8 \( j
7 o3 V" U3 }" | |