STM32F1系列单片机有多种外设,外设配置方式比较一致,一般是使能外设所在GPIO口时钟、使能外设的时钟,在禁止外设的情况下配置外设的时序以及中断和DMA等。大部分的外设配置相对简单,但是FSMC接口因为配置比较复杂,往往让一些初学者一头雾水。本文记录了本人在STM32F103ZET6的FSMC接口配置调试TFT LCD屏相关注意事项。
; _- |4 O# L) y! e: Y; q1 FSMC接口GPIO配置
. M- o3 t A& c8 f' }9 _- /** FSMC GPIOConfiguration
3 j& B, r" D8 d+ P# K& N' q - PF0 ------> FSMC_A0
' j* g' _0 J+ r& c* W, t - ------> LCD_RS: 0: Reg,1:Data
6 k8 m7 {2 S0 b# @5 n- H - PE7 ------> FSMC_D40 R8 v) q- K5 E8 {1 \
- PE8 ------> FSMC_D5
8 ^( l1 w G' ^- i! K# a - PE9 ------> FSMC_D65 o% A m& ^1 Z# I& n
- PE10 ------> FSMC_D7
( L- _, }) O* R _, v - PE11 ------> FSMC_D8
: l. ]& s) M' ^3 M1 g' ~$ f" x - PE12 ------> FSMC_D94 h7 k" ?0 c$ a6 T! U
- PE13 ------> FSMC_D10
" I \) s! k2 r - PE14 ------> FSMC_D11
- B5 z$ q9 P& } - PE15 ------> FSMC_D12
3 ?2 h5 s# u8 p) |8 Z6 w! w - PD8 ------> FSMC_D133 O9 `/ H3 O) i, k& G2 D) X. n! S
- PD9 ------> FSMC_D14
; d& y% w3 p% _6 o: a - PD10 ------> FSMC_D156 Y# b+ Z9 W5 I8 o2 J; Y
- PD14 ------> FSMC_D0
c( X5 H% G; s! d a$ N4 a. j3 Q - PD15 ------> FSMC_D1
$ y1 U3 O5 w8 h) U4 L R - PD0 ------> FSMC_D2+ ^$ i7 L, d& c: C0 U
- PD1 ------> FSMC_D3& f# Y9 g3 w* P
- PD4 ------> FSMC_NOE3 Y4 x, ]* ^" z: J/ O3 M
- ------> LCD_RD Default:1,Value:0 ) D1 j1 `, d9 n+ G
- PD5 ------> FSMC_NWE
4 C/ J: H) b: s - ------> LCD_WR Default:1,Value:0) x) C/ U/ n0 X; m$ h3 t
- PG12 ------> FSMC_NE4. U9 J' G2 S" a8 A' H$ \
- ------>LCD_CS Default:1,Value:0
复制代码
- h: n0 P, ^& ^7 R# f/ l" p7 i; c; }2 初始化FSMC时序! ~+ P6 T0 d+ o5 ^* {9 s7 l. ?
. Y4 x2 t- N% @% I+ s1 u7 d- /* FSMC initializationfunction */
9 H, i" Y4 n$ @5 V M( ` - FSMC_NORSRAM_TimingTypeDef Timing;
$ E9 G, n2 h& H' R; G ^ - SRAM_HandleTypeDef hsram1;1 m! {$ ? g) e5 q7 _1 D9 g7 s
3 Z# L H6 P( Y; n) |4 e- hsram1.Instance = FSMC_NORSRAM_DEVICE;
6 ~" d. d9 B: ] - hsram1.Extended =FSMC_NORSRAM_EXTENDED_DEVICE;( ^1 W. L1 _- X9 \
- /* hsram1.Init */ ?- D3 v- C1 v* P
- hsram1.Init.NSBank = FSMC_NORSRAM_BANK4;0 z7 [. ^, H+ b+ w8 b
- hsram1.Init.DataAddressMux =FSMC_DATA_ADDRESS_MUX_DISABLE;2 k5 k9 j/ A# [6 S
- hsram1.Init.MemoryType=FSMC_MEMORY_TYPE_NOR;
; V) }8 x" F- d - hsram1.Init.MemoryDataWidth =FSMC_NORSRAM_MEM_BUS_WIDTH_16;
+ f; w. } I5 c: S - hsram1.Init.BurstAccessMode =FSMC_BURST_ACCESS_MODE_DISABLE;6 j0 N D; B6 S2 C9 h: W2 v
- hsram1.Init.WaitSignalPolarity =FSMC_WAIT_SIGNAL_POLARITY_LOW;
+ j& f- `6 m7 B: h5 L0 H - hsram1.Init.WrapMode =FSMC_WRAP_MODE_DISABLE;) Y, D6 J [0 J; d$ W: y
- hsram1.Init.WaitSignalActive =FSMC_WAIT_TIMING_BEFORE_WS;
7 A) K1 M9 f2 x2 ]* m1 |" R7 A6 r - hsram1.Init.WriteOperation =FSMC_WRITE_OPERATION_ENABLE;( B+ l9 y9 T% R* g, o$ B- u: S
- hsram1.Init.WaitSignal =FSMC_WAIT_SIGNAL_DISABLE;+ a) Y: a* C2 b: Y6 l. U7 U
- hsram1.Init.ExtendedMode =FSMC_EXTENDED_MODE_DISABLE;
4 }$ n' h& b- Y: e- z" P4 E: _6 A/ L - hsram1.Init.AsynchronousWait =FSMC_ASYNCHRONOUS_WAIT_DISABLE;1 i# `( Z! Y9 g7 a" F7 R
- hsram1.Init.WriteBurst =FSMC_WRITE_BURST_DISABLE;9 t7 ~$ k' a5 h/ x1 g9 v
- /* Timing */
8 F0 q: t/ U2 X' { - Timing.AddressSetupTime = 0x04;8 r2 f9 m; ^) H5 u* p
- Timing.AddressHoldTime = 0x02;& W9 y* O( S$ g
- Timing.DataSetupTime = 0x08;; _3 P, s% x0 X
- Timing.BusTurnAroundDuration = 0x00;7 T6 ~$ l1 O9 F5 K9 |
- Timing.CLKDivision = 0x00;
6 p6 L8 ~- ?9 R/ R, { I8 R" t - Timing.DataLatency = 0x00;
, D5 A9 s* |2 ?$ n/ r/ G - Timing.AccessMode = FSMC_ACCESS_MODE_B; 后面数值决定读写屏快慢。
复制代码
; e% n; O+ @' F) O- C2 A* K4 f# ~4 \; v3 }* Z
注意点:- . n8 [8 }; M1 q) o; A1 { Y
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长度的地址;: H6 M% A& k& K" G+ C
7 A+ M" J2 ], X7 V! x0 Q- #define Bank1_LCD_D ((uint32_t)0x6C000002) //DispData ADDR
& z4 y2 V$ X, ~$ W - #define Bank1_LCD_C ((uint32_t)0x6C000000) //DispReg ADDR
R# \6 ~ X# U3 n6 L
( ]: z# u- J3 t$ s8 d2 M- P" s" [" W- void LCD_WR_REG(uint16_t index)
' \* {! `% L4 p5 |% X; e - { *(__IOuint16_t *) (Bank1_LCD_C) = index;}
& Q6 P. t& S, V, x6 c5 q( ]& x3 y - 6 X- w; }) H) r2 u: \$ c% A% g
- uint16_t LCD_READ_DATA(void)5 }/ G. C3 h: Z# J' s
- { uint16_ta = 0;
1 D% K) H! b2 L6 W& U' s( d - a=*(__IOuint16_t *) (Bank1_LCD_D); //L0 p: X* p- t! R5 H- f: U p
- return a;
" h5 _9 C5 G$ n0 e. o9 o' p - }
复制代码 2 Image2LCD软件转换时注意扫描方式和数据位宽度,以及高低为顺序。1 W1 Y* U( N; ^3 x
! R9 k9 `+ m# Y0 K9 ^; N实际效果:
6 \; X, a& z$ k2 z3 U3 C3 G
! D) U. @+ U$ G/ f4 C1 j) s8 \& `
* r$ c0 |' d* \( t% [( }4 I
' C" C8 A( x# ?2 H! r |