STM32f746gdiscovery 开发板使用的是16MB的SDRAM,由于少了一根地址线,只有8MB可用。
& T% O- U; n5 o) z1 n k8 V( v1 ~- n. I# G, D
4 M! N: j: c; E3 S
/ ~8 P* _- b3 o1 \3 v
' x/ _+ a, X" l, [- /*************************************************************************************************************
5 U' n) v, u; K6 t - * 文件名 : stm32f7_sdram.c
& o" o# Z9 O, Q( j! y - * 功能 : STM32F7 外部SDRAM驱动) q5 b/ R! q( F L M3 r# k1 o" F
- * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
: r* [7 X( {' A/ X, X- O2 X - * 创建时间 : 2019-09-08
5 E" r& X) b- c- f2 x6 j5 Q" s5 r - * 最后修改时间 : 2019-09-080 B# ?- n5 s( m
- * 详细 : 2019-10-31 设置突发长度:4(可以是1/2/4/8)-测试过1/2/4发现都正常,唯独8的时候,屏幕会出现随机噪点
/ Q$ L$ a8 d6 A( @ - *************************************************************************************************************/
+ S; A5 _& p& n/ M3 [& p - #include "stm32f7_sdram.h"
9 V$ h, P, ]* Q0 t7 @7 U - #include "SYSTEM.H" 8 w. H5 k4 e. u" {+ _ @7 k, ]' |
- . S1 @7 Y/ S) L1 w# Q* x2 _
+ q) Z1 a$ X$ r( p
, r0 C3 V' N. b' {. W) T& c4 U- //BANK选择( U% N% j1 }7 N; Y: W& Q
- typedef enum
; Z3 y/ x1 m7 {; F* J - {
9 _8 _. Y% {" |( W/ r/ N1 m; q - SDRAM_CMD_BANK1 = 2, //命令模板存储区域1
4 p1 o5 ~1 ? l6 P - SDRAM_CMD_BANK2 = 1, //命令模板存储区域2* w) k( n' P6 ~! j: ?% P
- SDRAM_CMD_BANK1_2 = 3, //命令模板存储区域1与2% K# e- f5 F/ h
- }SDRAM_CMD_BANK_SELECT;
. k) Y6 A8 G x; n2 V+ ^8 C
2 Y: ]/ S, ^# }$ j7 R. p- 6 N1 N$ N& d/ [& C/ }2 W
- //命令9 f4 t* H7 J8 X
- typedef enum 8 S+ C! F- ?- ?- R7 N
- {
% J, a! E% u6 @( ~: Z' r8 v - SDRAM_CMD_NORMAL = 0, //正常模式- j3 f5 g! v3 U7 Y; q! Z& f
- SDRAM_CMD_CLOCK_CONFIG = 1, //时钟配置使能" u( d7 y4 @+ t. L2 x
- SDRAM_CMD_PALL = 2, //预充电所有存储区域
# P: W: b8 n0 _3 u! b: ]4 x/ t% v3 Z - SDRAM_CMD_AR = 3, //自刷新命令
/ S( x1 {3 G6 o2 { - SDRAM_CMD_LOAD_MODE = 4, //加载模式寄存器
8 L4 r! D l+ Y' a2 {8 ^% r0 \ - //SDRAM_CMD_AR = 5, //自刷新命令3 ?/ }: f* P# P9 H, _. {
- SDRAM_CMD_POWER_DOWN = 6, //掉电命令# B8 Z5 }* d* Y* q& @
- }SDRAM_CMD_TYPE;/ \" J, q; C$ a8 \
- ( F# E1 Q* p2 k* q
- + a2 a( g. w% d8 i' m/ e
- bool SDRAM_SendCmd(SDRAM_CMD_BANK_SELECT BankSelect, u16 mode, u8 AutoRefresh, SDRAM_CMD_TYPE cmd);//SDRAM 命令模式设置6 p: R$ ~1 z! c$ R7 l
- 6 V' F8 b8 Z9 ?5 C
- 7 R- m) X! J% J) k) K8 U ~
- /*************************************************************************************************************************
" X4 f7 @5 e$ ]& f7 l - * 函数 : void SDRAM_Init(void)
* T2 t1 s: i# [. O5 c - * 功能 : SDRAM 接口初始化5 k b+ Q+ B$ O
- * 参数 : 无
A! M/ ~/ U' o( G; n, [ - * 返回 : 无9 n/ o5 }* A% d9 N
- * 依赖 : 底层宏定义/ S) ^+ y T, ~1 y7 ]
- * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
& F# F$ X6 c# Z1 Q; L" { - * 时间 : 2019-09-08
: C, y# c) l% _6 W% n F - * 最后修改时间 : 2019-09-082 T2 T% L9 S! A* R8 t, E0 [
- * 说明 : 用于初始化STM32F7 SDRAM 接口+ D+ Q& p! g, P1 U: _" c; j' v
- *************************************************************************************************************************/ . m' G& E1 l- t& j
- void SDRAM_Init(void)' z6 t" {/ m6 l3 t
- {( Y) |4 t+ H& e' L1 S6 u
- u32 temp;( N5 X/ W1 J3 z+ }& i( b
- , C: i7 ^$ h- K9 {0 \! L" z
- SYS_DeviceClockEnable(DEV_FSMC, TRUE); //FSMC时钟使能, r0 j- | v( X& o1 u# R" x+ h; a5 W
- SYS_DeviceClockEnable(DEV_GPIOC, TRUE); //使能GPIOC时钟1 d) R! o$ @6 H: ?
- SYS_DeviceClockEnable(DEV_GPIOD, TRUE); //使能GPIOD时钟+ I3 N: z" M1 Z3 ^1 ^
- SYS_DeviceClockEnable(DEV_GPIOE, TRUE); //使能GPIOE时钟' e5 k6 |' y) Q, N, O8 C
- SYS_DeviceClockEnable(DEV_GPIOF, TRUE); //使能GPIOF时钟) r5 F( Q5 {5 T
- SYS_DeviceClockEnable(DEV_GPIOG, TRUE); //使能GPIOG时钟9 f2 y% K6 h; r$ G/ d1 }2 h8 ^
- SYS_DeviceClockEnable(DEV_GPIOH, TRUE); //使能GPIOH时钟
# T$ d9 V4 d. r6 G - 4 |6 }8 H% `" M0 {4 Q, C# |
- //初始化IO8 U' c Y4 U6 @1 i* }
- SYS_GPIOx_Init(GPIOC, BIT3, AF_PP_OPU, SPEED_100M); //PC3
; @7 _) m" J" Y7 G/ i% x - SYS_GPIOx_Init(GPIOD, BIT0|BIT1|BIT8|BIT9|BIT10|BIT14|BIT15, AF_PP_OPU, SPEED_100M); //PD0/1/8/9/10/14/15 # H8 p6 I3 Z% ], F
- SYS_GPIOx_Init(GPIOE, BIT0|BIT1|(0X1FF<<7), AF_PP_OPU, SPEED_100M); //PE0/1/7~15 ( Z+ J' L B( b1 r" E& T
- SYS_GPIOx_Init(GPIOF, BIT0|BIT1|BIT2|BIT3|BIT4|BIT5|BIT11|BIT12|BIT13|BIT14|BIT15, AF_PP_OPU, SPEED_100M); //PF0~5/11~15
1 K1 S- u) Y, S- C/ a8 i - SYS_GPIOx_Init(GPIOG, BIT0|BIT1|BIT4|BIT5|BIT8|BIT15, AF_PP_OPU, SPEED_100M); //PG0/1/4/5/8/15
M3 o: L! u3 M: n/ W, g1 {6 Y$ \& \ - SYS_GPIOx_Init(GPIOH, BIT3|BIT5, AF_PP_OPU, SPEED_100M);
9 M1 C6 w( e. I5 K5 { y4 N* q - 9 ` l- W9 U6 A: p1 B2 u# s
- SYS_GPIOx_SetAF(GPIOC, 3, AF12_FSMC); //PC3,AF12$ N, `( j: ^; e" D2 Q$ S7 k3 D
-
5 ]7 c3 A, t+ G8 ~ - SYS_GPIOx_SetAF(GPIOD, 0, AF12_FSMC); //PD0,AF12 - |* A1 B) }2 r) n0 r/ O
- SYS_GPIOx_SetAF(GPIOD, 1, AF12_FSMC); //PD1,AF12 5 D$ k3 f2 D+ P3 D/ {
- SYS_GPIOx_SetAF(GPIOD, 8, AF12_FSMC); //PD8,AF127 o, Y" }' v3 k' g _& t/ c
- SYS_GPIOx_SetAF(GPIOD, 9, AF12_FSMC); //PD9,AF12
0 c8 p+ I5 T2 Z1 |1 b - SYS_GPIOx_SetAF(GPIOD, 10, AF12_FSMC); //PD10,AF12
! r5 W1 Z3 [% W; }& x3 k$ M7 U: O - SYS_GPIOx_SetAF(GPIOD, 14, AF12_FSMC); //PD14,AF12" r; _3 E* [ U
- SYS_GPIOx_SetAF(GPIOD, 15, AF12_FSMC); //PD15,AF12
2 n1 Q# Q' L$ \% ~; |4 C5 o$ o! h9 z - - t7 r7 h( L+ P/ `7 M% D
- SYS_GPIOx_SetAF(GPIOE, 0, AF12_FSMC); //PE0,AF12
4 a, I9 b& {6 [, C% S - SYS_GPIOx_SetAF(GPIOE, 1, AF12_FSMC); //PE1,AF12 6 R- ~3 ~2 m# g
- SYS_GPIOx_SetAF(GPIOE, 7, AF12_FSMC); //PE7,AF12
1 K# D' J* |. Y - SYS_GPIOx_SetAF(GPIOE, 8, AF12_FSMC); //PE8,AF12
2 R. a. F, v6 u6 q& M$ f - SYS_GPIOx_SetAF(GPIOE, 9, AF12_FSMC); //PE9,AF12
, {7 ?4 X4 h3 n' f2 b& r1 u7 ^ - SYS_GPIOx_SetAF(GPIOE, 10, AF12_FSMC); //PE10,AF12
. v; A1 h0 s# S' J( i$ X - SYS_GPIOx_SetAF(GPIOE, 11, AF12_FSMC); //PE11,AF128 f# @: F; L3 u7 c6 T% i \; q. j
- SYS_GPIOx_SetAF(GPIOE, 12, AF12_FSMC); //PE12,AF12( f$ F' x5 K( _' _
- SYS_GPIOx_SetAF(GPIOE, 13, AF12_FSMC); //PE13,AF129 L1 b ^) W5 X
- SYS_GPIOx_SetAF(GPIOE, 14, AF12_FSMC); //PE14,AF12
$ ?% E6 E& X. m - SYS_GPIOx_SetAF(GPIOE, 15, AF12_FSMC); //PE15,AF12
* O( Q/ o; w/ {* [" p0 r
( M" k8 W# I! A% M* D/ N9 H& K/ {- SYS_GPIOx_SetAF(GPIOF, 0, AF12_FSMC); //PF0,AF12
* w* j; ]7 U- v - SYS_GPIOx_SetAF(GPIOF, 1, AF12_FSMC); //PF1,AF12
+ N* n% X2 z; J R4 ?! D4 M - SYS_GPIOx_SetAF(GPIOF, 2, AF12_FSMC); //PF2,AF120 J' A9 M% W% f. x4 a' Q- P
- SYS_GPIOx_SetAF(GPIOF, 3, AF12_FSMC); //PF3,AF12
/ a( r. L- z) F; F - SYS_GPIOx_SetAF(GPIOF, 4, AF12_FSMC); //PF4,AF124 Q7 K0 f# C& h$ l) A) l
- SYS_GPIOx_SetAF(GPIOF, 5, AF12_FSMC); //PF5,AF12' s; ~2 j" \" K6 J3 S
- SYS_GPIOx_SetAF(GPIOF, 11, AF12_FSMC); //PF11,AF12: _7 L0 D, S9 A) M
- SYS_GPIOx_SetAF(GPIOF, 12, AF12_FSMC); //PF12,AF12
# L6 ], I f! ]1 I - SYS_GPIOx_SetAF(GPIOF, 13, AF12_FSMC); //PF13,AF12
+ ?. k0 \+ e" \$ b7 i) x - SYS_GPIOx_SetAF(GPIOF, 14, AF12_FSMC); //PF14,AF12
. j0 g, Z+ X" J7 [ g/ Q M$ _ - SYS_GPIOx_SetAF(GPIOF, 15, AF12_FSMC); //PF15,AF12
: W8 l2 t' b- P9 f* H3 j -
/ ] z+ `" U& C! z5 O - SYS_GPIOx_SetAF(GPIOG, 0, AF12_FSMC); //PG0,AF12
* h: K, n# ~- j1 o - SYS_GPIOx_SetAF(GPIOG, 1, AF12_FSMC); //PG1,AF12
1 J4 P$ e- u. ` }, o' E - SYS_GPIOx_SetAF(GPIOG, 4, AF12_FSMC); //PG4,AF12& ^2 Q+ [0 b+ S) u, @
- SYS_GPIOx_SetAF(GPIOG, 5, AF12_FSMC); //PG5,AF12 2 h" Y' f& ]+ a
- SYS_GPIOx_SetAF(GPIOG, 8, AF12_FSMC); //PG8,AF12
& t) E& [; e4 j$ A! K+ D6 N - SYS_GPIOx_SetAF(GPIOG, 15, AF12_FSMC); //PG15,AF12
0 h, J( c a+ o: V - 2 ?# m+ }+ ^4 B; G" V: r
- SYS_GPIOx_SetAF(GPIOH, 3, AF12_FSMC); //PH3,AF12
% ]) z$ h" m5 f* N: M5 e - SYS_GPIOx_SetAF(GPIOH, 5, AF12_FSMC); //PH5,AF12 t+ w2 p$ a. \% O
- ! k! U; U; B2 Y8 Y$ d! M
- + b1 }5 G- ^% Z: L6 @3 P9 K
- temp = 0;+ f0 j' ~% V( a% Y' ^9 V9 ~
- temp |= 0<<0; //8位列地址
& J4 [' I# P) j2 L/ P- X - temp |= 1<<2; //12位行地址
q3 Z5 F# I4 }3 k. M# t" p - temp |= 1<<4; //16位数据位宽- W. U5 b8 d7 B/ U
- temp |= 1<<6; //4个内部存区(4 BANKS)
C9 U$ d: H4 p) [ - temp |= 2<<7; //2个CAS延迟6 a e0 m8 V2 C. q' r1 v
- temp |= 0<<9; //允许写访问
4 x& u+ B# c. u/ M4 M - temp |= 2<<10; //SDRAM时钟=HCLK/2
8 w2 Q2 R) S1 }/ v: Q6 p - temp |= 1<<12; //使能突发访问 ' J5 v' ^ J9 ^
- temp |= 0<<13; //读通道延迟0个HCLK
; ^; Z2 T3 ]0 H9 @/ n - FMC_Bank5_6->SDCR[0] = temp; //设置FMC BANK5 SDRAM控制寄存器(BANK5和6用于管理SDRAM).
+ r; j/ r# e$ C0 u7 \" s* ~
5 J0 e0 l. Z0 F- temp = 0;
5 [6 U H5 P1 J% ?* @/ ^ - temp|=1<<0; //加载模式寄存器到激活时间的延迟为2个时钟周期
4 k3 Y! v d+ |- H( C8 a' | - temp|=5<<4; //退出自刷新延迟为6个时钟周期) P% W( ^1 @% s( n
- temp|=3<<8; //自刷新时间为4个时钟周期- r2 e) I% ]/ F0 G
- temp|=5<<12; //行循环延迟为6个时钟周期4 `2 @; \. o1 s2 w* q+ c* D6 ]
- temp|=1<<16; //恢复延迟为2个时钟周期6 h( }8 k/ ~* n9 s' S
- temp|=1<<20; //行预充电延迟为2个时钟周期
0 ?+ p$ f+ T2 |% a- w' D# j- ? - temp|=1<<24; //行到列延迟为2个时钟周期2 o+ w; N& `! C% D) q7 q
- FMC_Bank5_6->SDTR[0] = temp; //设置FMC BANK5 SDRAM时序寄存器 1 v' J5 ?. U& H, `6 y2 m
5 ~1 I: e0 u7 P5 F- SDRAM_SendCmd(SDRAM_CMD_BANK1, 0, 1, SDRAM_CMD_CLOCK_CONFIG); //时钟配置使能 . L2 E. X* P' c% ?
- Delay_US(300); //至少延迟200us.
+ C) v( K' g s& G - SDRAM_SendCmd(SDRAM_CMD_BANK1,0, 1, SDRAM_CMD_PALL); //对所有存储区预充电5 Q& g- e4 t1 u/ l
- SDRAM_SendCmd(SDRAM_CMD_BANK1,0, 8, SDRAM_CMD_AR); //设置自刷新次数 ! n% G$ }+ ]! ] p6 @- g
- 1 a% {! C' J- ?) g5 [! @* @6 B
- temp = 0;
$ p L7 y& f" L& ^' B7 q* O: h - temp |= 2<<0; //设置突发长度:4(可以是1/2/4/8) -测试过1/2/4发现都正常,唯独8的时候,屏幕会出现随机噪点# i9 R6 f0 p+ o' m6 Q4 N$ t
- temp |= 0<<3; //设置突发类型:连续(可以是连续/交错)
# k d2 b( @& V - temp |= 2<<4; //设置CAS值:25 `$ J% R w7 A7 G6 H: w
- temp |= 0<<7; //设置操作模式:0,标准模式
( q: l! {% a6 W - temp |= 1<<9; //设置突发写模式:1,单点访问6 T% f" j0 x7 ?7 Z
- SDRAM_SendCmd(SDRAM_CMD_BANK1,temp, 1, SDRAM_CMD_LOAD_MODE); //设置SDRAM模式. g$ w5 D. E" P; v) ?. q$ |
- 1 \" r# }# p" C& y! \0 a
- //COUNT=SDRAM刷新周期/行数-20# G4 J0 H1 m$ T7 N N
- //SDRAM刷新周期为64ms,SDCLK=AHB/2=100Mhz,行数为4096.2 F3 c5 N. S; J4 b/ b
- //计算方法为64*1000*AHB/2/4096-20
1 q% a) ^# l+ [3 ~ D - temp = 64*1000*(SYS_GetAHBClockSpeed()/1000000/2)/4096-20;- ? \% v' @+ ^9 ]* x9 V
- FMC_Bank5_6->SDRTR = temp<<1; //设置刷新频率计数器 . X" q% }" R8 _& b7 K
- } n7 x" a3 c; `9 V% F, a1 V
- 2 c! m1 r2 G1 p& W, U9 W' K. j" M
- # n5 @9 u) P" f7 z
- /*************************************************************************************************************************3 z& v B( q; ]; ]) v
- * 函数 : bool SDRAM_SendCmd(SDRAM_CMD_BANK_SELECT BankSelect, u16 mdr, u8 AutoRefresh, SDRAM_CMD_TYPE mode)1 L: P, B1 n0 f2 t7 U
- * 功能 : SDRAM 命令模式设置8 Y$ ?! a+ y' p' T+ D5 p# v8 U% i% a
- * 参数 : BankSelect:bank选择;mdr:模式;AutoRefresh:自刷新设置;mode:模式命令
% N) |4 c$ V, v/ B - * 返回 : TRUE:成功;FALSE:失败1 n: R) A' i; z2 m8 `& ^5 K* Q* x
- * 依赖 : 底层宏定义: G! k2 I" k4 `* Y5 P
- * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>. S) O& I. L& r: U1 `
- * 时间 : 2019-09-08
8 G+ t, ^5 M8 \4 r" I3 F - * 最后修改时间 : 2019-09-08
7 Y( V1 Y' e& B/ U - * 说明 : $ a m+ d" m) B. W i3 ~; K) Y
- *************************************************************************************************************************/ & V: T; D& N+ B9 W
- bool SDRAM_SendCmd(SDRAM_CMD_BANK_SELECT BankSelect, u16 mdr, u8 AutoRefresh, SDRAM_CMD_TYPE mode)4 V( N; A5 [2 L! o2 F+ ]/ j
- {
' H! n: R2 [4 J' }+ u2 l+ p. x - u32 retry=0;( x: F9 ~8 s0 r4 _) |3 l3 ]6 Q
- u32 temp = 0;
: \5 n6 f% L+ F* X1 g ? -
& A6 P! d; I/ N! m0 @ - temp |= mode<<0; //设置指令# t: G: U$ `' }3 E! h# n1 S( e4 s; x
- temp |= BankSelect<<3; //设置发送指令到bank5还是6
; t$ Y) T8 X2 N5 q/ X6 K - temp |= (AutoRefresh&0xf)<<5; //设置自刷新次数
+ L( o! C8 r+ p) _6 U - temp |= mdr<<9; //设置模式寄存器的值
0 E% |& j S- Q+ {8 A2 V - FMC_Bank5_6->SDCMR = temp; //配置寄存器) T# Z# @9 x" c1 }
- - g" ~! {: |+ F0 V
- //temp = FMC_Bank5_6->SDCMR;
3 L$ J, _5 {+ c+ c* A4 W - //uart_printf("FMC_Bank5_6->SDCMR=%X\r\n", temp);! O9 z7 k$ u2 p0 [0 N6 a N
- while((FMC_Bank5_6->SDSR&(1<<5))) //等待指令发送完成 & r( i; K9 @2 ^" B; Y) J& G! {
- {
( f2 G: r9 f) j+ d - retry++;
7 B" m, {# u( `! j - Delay_US(1); ]4 G" G7 R6 c/ ]' s
- if(retry > 50000)return FALSE; $ p! S2 w1 `& z( y9 V
- }3 k5 \) P( c) J* a0 V: H7 d4 v7 j
-
4 L4 [# u9 D- Z3 W -
" @2 |7 {- x G" i$ z- c - return TRUE;
0 F- m4 g/ O; q* K2 y/ U) A( h - }
复制代码
6 y. C5 [- ]* [6 R6 Q% ?4 x' @
5 c3 U: U& k+ X' J( b- /*************************************************************************************************************
% A* X0 D8 x# O3 r - * 文件名 : stm32f7_sdram.h
6 L* |2 b$ x$ _/ M6 v - * 功能 : STM32F7 外部SDRAM驱动5 J; @$ c$ V; R7 g s
- * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>2 l# b1 R$ o: r y% A
- * 创建时间 : 2019-09-08" I( r2 M R8 v! w
- * 最后修改时间 : 2019-09-08# Y/ S6 q9 V1 K Q$ e& ~7 g
- * 详细: & }& F! g& v2 E' O0 P% C2 @. W
- *************************************************************************************************************/ 2 S. P. p) u/ Y' \/ @, `1 w2 [3 u+ G
- #ifndef __STM32F7_SDRAM_H_7 ^9 _- F+ V, M% O, _% z3 Q
- #define __STM32F7_SDRAM_H_
0 E4 s, C. N' B; A& k - #include "system.h"
x1 ~" W9 u+ {1 @: C' d, G3 V* X! T$ i8 x - % A: S8 t, k- W! i- e: e
- & o* N$ l3 I! j, r4 ?
- //========================================================================2 \! S7 v; k0 ?
- // SRAM硬件相关配置/ D, n# C7 E3 `7 b1 h7 e' t
- //------------------------------------------------------------------------6 [* ~ v* q% g5 [: _9 T8 O: Q
- #define Bank5_SDRAM_ADDR ((u32)0XC0000000)- `) w+ z1 y4 f, Y4 Z. V: B
- 8 J, }& N) X+ |+ J
- void SDRAM_Init(void); //SDRAM初始化
/ d5 I" w4 m# e. _9 ~4 @
2 [$ h3 x- d" `
) R+ R: q7 b8 U# n- #endif //__STM32F7_SDRAM_H_# _- j3 d+ C+ D
复制代码
* e3 w2 r* G& a. l2 x8 \' x0 w' j+ [0 ~) K$ t
|