上星期六刚刚买的新板子,来处理下SD卡这个东西(后期还将做fatfs文件系统移植)
& I0 \5 f2 F& R' V6 N2 S- S
# ` t0 y7 N) o" t) P0 K% u
' s8 F4 `: m4 ]; O0 |) _& Z8 p" z图1 SD接口图
8 D9 A3 M% r1 o; G i: b) V/ R图1 的接口图不是完全正确的,每个PIN上都必须接一个50K的上拉电阻;
1 m, |% }) f/ l) R9 N d( x" c$ z8 [# o
在ST官方提供的库里面有很多意见做好的外设,LCD,EEPROM,等等,当然我们比较幸运,也包括SD卡,这次移植基于3.5的库: n% ?: v2 F' D8 E+ a
. W8 h/ Z3 b1 x8 g) D! b
我们要移植的文件在这个STM32F10x_StdPeriph_Lib_V3.5.0\Utilities\STM32_EVAL下:
, Y9 }5 @$ w& O8 ?2 ^' `/ U* z; ~( ]% P" m d8 M; l
! t; T1 k- t( p D- [: Z图2 移植需要的文件
8 W* i% T' Q- V5 C7 |7 x因为我的板子是stm32f103vet6跟STM3210E_EVAL比较相近,所以选这个;. z b( L1 R+ i2 }. R( @& R
, z: f1 Q2 {% z. ^
[7 k% Z0 }! n4 x图3 common目录
( S) S R7 K, {+ C% h' e把stm32_eval_spi_sd.c / stm32_eval_spi_sd.h 复制到你的工程里面,并添加;如果就这样编译的话有很多error和warning;
( S0 ]+ ]* p6 Q* l7 ]
! g1 v* b8 s$ H' L, q/ ~4 s因为他里面确实一些函数,这些函数属于API层、或者说是驱动层的,跟处理器有关,所以我们就要到STM3210E_EVAL目录下看看了。
, k, B7 U% r# r) h+ }8 V) B
# m. z* t6 ^8 o+ o9 j6 Z/ n如果你把上面那个直接拿过去编译的话,会提示少下面一些函数:, w A; Z6 I8 F
- [cpp] view plain copy
9 n0 _* v7 b ~ - void SD_LowLevel_DeInit(void); 1 z" Q7 j: }5 w
- void SD_LowLevel_Init(void);
5 Q+ ~1 _3 H u- b, T4 z2 @+ B+ W - void SD_LowLevel_DMA_TxConfig(uint32_t *BufferSRC, uint32_t BufferSize); + |, v5 V& h8 Y5 O5 y; s8 d$ k2 N ^3 l
- void SD_LowLevel_DMA_RxConfig(uint32_t *BufferDST, uint32_t BufferSize); ) H7 v4 J- x% v \
- uint32_t SD_DMAEndOfTransferStatus(void);
复制代码 和一些宏定义:
5 W/ R9 k9 B7 h' R. [3 d- [cpp] view plain copy- G) f( o( s8 }5 b
- /** & J5 Z* f, H& K9 W4 m r
- * @brief SD FLASH SDIO Interface - y, ]: t" P+ e3 S0 V$ ^3 X
- */
. v$ b9 O Z' u$ L; L9 Z -
* V/ V3 v+ I: M% c - #define SD_DETECT_PIN GPIO_Pin_11 /* PF.11 */ & ]% Q0 |$ N. a: B$ G( I
- #define SD_DETECT_GPIO_PORT GPIOF /* GPIOF */
, U4 ?% v8 Y8 i- ~2 P# o" i4 u - #define SD_DETECT_GPIO_CLK RCC_APB2Periph_GPIOF
" \% b M" T: A- S. K7 g - ! n5 }# J5 K/ C; }! M
- #define SDIO_FIFO_ADDRESS ((uint32_t)0x40018080)
7 b! z! z; U4 m) M* E Z - /** & U9 z4 y& V& D' E" _7 L
- * @brief SDIO Intialization Frequency (400KHz max)
; D; o$ p, x7 G$ T9 f1 o6 R7 G- V - */ 5 K7 ^$ c5 [% s) [
- #define SDIO_INIT_CLK_DIV ((uint8_t)0xB2) + R' y) a# m! Z. c/ X
- /** , b4 e% j" R/ N; z9 Q6 q
- * @brief SDIO Data Transfer Frequency (25MHz max) . d/ w0 `9 X" G) r; U* V% i
- */ 7 f$ e: |1 G* s4 m* L0 w, P. l
- #define SDIO_TRANSFER_CLK_DIV ((uint8_t)0x00)
复制代码 这些声明和定义都在STM3210E_EVAL目录下的 "stm3210e_eval.h"里面,找到他们并复制到stm32_eval_spi_sd.h里面,如果你不想找的话,直接把我的这些复制走就好了!4 ?6 o9 B6 t S$ g! Y; n
对应的函数也都在"stm3210e_eval.c"里面;
# @8 K1 b$ U" e4 |' P1 I1 u( N- [cpp] view plain copy
) E$ E8 o5 [9 E- Z* l - /** ; I; X. s: ]5 t
- * @brief DeInitializes the SDIO interface.
& B% L m1 D6 s0 b - * @param None
. C* o3 t- p" G( `: R8 Q- ` - * @retval None
9 @3 K0 ?: C% N - */ ' I9 G* {/ z+ G/ w
- void SD_LowLevel_DeInit(void) 0 f2 j) {7 k) {+ L, ]+ F
- {
. w. {! f& p: v7 f! @ - GPIO_InitTypeDef GPIO_InitStructure;
% Q5 n, j7 G! m" I, q -
( T2 u( v( ?: H* R2 F1 B - /*!< Disable SDIO Clock */
r% A. J0 Q; e9 N" Q$ a2 ] - SDIO_ClockCmd(DISABLE);
7 s* y3 l! n" m3 D -
* W; u, {" F0 J8 a! b8 p; V: W - /*!< Set Power State to OFF */
P; E) I0 m1 b& D* x - SDIO_SetPowerState(SDIO_PowerState_OFF);
" ~: g8 I4 `2 O% u$ f+ e1 O2 ] - + O/ g8 A8 |3 i
- /*!< DeInitializes the SDIO peripheral */
1 t+ r# T4 z2 `/ |" p! H - SDIO_DeInit(); ! |. X9 j* H, {1 R6 ]' [* ]
-
/ _ S3 O+ G& v, n - /*!< Disable the SDIO AHB Clock */ + n5 Z0 ~( m7 E( {( ^2 O; c- _
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SDIO, DISABLE);
: e! o& R# j5 q- b- b& q/ h - - @8 h$ C3 x# {5 E: r1 O" V5 `( v4 |
- /*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */
! |5 Y2 P5 e1 ^9 C' E - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
8 ^' ~$ y) q; ` [( k. t - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
: n( n* e- U4 D& K% I: u& @, M! \ - GPIO_Init(GPIOC, &GPIO_InitStructure); ! n9 N" i* E! [- J
-
! b+ N( o& c+ m - /*!< Configure PD.02 CMD line */ 3 l: r1 O3 g* D
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
" d4 ] [" S4 c- n! o- v8 [' S - GPIO_Init(GPIOD, &GPIO_InitStructure);
: ?+ V& e d$ M' i4 p3 S8 O: _ - }
/ L. L+ S0 z. d: u/ ]+ D9 W -
) L0 h, S9 m7 b. s - /** + @8 v7 `6 ^+ Q0 O
- * @brief Initializes the SD Card and put it into StandBy State (Ready for / I0 Z! ?8 [& C- ]
- * data transfer). ' E& T6 H9 V& }! Q4 C9 W6 U
- * @param None 9 ^' e8 g& n/ k- q' c% f' D
- * @retval None
* s7 d: `3 Y! m4 p d d1 v; x9 _$ | - */
: `8 R7 L. T6 V" H( D3 @) s; X - void SD_LowLevel_Init(void) ; y ^7 h+ ^ V, X% d; Z
- {
, ]5 @/ l5 L/ {$ U" _& ^6 w - GPIO_InitTypeDef GPIO_InitStructure; , A! T7 o& w2 g+ R$ S$ W
- / o3 B7 u( F- @& n1 i
- /*!< GPIOC and GPIOD Periph clock enable */
7 O! k h) y& s% J& }3 w2 ` - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | SD_DETECT_GPIO_CLK, ENABLE); ; F e8 \% |; y% C8 A# w+ v
- + T$ a) C3 K$ s2 q! a; k
- /*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */ 4 }2 v% T8 B1 j& B* G
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
$ Q# J$ V( j* \. V' J" H - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 4 P. a- D) e1 O2 H# ?* t
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; - I$ f! X' t4 T
- GPIO_Init(GPIOC, &GPIO_InitStructure); 3 ~) o0 ~8 |5 |1 X1 r% A; b
-
; k8 Z) B- C* ?' s' G( G% M - /*!< Configure PD.02 CMD line */
# |9 C4 {4 {* @- X - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
7 B1 D4 b0 R: C* j9 T4 R& F - GPIO_Init(GPIOD, &GPIO_InitStructure);
5 Q$ @5 K' o( {8 ` - 7 _$ H/ I3 R! c: |/ [6 t
- /*!< Configure SD_SPI_DETECT_PIN pin: SD Card detect pin */ # W+ k* @( a: m# t5 X
- GPIO_InitStructure.GPIO_Pin = SD_DETECT_PIN;
, G$ {' s6 |6 R& e - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; g1 g9 l k8 S; L
- GPIO_Init(SD_DETECT_GPIO_PORT, &GPIO_InitStructure);
# N: Z4 s. ^8 h( B -
3 c; Z4 n# f- H& x - /*!< Enable the SDIO AHB Clock */ 0 @8 ]1 E7 g: D8 N( G7 O% j; l
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SDIO, ENABLE);
1 Y- `; _! o& @) Q2 r# [ - . s) u- n; @. w) v4 W
- /*!< Enable the DMA2 Clock */ ' A! g S- x; u& V
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); , t/ t/ d2 p. B. Z7 `/ l) N2 \
- } . e; e+ ^$ P* ]" H3 |! o. U* K
- , k( B/ p. h5 _! @4 |# q
- /**
0 o. }9 h8 p( A, S. m) h - * @brief Configures the DMA2 Channel4 for SDIO Tx request.
4 M9 }& W0 z5 n - * @param BufferSRC: pointer to the source buffer
5 S8 H# n5 Q! {1 {# b- n4 }$ ]8 q - * @param BufferSize: buffer size
' h7 q/ o: b& N, J8 k6 i - * @retval None M+ m/ C1 m, v. l
- */ ) I, [$ D* Y- D" t" Z' y6 Q: j: C
- void SD_LowLevel_DMA_TxConfig(uint32_t *BufferSRC, uint32_t BufferSize) 6 |/ N, k% d* ]- K
- {
& W' k+ J* F8 k" W - ) h5 q# E) Y9 A- b0 ^
- DMA_InitTypeDef DMA_InitStructure; H7 V4 K' Y m* r: p
-
u* [$ q6 ^2 F/ U% r3 a# @: w& C2 @ - DMA_ClearFlag(DMA2_FLAG_TC4 | DMA2_FLAG_TE4 | DMA2_FLAG_HT4 | DMA2_FLAG_GL4);
# g( R. L! x/ F s s' a: P -
% R0 q9 ~* }4 |6 i9 R - /*!< DMA2 Channel4 disable */
5 M" \- Z! `" }3 Q+ G; Y( G/ O. _ - DMA_Cmd(DMA2_Channel4, DISABLE); 8 a5 \1 l( n' b7 D* q
-
' B4 w6 m5 L7 b3 O. _- k - /*!< DMA2 Channel4 Config */
+ d8 `" `7 P7 x - DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SDIO_FIFO_ADDRESS;
# w/ V: \7 y1 t2 \9 f* z - DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)BufferSRC; 1 O: E2 P) Q( k, [9 r4 `
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
' I7 N- L2 a R# t/ I - DMA_InitStructure.DMA_BufferSize = BufferSize / 4;
2 Z O" K0 Z* N9 l& n. K8 e1 t - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
% H1 s2 j4 M7 x9 h/ u - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 0 F. c o! V) A( B E
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; 9 }: L: b9 F8 _# _: j
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; 3 z6 E+ X6 K) P; _& }
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; ) R+ u6 c# a! I& S+ x, n
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
$ z1 Y" q' e4 R, v2 }; q4 R/ O - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
8 i5 y/ M& Y" N( b" B - DMA_Init(DMA2_Channel4, &DMA_InitStructure); . H! I3 y; {# ?0 t$ H
- 7 v1 g1 V# i) M9 \+ @
- /*!< DMA2 Channel4 enable */
6 y7 k. m! O" ~ z - DMA_Cmd(DMA2_Channel4, ENABLE);
4 s0 w8 \3 U9 H% O. A( X - } $ {% u. q, g; z7 ?0 D( t1 }
- 2 M' Q" p' S' Z7 E" ^5 E- [' y
- /** ' }/ l% E2 X' N m
- * @brief Configures the DMA2 Channel4 for SDIO Rx request. 9 B# o: N. v3 t
- * @param BufferDST: pointer to the destination buffer 3 m- H- Q1 o7 k" `
- * @param BufferSize: buffer size 8 O) u+ }7 T; [& e& }
- * @retval None
* w! C9 z, Y g ~7 l - */ 7 K9 z. Z& e& {
- void SD_LowLevel_DMA_RxConfig(uint32_t *BufferDST, uint32_t BufferSize) ' [4 q5 ] W! z: P
- { 8 ?3 p) x5 T$ a6 A
- DMA_InitTypeDef DMA_InitStructure;
- C* e1 q" g# `. k. n: z - % B8 J; @# u% a3 K$ X
- DMA_ClearFlag(DMA2_FLAG_TC4 | DMA2_FLAG_TE4 | DMA2_FLAG_HT4 | DMA2_FLAG_GL4);
2 {; q( g- Z9 j( ]8 w - 6 U% j$ e8 t) U X. t" j/ O4 W
- /*!< DMA2 Channel4 disable */
3 I/ d1 f# `9 G - DMA_Cmd(DMA2_Channel4, DISABLE); * v- n$ p5 b( \5 J4 g5 ]
- " F; M$ M5 D2 N6 V' j! M
- /*!< DMA2 Channel4 Config */
: d' z7 P4 c* r1 b) J8 _( A) H- I - DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SDIO_FIFO_ADDRESS;
+ z% h( o0 { r; c4 m, {8 \ C1 g - DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)BufferDST; 2 e7 _3 g2 J! P* M9 ]. e$ r! q
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
0 m+ b* }# |+ a+ [) w; v5 X - DMA_InitStructure.DMA_BufferSize = BufferSize / 4;
5 l, t7 S' b! \$ R - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 7 {& U/ @' M# T3 U" r6 w
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
3 M7 _6 b- r' Z m6 N: ?+ Y - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; 5 q3 D+ O4 v4 R! E
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; 2 S4 m% i7 L4 j1 M! k
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; : [- h1 `" o9 t* b M- E
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
# e! m( A# Y2 n+ u! y) H - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; z6 f+ m( }2 V& X
- DMA_Init(DMA2_Channel4, &DMA_InitStructure);
& B! z1 D4 x* I# q/ X; U -
6 V* U! ]; f! z- A - /*!< DMA2 Channel4 enable */
6 H% S1 z' l; H8 r - DMA_Cmd(DMA2_Channel4, ENABLE); ; V' u: `) @: R' Z3 A
- } , F, ~% z1 [' c' h- ^ i/ W* \$ b
- . ?) J2 ]5 `4 \
- /** 3 X4 ~7 w; `- @: d, R
- * @brief Returns the DMA End Of Transfer Status. ; f5 Y9 c% O% U/ K1 P9 z
- * @param None # L$ f# K- r/ @
- * @retval DMA SDIO Channel Status. ; _/ Y, h# a, j/ k
- */ ! T& S+ x6 P1 c# N
- uint32_t SD_DMAEndOfTransferStatus(void) + S6 V- n" m" P" o- Q; H
- {
* B0 N- ~9 y. O5 m) y6 K8 |* t - return (uint32_t)DMA_GetFlagStatus(DMA2_FLAG_TC4); & |' ^' T& g& t; Z
- }
复制代码 同样,把这些复制到stm32_eval_spi_sd.c里面;你也可以从这里直接复制! L, i: r6 B0 Y5 Q) K+ R
就这么多,如果你不是我这个平台的处理器,那么一定要注意找到适合你自己的再移植!8 Q4 r4 Z. g# d/ P
) Y) T& N3 R6 C& g0 M: U/ b+ n如何判别是否适合呢?
' `* `8 g3 v8 L* C$ O. e) P$ {3 D/ x X( F6 V
在STM321xxxE_EVAL目录下的stm32xxxe_eval.c里面看函数void SD_LowLevel_DeInit(void);看他初始化的管脚是否是你的外设管脚;- p+ m9 Y h, V0 T0 H J6 S
- [cpp] view plain copy3 z& H1 \( h5 q: g
- /*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */ 3 U9 Q- i* q2 y- \
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12; 0 \5 g, N* @+ A2 [
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; I+ i, Z' c" h j _4 b( D2 i! E( Z
- GPIO_Init(GPIOC, &GPIO_InitStructure);
复制代码 OK!这些移植好后,我们可以到STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\SDIO\uSDCard里面把例程移植一个看看效果怎么样;
4 a% [# E& |' x N4 u& n. ~我这里用了这个代码,看看他有SD卡有多大:: ]- x5 N, `* q2 w# U' c
) E, v# R0 q1 B" N) {9 B+ W1 d
- [cpp] view plain copy
/ R5 T* a' U/ w( W - Status = SD_Init(); 9 s( ~# u. l7 j1 h
- Status = SD_GetCardInfo(&SDCardInfo);
! e" q. Y6 K# j8 s6 M - printf("%d,%d\n",SDCardInfo.CardBlockSize,SDCardInfo.CardCapacity);
: ?- v/ G2 P: ~3 p, h# @1 Q - Status = SD_SelectDeselect((uint32_t) (SDCardInfo.RCA << 16)); 1 P7 Q- z1 P, |. S) g+ A
- Status = SD_EnableWideBusOperation(SDIO_BusWide_4b);
/ f) n( o A1 Y0 Y - Status = SD_ReadBlock(buff, 0x00, 512); 5 V. m; n# c. Q/ @! e
- if (Status == SD_OK)
0 R9 f( n2 A! n4 I* m - printf("\nRead%s",buff);
z4 R& ~& P2 R* m" x/ s9 V8 r - printf("Test SD OK!");
复制代码 % U- w# O/ z- L8 K0 L+ A
% Z# \" {+ r& H4 w4 m+ D
) v8 D" q$ j* a, O/ B" O% U6 W图4: 效果图
, e) T' E" j6 `. R$ [ J$ u Q【1:block size 2:memory size 3:read message】
) y3 @! f! P/ B% o4 b" u! T0 \$ ^. w- Y
K# J/ t. y# K+ a
* X5 E% G" o3 Z- y) b, U
转载自ieczw
: F% s& ~: t( c+ O& Q# p: a# ~
& L8 l, I2 K, B. B8 X! L |