问题:8 F$ F$ s/ t/ p: `5 F! g
在合计智能穿戴应用的时候,为了更好的用户体验和丰富的人机交互界面,需要更多的存储(RAM 和 FLASH)来存储自定义的图片资源 ;由于可穿戴类的产品体积都非常小,因此 FLASH&PSRAM集成在一起的 MCP 存储芯片是一个不错的选择.8 { `+ e; i4 n, n* X* k% a
我们的 STM32 FMC 外设是可以支持 MCP 存储芯片的,而且只需要简单的配置就可以实现MCP 的访问.
# Z# [/ M6 t+ S7 C) w9 j h. ~- i7 @
6 H# J, G) L) s% a6 ?- ^" O0 t3 \% {+ P$ G& _
调研:
$ i$ ]" ~) A2 ?" p1 }; K下面介绍使用 STM32CubeMX 配置 MCP 驱动的过程,我们使用 STM32F429+MX69V28F64 举例说明:+ ~6 n3 [7 O# ~
6 t1 Q/ U c* G- v9 Y. x/ a
一、配置过程:
: h% L4 x2 C3 S+ y' I' r6 J1.MX69V28F64 的总线结构和 PIN 定义:* G% k: h' ^9 m( b$ m6 H
) m' T- E' n* x% D" k
! m" ]/ y" O% Q) O0 U2 B' O
5 G1 Y7 b6 _, c
2 A* j% N+ |% [5 `& ~" b1 y4 {! E1 J- c9 O3 o3 |" R
2.下面我们使用 STM32CubeMX 来配置 MCP 接口:
" |& G0 ^$ N. f2 U+ G2 ]3 Ta.新建 STM32F429ZIYx 的工程,在 FMC 根据 MCP 芯片来配置 FMC 的参数:: Z( d6 T# B! K: N) Y( M, r, ?
9 t8 O) ]& p* M& q
! S7 |/ ~4 r& m- e# [9 t' |4 Z9 x; D; J$ ]2 B4 {- s
b.在 configuration 选项卡中配置 FMC 的详细参数,7 Z! h0 |% {9 L8 K/ i$ J2 N, G5 ?
8 p& P8 A9 K$ l/ G/ `: |
! n D* v2 y0 x8 Y0 a0 y
( F# G0 b% ~% B6 |0 @c.根据 MX69V28F64 datasheet 中对时间的要求来更改 NOR/PSRAM timing 的参数:- _$ U# R Z0 ? w- `
# k! { H$ k: ^7 U# E c) b
( S9 u6 v+ M" W" A+ D) W% h8 B! m
* T( c" d2 `/ H. ?: bc.配置完成后,生成代码,FMC 主要初始化如下:
, L4 _- E0 L9 e3 M, l4 c' i- /* FMC initialization function */
( B/ x! @- F8 s - void MX_FMC_Init(void)% p: w+ j2 D# J0 K# O5 @) U/ ]
- {) O: j. g/ W2 a, K% u8 z2 _
- FMC_NORSRAM_TimingTypeDef Timing;
. P5 b3 t b7 Q7 ^5 K4 C - /** Perform the SRAM1 memory initialization sequence
7 y2 ]4 d/ q) w) c - */0 D5 N( H" O) i8 J/ f3 K, N! R
- hsram1.Instance = FMC_NORSRAM_DEVICE;5 S% n Q4 G8 `
- hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
5 T! I, j/ _! X d+ E D- r - /* hsram1.Init */: I; ]2 A1 L5 k( J
- hsram1.Init.NSBank = FMC_NORSRAM_BANK1;
0 o r6 j8 W y4 V' J4 F, [' P - hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_ENABLE;
, s# C- \/ X3 O0 d# S( I. y - hsram1.Init.MemoryType = FMC_MEMORY_TYPE_PSRAM;9 ^- [* C( p8 g
- hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;4 ^! V. B# q; _+ C6 y- q
- hsram1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;7 N- \( c) v1 E
- hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_HIGH;$ d6 m0 {: x7 y; {# N
- hsram1.Init.WrapMode = FMC_WRAP_MODE_DISABLE;4 b! g+ i+ E$ b) V7 i. ?- v! c
- hsram1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
+ R+ ?$ W. w) `, L" J$ D - hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_DISABLE;
$ l% l3 m. o' U) j' L: c' N; K G - hsram1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;3 i; O i( A! d6 ], o
- hsram1.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;7 w2 n M! e4 x! W1 ?% \1 g8 `
- hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_ENABLE;; J5 x7 I) c- b" Y' N
- hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
* ?/ p0 Q5 }! ]5 L$ S: d - hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
2 l# w4 u _! w1 e - /* Timing */0 i0 {" ], n# d P
- Timing.AddressSetupTime = 2;
- v+ q- b2 c5 A9 V5 G; O6 ~ - Timing.AddressHoldTime = 2;3 g! m. w6 h6 E! `8 o
- Timing.DataSetupTime = 6;0 H( I3 R4 n6 c' {: r% d
- Timing.BusTurnAroundDuration = 0;
6 t2 g! E( t) r - Timing.CLKDivision = 16;
7 _$ o& e$ z$ g - Timing.DataLatency = 17;8 y s: Q" _% k+ Z1 p
- Timing.AccessMode = FMC_ACCESS_MODE_A;
7 P- A; ?1 a- W! V( l% b - /* ExtTiming */5 b* E, L- a" R3 z2 f
- HAL_SRAM_Init(&hsram1, &Timing, NULL);
0 F, o* d1 w. J/ M# T - /** Perform the NOR2 memory initialization sequence
6 }! ~3 e1 P7 X3 T l% Q - */8 N1 H' n. c+ ~: ?( G; I5 z( {+ ?& V4 ~
- hnor2.Instance = FMC_NORSRAM_DEVICE;# `) L: x+ U; c8 o4 }& s7 ?
- hnor2.Extended = FMC_NORSRAM_EXTENDED_DEVICE;* M4 V/ J" T: D8 e# e
- /* hnor2.Init */
8 B, W& S/ }! K5 s$ w1 A - hnor2.Init.NSBank = FMC_NORSRAM_BANK2;9 }) E4 y) K' x% R
- hnor2.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_ENABLE;
9 V* C. \: s) |$ t* l# \7 o0 X - hnor2.Init.MemoryType = FMC_MEMORY_TYPE_NOR;( k! B" a/ b: h% W% U0 i7 z" ?7 w
- hnor2.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
' W; N" c& ?. C - hnor2.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
+ Q; F9 h7 n- G# D3 O - hnor2.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;, v! t2 L; ?( Z( E Z
- hnor2.Init.WrapMode = FMC_WRAP_MODE_DISABLE;( I; f! X0 p, G$ Z ?' O0 ?3 p, _
- hnor2.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;1 h4 M" U6 T* a& O
- hnor2.Init.WriteOperation = FMC_WRITE_OPERATION_DISABLE;8 p( @8 W3 |( _9 q; z+ A
- hnor2.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
1 C) }! o& n, C. z- e - hnor2.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
9 P) k% U* g* O3 U3 d$ g - hnor2.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;3 C% }% Z; a! J$ M# D; y
- hnor2.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;7 u' {$ Q9 H0 r0 k3 u1 ~/ Y; u
- hnor2.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;: q2 ~6 C# e2 R. b2 y- S; a
- /* Timing */+ V; P2 e) t+ O
- Timing.AddressSetupTime = 5;1 V3 @% w& l4 g8 X/ b2 Z* R$ `/ p; t
- Timing.AddressHoldTime = 15;
/ W* r7 U8 A! F- I2 I9 f8 `* C' c @ - Timing.DataSetupTime = 7;; _) p \% W0 `+ c" n) l$ j
- Timing.BusTurnAroundDuration = 2;
( O: k" X: i, O- Y - Timing.CLKDivision = 16;
" E& S! s- i+ U6 K& P O; C - Timing.DataLatency = 17;
$ z+ R$ m: k Z/ p$ v# I2 @) H - Timing.AccessMode = FMC_ACCESS_MODE_A;
h7 R7 L! b0 z6 d3 u - /* ExtTiming */
; o3 Z1 V6 O& @+ x( w8 G5 o: D7 T - HAL_NOR_Init(&hnor2, &Timing, NULL);
( Z3 Y( k5 h, P1 H& K8 V& \; g - }
复制代码 : T; a6 K: X9 z" I9 Y
二、软件如何使用:9 z, t7 T" S2 X- B' ]# D
用户在编写软件的时候,直接访问 FMC Bank1 的分区地址即可,FMC 外设会生成读写MCP 芯片的时序.- M( q( K4 u1 `) h9 v
9 k& v4 L' u3 i- H9 m; P, T
# B- p5 A* u4 H7 l
3 {$ p) ^4 u/ ?, x; @2 y
: I! i3 r4 X& X! Z# G N
$ n( U" a$ g. ~' g |