STM32F1系列单片机有多种外设,外设配置方式比较一致,一般是使能外设所在GPIO口时钟、使能外设的时钟,在禁止外设的情况下配置外设的时序以及中断和DMA等。大部分的外设配置相对简单,但是FSMC接口因为配置比较复杂,往往让一些初学者一头雾水。本文记录了本人在STM32F103ZET6的FSMC接口配置调试TFT LCD屏相关注意事项。6 s( @ T! k( J: X6 u
1 FSMC接口GPIO配置- / l6 i& D1 m. W7 B! J
- /** FSMC GPIOConfiguration
" Q* v& h k6 S6 X - PF0 ------> FSMC_A0 ( _7 Z5 x9 S$ P7 M1 T3 D: D0 d
- ------> LCD_RS: 0: Reg,1:Data
' e' J% _' Z8 G3 g2 i - PE7 ------> FSMC_D4. [7 b: A& n8 y' B8 Z
- PE8 ------> FSMC_D5& W! C. ~7 o) k/ a$ @ u2 @9 P
- PE9 ------> FSMC_D62 Y6 L8 Z3 c, P4 F# L/ C
- PE10 ------> FSMC_D7+ W+ D9 {, ]1 l' G* q) `' e6 X s O: P
- PE11 ------> FSMC_D8* A4 C- G, S$ b5 X2 n& |% D. x
- PE12 ------> FSMC_D9
g3 }& M& J6 | M7 T2 o - PE13 ------> FSMC_D10
7 }% B4 K+ U) } - PE14 ------> FSMC_D11
7 y- s0 G8 B) D; c6 u, p5 h. e# j* p - PE15 ------> FSMC_D12
# w3 q6 y1 N2 {0 g - PD8 ------> FSMC_D13
/ U' L, g% I- y& D/ V& q - PD9 ------> FSMC_D14
" V* ]7 {+ q5 p1 o9 A; I - PD10 ------> FSMC_D15
6 X1 Q% u( S5 a! ~% ` - PD14 ------> FSMC_D0/ {5 H! L2 v% m
- PD15 ------> FSMC_D1
8 F& k2 E/ X2 Y! u - PD0 ------> FSMC_D2# C, ]: e9 H: v: X7 h( A, G
- PD1 ------> FSMC_D3$ @9 Z3 N+ I7 h2 h* o$ h( ]# G
- PD4 ------> FSMC_NOE
. [1 F0 J# _+ ]. }% e6 ?( z - ------> LCD_RD Default:1,Value:0 3 f' x( |* N: {7 Z* Y( w
- PD5 ------> FSMC_NWE
/ G2 V* g1 O, S3 B2 _2 \ - ------> LCD_WR Default:1,Value:0
+ ]2 [9 _, p3 n6 { - PG12 ------> FSMC_NE4
# ~ C! y0 ]+ v. h3 j% D5 x - ------>LCD_CS Default:1,Value:0
复制代码
! [5 _# j, a3 B* T2 初始化FSMC时序1 v9 f( b* R; n) W
- * c; Z7 V' }4 g+ W j
- /* FSMC initializationfunction */
6 t3 \. [2 \0 j% D* x0 s9 K6 | - FSMC_NORSRAM_TimingTypeDef Timing;- f6 a+ c' l4 i% l
- SRAM_HandleTypeDef hsram1;
- {! c' ^4 a5 K& }
" A8 I" l- R6 j! |* v; w, \( K( }- hsram1.Instance = FSMC_NORSRAM_DEVICE;
6 @: b+ u' S- D9 s2 n% ? - hsram1.Extended =FSMC_NORSRAM_EXTENDED_DEVICE;! W: M6 F' N# R( n! D# m) l; g
- /* hsram1.Init */' ]; s% U" L! ]4 Y9 ?% e- {
- hsram1.Init.NSBank = FSMC_NORSRAM_BANK4;
: j/ q1 c. [1 h: V2 S; \ - hsram1.Init.DataAddressMux =FSMC_DATA_ADDRESS_MUX_DISABLE;
4 A" o; O3 D- ~ Z/ T% C6 l - hsram1.Init.MemoryType=FSMC_MEMORY_TYPE_NOR;
2 F' S; S# e- w) W# F) P - hsram1.Init.MemoryDataWidth =FSMC_NORSRAM_MEM_BUS_WIDTH_16;% H2 R- X% g3 w9 R3 \
- hsram1.Init.BurstAccessMode =FSMC_BURST_ACCESS_MODE_DISABLE;
& n4 ~3 `% z6 x- p" x! P; h: D. C - hsram1.Init.WaitSignalPolarity =FSMC_WAIT_SIGNAL_POLARITY_LOW;
2 N4 [% S: o( A5 S: ^ - hsram1.Init.WrapMode =FSMC_WRAP_MODE_DISABLE;# g% C. t! ?/ c+ J# q
- hsram1.Init.WaitSignalActive =FSMC_WAIT_TIMING_BEFORE_WS;* [, i. C; \$ N& W9 g: d8 c
- hsram1.Init.WriteOperation =FSMC_WRITE_OPERATION_ENABLE;3 s( K/ `0 _0 S5 ~. x
- hsram1.Init.WaitSignal =FSMC_WAIT_SIGNAL_DISABLE;
: s. }- D* s7 R; C+ \ - hsram1.Init.ExtendedMode =FSMC_EXTENDED_MODE_DISABLE;, Z+ R% Z" Y: p% }5 N1 Y, B# z. \
- hsram1.Init.AsynchronousWait =FSMC_ASYNCHRONOUS_WAIT_DISABLE;
2 S( E+ A$ E% ]- c - hsram1.Init.WriteBurst =FSMC_WRITE_BURST_DISABLE;. s \5 o6 Q% S7 Q
- /* Timing */
7 ^# q# z; Q: r8 T- X! m - Timing.AddressSetupTime = 0x04;) t' V9 n) S) g9 O" ?
- Timing.AddressHoldTime = 0x02;! Z, T# d' o# n
- Timing.DataSetupTime = 0x08;% g+ E" o R( ~* y
- Timing.BusTurnAroundDuration = 0x00;
6 \- w- C, h0 h4 o4 ~1 y) f! p - Timing.CLKDivision = 0x00;4 z( i1 A ?0 k3 x9 p/ J
- Timing.DataLatency = 0x00;8 P8 k2 r4 U- ]2 b9 ~
- Timing.AccessMode = FSMC_ACCESS_MODE_B; 后面数值决定读写屏快慢。
复制代码
& j- X' G- H$ `7 a- z+ x3 [/ E9 _
+ h5 }: ?# r2 z注意点:
0 q9 h) q- y" f0 G) p 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长度的地址;' R# R$ ]: C2 _& A
- " f0 G* H: D% u5 ]) ?" |" K% H* m
- #define Bank1_LCD_D ((uint32_t)0x6C000002) //DispData ADDR
) Q Q# R5 r& o& C - #define Bank1_LCD_C ((uint32_t)0x6C000000) //DispReg ADDR
8 G/ r6 x- S. P" M" H' [ - % K$ d e' S0 t! G3 ~, {) Z( ?
- void LCD_WR_REG(uint16_t index)
7 n7 T/ ]/ c' c+ W% t - { *(__IOuint16_t *) (Bank1_LCD_C) = index;}/ W% s) P8 O" t& U
- & \7 }' Y5 M( i6 V
- uint16_t LCD_READ_DATA(void)( }, \6 t; F3 s# S. e
- { uint16_ta = 0;- r' f9 H5 h& k' u4 P
- a=*(__IOuint16_t *) (Bank1_LCD_D); //L
' \, |" Z3 j6 V# @" y8 l - return a;+ j, G& l0 {/ w1 }; K5 N2 b5 ~8 t
- }
复制代码 2 Image2LCD软件转换时注意扫描方式和数据位宽度,以及高低为顺序。
9 n* X8 Z6 x7 f5 ]! n8 @) o) Q) O
$ q d3 a9 W3 o, F; |
实际效果:
@% c! Y. d7 W1 B% Y: K8 L
0 b2 q+ e$ }* a) h* G+ w% q* C+ x" j5 j) H5 f" y
m: Z9 K: x+ A4 q2 O
|