STM32f746gdiscovery 开发板使用的是16MB的SDRAM,由于少了一根地址线,只有8MB可用。" ?0 Z2 R* {: k3 S8 ?. t
3 D! f; C: b0 b8 k3 i9 g3 h7 l' A
; ^' C7 o# }' b4 w( S2 D$ c$ t+ p2 H3 q1 b" x* t( ^0 X4 G
( w0 r" e! T" `- [% K4 m z% v! v4 [
- /*************************************************************************************************************
- v' k- z' V1 Q/ o# y3 H% s0 p8 u - * 文件名 : stm32f7_sdram.c" F4 k2 k3 f8 k0 v
- * 功能 : STM32F7 外部SDRAM驱动
$ n2 p. h% w$ o5 L4 y3 h. ?8 ?, [ - * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
$ H* h& W* W$ e9 [4 k: W - * 创建时间 : 2019-09-08
, P* M5 C @) ^, H - * 最后修改时间 : 2019-09-08
' K+ _' C8 N; m/ \, D - * 详细 : 2019-10-31 设置突发长度:4(可以是1/2/4/8)-测试过1/2/4发现都正常,唯独8的时候,屏幕会出现随机噪点
2 O8 z p( o. n8 S& @ |% ^' d - *************************************************************************************************************/
' `% T1 w! U1 y - #include "stm32f7_sdram.h" c# e: r& N! I, V% m8 q
- #include "SYSTEM.H" - m, Z9 a) K2 P
* N0 S g. `2 |, G7 X7 B
8 w* [ l" K" x- ( _2 }) `" f- L1 a
- //BANK选择
6 r4 ?: {8 I6 ]+ x" H - typedef enum/ |& ~" U- [; m5 T+ Z0 W! q: p
- {) f3 i( W1 z6 i* [% J
- SDRAM_CMD_BANK1 = 2, //命令模板存储区域1* E. D% w+ |6 q( p" u
- SDRAM_CMD_BANK2 = 1, //命令模板存储区域2
1 Y% J6 t0 K; S q - SDRAM_CMD_BANK1_2 = 3, //命令模板存储区域1与2* t) ?. S% k5 U- ]5 L- [+ I$ N
- }SDRAM_CMD_BANK_SELECT;
% y8 u4 P0 ^ j0 C8 m; I4 U# @
# O2 C/ G/ F/ g% i2 R. @* N
3 Z$ m* K( ]/ ~/ \7 h" g- //命令
9 _3 U& p! ?) [# z; x/ Y) I - typedef enum 5 c; j# Q: A; ?# H
- {( P$ t4 y: T& [) v7 R3 ^0 E: J
- SDRAM_CMD_NORMAL = 0, //正常模式
, D3 a9 W) Q# M6 \, C - SDRAM_CMD_CLOCK_CONFIG = 1, //时钟配置使能+ _# O( G; e: }; j$ D3 ?
- SDRAM_CMD_PALL = 2, //预充电所有存储区域 w0 z* K) O8 Z6 D* z# i, d
- SDRAM_CMD_AR = 3, //自刷新命令
4 e9 i. }- \4 E+ Y. }2 }: ^ - SDRAM_CMD_LOAD_MODE = 4, //加载模式寄存器+ G2 s- H& x1 M, v3 Y
- //SDRAM_CMD_AR = 5, //自刷新命令- o# i) Q6 ^- C+ f
- SDRAM_CMD_POWER_DOWN = 6, //掉电命令: F/ f L5 W( I+ _3 N
- }SDRAM_CMD_TYPE;
4 M2 }4 k$ e4 v! n8 Z+ T6 J
8 p m9 A( J d1 k" a
1 i( C+ x* C' ^* m$ F9 g# \. ^2 P- bool SDRAM_SendCmd(SDRAM_CMD_BANK_SELECT BankSelect, u16 mode, u8 AutoRefresh, SDRAM_CMD_TYPE cmd);//SDRAM 命令模式设置
) D+ K3 F; i3 s2 y; z3 |7 t
, P" S# ^% R9 z* \9 C1 {- m. V
% L ~. c" D1 q1 R3 C- /*************************************************************************************************************************
. B; Q+ |2 ?; u8 g- l9 w% w - * 函数 : void SDRAM_Init(void)& R, p$ k' ?# d6 |1 V
- * 功能 : SDRAM 接口初始化
& l) d1 B4 [. _* \* o - * 参数 : 无
6 F+ a0 m# c, u; @# a. r - * 返回 : 无
# h# O4 Z( w) G5 G7 Y - * 依赖 : 底层宏定义
2 v5 s$ \* ?7 G1 G' v6 ?6 A - * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
: @1 j" Q5 `+ Q$ p7 O. k( d - * 时间 : 2019-09-089 T* D f* q* Y/ \: j @! t
- * 最后修改时间 : 2019-09-08
% M: Z$ _; E% P) @7 G/ r' B - * 说明 : 用于初始化STM32F7 SDRAM 接口" B x6 S' P! }( V d( u C
- *************************************************************************************************************************/
& \ n) T) x) I( E% D7 L, _ - void SDRAM_Init(void)' Y, a) }$ ~7 _1 x! Z
- {
4 A! e7 J; ]- N7 u3 q2 P, L - u32 temp;, N1 j6 |( ^! @
-
$ M2 c7 [! C1 t: U/ s - SYS_DeviceClockEnable(DEV_FSMC, TRUE); //FSMC时钟使能7 h4 \7 k- a# f
- SYS_DeviceClockEnable(DEV_GPIOC, TRUE); //使能GPIOC时钟1 p3 [ ]* T0 ^
- SYS_DeviceClockEnable(DEV_GPIOD, TRUE); //使能GPIOD时钟; V3 l! Y. C- {$ i
- SYS_DeviceClockEnable(DEV_GPIOE, TRUE); //使能GPIOE时钟3 R) C1 o* o! p% L d* W
- SYS_DeviceClockEnable(DEV_GPIOF, TRUE); //使能GPIOF时钟+ R$ ^, T' R0 k, d. k% X( n
- SYS_DeviceClockEnable(DEV_GPIOG, TRUE); //使能GPIOG时钟
6 x) U5 v7 X, I( i4 M9 V) P - SYS_DeviceClockEnable(DEV_GPIOH, TRUE); //使能GPIOH时钟 g4 o4 Z6 ~- S( S; [
-
$ {% Y( j4 a, S5 B, E - //初始化IO5 E! |2 B. s0 g9 h, Y2 ~# l) J
- SYS_GPIOx_Init(GPIOC, BIT3, AF_PP_OPU, SPEED_100M); //PC3
) `& ?" p$ v' g% l - SYS_GPIOx_Init(GPIOD, BIT0|BIT1|BIT8|BIT9|BIT10|BIT14|BIT15, AF_PP_OPU, SPEED_100M); //PD0/1/8/9/10/14/15
3 q/ d9 [1 u! s' x* ]* ?! F- K - SYS_GPIOx_Init(GPIOE, BIT0|BIT1|(0X1FF<<7), AF_PP_OPU, SPEED_100M); //PE0/1/7~15
8 b; q/ W# P" @! w& ^$ Z- N - SYS_GPIOx_Init(GPIOF, BIT0|BIT1|BIT2|BIT3|BIT4|BIT5|BIT11|BIT12|BIT13|BIT14|BIT15, AF_PP_OPU, SPEED_100M); //PF0~5/11~15 ! W. s" Z1 i; ^% ^
- SYS_GPIOx_Init(GPIOG, BIT0|BIT1|BIT4|BIT5|BIT8|BIT15, AF_PP_OPU, SPEED_100M); //PG0/1/4/5/8/15
# {8 v( i d8 v, n- M# T* L& @1 q - SYS_GPIOx_Init(GPIOH, BIT3|BIT5, AF_PP_OPU, SPEED_100M);
: V9 p0 O. Z9 M& E# W -
9 Y$ v/ Y8 o" N& F - SYS_GPIOx_SetAF(GPIOC, 3, AF12_FSMC); //PC3,AF12% T& S- f! o" J' \" P
-
+ [1 ]5 R8 y. P; F4 u6 [6 |6 F4 i - SYS_GPIOx_SetAF(GPIOD, 0, AF12_FSMC); //PD0,AF12
: P: \; N* \5 v2 p3 u. _ - SYS_GPIOx_SetAF(GPIOD, 1, AF12_FSMC); //PD1,AF12 1 d- V2 E6 X7 o5 H% |- ]0 H# i
- SYS_GPIOx_SetAF(GPIOD, 8, AF12_FSMC); //PD8,AF12
* _) k- T) |2 F y1 H - SYS_GPIOx_SetAF(GPIOD, 9, AF12_FSMC); //PD9,AF12
8 q7 P A3 b, @3 C$ o8 N$ V - SYS_GPIOx_SetAF(GPIOD, 10, AF12_FSMC); //PD10,AF12 2 a" }; P# g5 t- e: h2 p
- SYS_GPIOx_SetAF(GPIOD, 14, AF12_FSMC); //PD14,AF12. T; H6 ^+ c1 e6 l
- SYS_GPIOx_SetAF(GPIOD, 15, AF12_FSMC); //PD15,AF12# L! }: v, G: Y- f! T
-
; s- ]: X+ R6 ~3 }, L' ^( Y - SYS_GPIOx_SetAF(GPIOE, 0, AF12_FSMC); //PE0,AF12 & o( U& r- t" Y' o% [( T
- SYS_GPIOx_SetAF(GPIOE, 1, AF12_FSMC); //PE1,AF12 7 p7 v; @- T9 V' a& R5 q
- SYS_GPIOx_SetAF(GPIOE, 7, AF12_FSMC); //PE7,AF12
) F4 j w, k' |! d6 ?! N - SYS_GPIOx_SetAF(GPIOE, 8, AF12_FSMC); //PE8,AF12
1 \; [0 e3 C, F- P1 J) e - SYS_GPIOx_SetAF(GPIOE, 9, AF12_FSMC); //PE9,AF12$ k& z- X3 U! |9 B3 h
- SYS_GPIOx_SetAF(GPIOE, 10, AF12_FSMC); //PE10,AF12
8 s2 Y: R' u9 g; }( s8 y0 P - SYS_GPIOx_SetAF(GPIOE, 11, AF12_FSMC); //PE11,AF12) Q3 H( h* b- H* x6 J1 N1 D( G* c
- SYS_GPIOx_SetAF(GPIOE, 12, AF12_FSMC); //PE12,AF123 k! }" X. p( _! L! r9 c
- SYS_GPIOx_SetAF(GPIOE, 13, AF12_FSMC); //PE13,AF12% s. A; B" c( o2 E- }& S6 K
- SYS_GPIOx_SetAF(GPIOE, 14, AF12_FSMC); //PE14,AF12# f1 r7 g5 o4 B9 S3 E& H1 u
- SYS_GPIOx_SetAF(GPIOE, 15, AF12_FSMC); //PE15,AF123 f7 J; l/ ]3 y# x
- / A9 r; R+ k1 E+ V
- SYS_GPIOx_SetAF(GPIOF, 0, AF12_FSMC); //PF0,AF12
) s* G( W1 Z) q# J( Q0 O - SYS_GPIOx_SetAF(GPIOF, 1, AF12_FSMC); //PF1,AF12 8 v9 V4 ^/ a2 q
- SYS_GPIOx_SetAF(GPIOF, 2, AF12_FSMC); //PF2,AF12$ x9 Q! J I5 \; ^
- SYS_GPIOx_SetAF(GPIOF, 3, AF12_FSMC); //PF3,AF12
2 @' G) g! Y/ F - SYS_GPIOx_SetAF(GPIOF, 4, AF12_FSMC); //PF4,AF122 s& o! c; i4 I- U" A* h
- SYS_GPIOx_SetAF(GPIOF, 5, AF12_FSMC); //PF5,AF12* B4 w- K7 g/ p/ r0 Z2 e6 u
- SYS_GPIOx_SetAF(GPIOF, 11, AF12_FSMC); //PF11,AF12
0 Z! u# [2 Q! p! Y8 g: L6 s$ y - SYS_GPIOx_SetAF(GPIOF, 12, AF12_FSMC); //PF12,AF12
+ z9 G) Z& x: Z; A. r - SYS_GPIOx_SetAF(GPIOF, 13, AF12_FSMC); //PF13,AF12
( [5 ]8 Q: F# i2 S - SYS_GPIOx_SetAF(GPIOF, 14, AF12_FSMC); //PF14,AF12
3 g# i/ u4 u$ [6 a4 p1 X - SYS_GPIOx_SetAF(GPIOF, 15, AF12_FSMC); //PF15,AF12
6 W3 C4 l! @, D) ^( [* L -
4 q, t( Z8 I* _' ` - SYS_GPIOx_SetAF(GPIOG, 0, AF12_FSMC); //PG0,AF12
A$ z* e6 k; s& @- l+ e, P - SYS_GPIOx_SetAF(GPIOG, 1, AF12_FSMC); //PG1,AF12 " }& ^' D: @7 }6 ^- A
- SYS_GPIOx_SetAF(GPIOG, 4, AF12_FSMC); //PG4,AF12
- p; O* s' e$ V9 b - SYS_GPIOx_SetAF(GPIOG, 5, AF12_FSMC); //PG5,AF12 : M% S) y+ y, S, m) D! h+ M/ P
- SYS_GPIOx_SetAF(GPIOG, 8, AF12_FSMC); //PG8,AF12
, S) F- i& J! y; l) W5 l8 v - SYS_GPIOx_SetAF(GPIOG, 15, AF12_FSMC); //PG15,AF122 }. S( [) Y5 z" M' b
-
* U& H6 e5 ?" X! g7 T. v - SYS_GPIOx_SetAF(GPIOH, 3, AF12_FSMC); //PH3,AF12
, I0 T, ?, }" j: P7 H- P1 Y - SYS_GPIOx_SetAF(GPIOH, 5, AF12_FSMC); //PH5,AF12 4 V! T: ^' o. i, ^2 H! E6 n# w6 c( B' t
-
1 P9 P- L w' W - 9 _* H$ P( [; e$ P; H
- temp = 0;
% R+ j0 w9 ]( y) o2 M/ m - temp |= 0<<0; //8位列地址
4 J7 Z* l) \2 G7 K! T2 H6 W) Q0 L) j - temp |= 1<<2; //12位行地址
; R# X2 F1 K: y& Y - temp |= 1<<4; //16位数据位宽
/ Q& j4 Z: F0 e0 a; G - temp |= 1<<6; //4个内部存区(4 BANKS)6 L6 L: Y$ q5 L8 a+ h; G. ?' ]; a
- temp |= 2<<7; //2个CAS延迟$ y, r1 L- L9 V! F7 n2 I( i
- temp |= 0<<9; //允许写访问9 P- u' H. j& E' X- z6 b2 S
- temp |= 2<<10; //SDRAM时钟=HCLK/2* q! Y( H/ h% J
- temp |= 1<<12; //使能突发访问 $ w/ o# a. F) }$ q9 A# ^
- temp |= 0<<13; //读通道延迟0个HCLK& u. w8 j0 D6 |! v# C, x
- FMC_Bank5_6->SDCR[0] = temp; //设置FMC BANK5 SDRAM控制寄存器(BANK5和6用于管理SDRAM).6 [/ u& u" _ A# _# N
- 1 d# N" Q) @' D% x
- temp = 0;
0 Q' _$ w( R L6 f- L: p - temp|=1<<0; //加载模式寄存器到激活时间的延迟为2个时钟周期1 d/ m* o- H" w$ o7 j8 k0 S
- temp|=5<<4; //退出自刷新延迟为6个时钟周期5 v& m& D$ ]4 r+ w+ V: N
- temp|=3<<8; //自刷新时间为4个时钟周期/ Z+ S8 m5 r( u' D# _; i7 a5 [
- temp|=5<<12; //行循环延迟为6个时钟周期" g* \- Z4 u4 D% P6 @- H& [! I- R
- temp|=1<<16; //恢复延迟为2个时钟周期4 s. |6 {! A* ~8 X6 c0 L
- temp|=1<<20; //行预充电延迟为2个时钟周期- `2 `0 [' k; J$ B, _
- temp|=1<<24; //行到列延迟为2个时钟周期
7 J' C( n2 c9 k3 I# r - FMC_Bank5_6->SDTR[0] = temp; //设置FMC BANK5 SDRAM时序寄存器
- N. ]" M: G6 z% j% a8 b* X
- Z0 J* O6 W5 Z( T2 G- SDRAM_SendCmd(SDRAM_CMD_BANK1, 0, 1, SDRAM_CMD_CLOCK_CONFIG); //时钟配置使能
1 h [' Y F0 U - Delay_US(300); //至少延迟200us.1 z/ P1 t0 _# O. ^ p+ A3 Z
- SDRAM_SendCmd(SDRAM_CMD_BANK1,0, 1, SDRAM_CMD_PALL); //对所有存储区预充电
. k7 z! e4 T( M1 C, ^. \/ H, _ - SDRAM_SendCmd(SDRAM_CMD_BANK1,0, 8, SDRAM_CMD_AR); //设置自刷新次数
+ h( f7 ^1 u/ _ Q# ]5 z$ Q -
# w3 j" d. F5 L1 |. Y2 F - temp = 0; u% r* u1 C& I1 u% f6 C5 Y& q
- temp |= 2<<0; //设置突发长度:4(可以是1/2/4/8) -测试过1/2/4发现都正常,唯独8的时候,屏幕会出现随机噪点1 _% @- P! G, v& \* W% G
- temp |= 0<<3; //设置突发类型:连续(可以是连续/交错)
+ D" v9 n1 w+ |% Y8 w b* D7 x - temp |= 2<<4; //设置CAS值:2
6 [9 w: \* x! @+ p4 y. a - temp |= 0<<7; //设置操作模式:0,标准模式2 T# E; z( t7 z% ?* p% B# B
- temp |= 1<<9; //设置突发写模式:1,单点访问
4 m- d% @; y2 d' c) s! ~" K - SDRAM_SendCmd(SDRAM_CMD_BANK1,temp, 1, SDRAM_CMD_LOAD_MODE); //设置SDRAM模式
c0 q" Q9 `- e/ @ -
% [; ]8 d' Y; ^$ V+ r - //COUNT=SDRAM刷新周期/行数-20
- [ i U3 r' |, C0 a; O - //SDRAM刷新周期为64ms,SDCLK=AHB/2=100Mhz,行数为4096.
2 ^8 u, ?- J2 V1 K - //计算方法为64*1000*AHB/2/4096-20
$ G6 a3 T6 i4 o0 S- @# I! P9 i - temp = 64*1000*(SYS_GetAHBClockSpeed()/1000000/2)/4096-20;
7 y7 l5 D0 c2 R% W - FMC_Bank5_6->SDRTR = temp<<1; //设置刷新频率计数器 % d2 W/ T3 n( k# U5 N" r, S+ H7 U
- }7 e# n6 X8 w0 E
: v- s1 g3 i! Z. P- " N5 E v9 F' f- b. x6 Y
- /*************************************************************************************************************************
8 u, `8 x( G2 x* p - * 函数 : bool SDRAM_SendCmd(SDRAM_CMD_BANK_SELECT BankSelect, u16 mdr, u8 AutoRefresh, SDRAM_CMD_TYPE mode): d( ~+ H+ W1 G
- * 功能 : SDRAM 命令模式设置 C% Y# U0 v, l, d3 C( ^' S/ F& G
- * 参数 : BankSelect:bank选择;mdr:模式;AutoRefresh:自刷新设置;mode:模式命令# {7 b3 E G. |' [9 O$ ~) w$ W6 R4 X* q q
- * 返回 : TRUE:成功;FALSE:失败* }8 l* o! W6 C% J0 c k4 N
- * 依赖 : 底层宏定义* A& F! a- q" h7 Z0 w
- * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>7 S6 l/ M) n1 {# v9 U& i& v
- * 时间 : 2019-09-08" l0 \3 B7 L1 a& U. l; a8 \
- * 最后修改时间 : 2019-09-08
m( I1 K& s. h/ U' e/ e* V - * 说明 :
/ Q v2 R4 D) t% u% ? - *************************************************************************************************************************/
. z4 i# [! I/ d2 f - bool SDRAM_SendCmd(SDRAM_CMD_BANK_SELECT BankSelect, u16 mdr, u8 AutoRefresh, SDRAM_CMD_TYPE mode)5 b! W5 G! i3 ^4 R4 g* h5 E
- {
A- O. I$ D) O( l" f; S: a( y - u32 retry=0;2 i6 \) L0 H$ m8 F5 e7 c
- u32 temp = 0;
: z3 P+ r, D) F -
1 j6 L% E% B2 k" o7 } - temp |= mode<<0; //设置指令5 k/ S, x& ]9 j$ m. }/ p2 A
- temp |= BankSelect<<3; //设置发送指令到bank5还是6
: ~9 e4 h! y( ]6 `1 \" M - temp |= (AutoRefresh&0xf)<<5; //设置自刷新次数5 |( i2 r/ {+ z* W- |, z, ~
- temp |= mdr<<9; //设置模式寄存器的值; Q; A! Q( Y0 F) p
- FMC_Bank5_6->SDCMR = temp; //配置寄存器
8 K& D! C! ], S -
$ O& H' z1 k0 g - //temp = FMC_Bank5_6->SDCMR;
9 H2 F; I. X% X. x - //uart_printf("FMC_Bank5_6->SDCMR=%X\r\n", temp);
" q# r* ~; C7 R, t' k: p: T - while((FMC_Bank5_6->SDSR&(1<<5))) //等待指令发送完成
0 H+ r3 O+ R! C" |& x }+ Z! g/ D4 C - {: D, H( k3 k% K. l, v
- retry++;
; a1 ]- ]8 I7 ^- r1 C3 i. ` - Delay_US(1);
% B3 ~& J0 X1 P0 I- I N, G - if(retry > 50000)return FALSE;
: N; ^7 v+ O& G - }- F1 u; p b+ ?
-
. Q$ R4 s3 H0 e" G/ U/ M/ t, z: k9 k -
( U; L* \, s! Q5 F! j - return TRUE;( w9 f; g, O4 X) _* t
- }
复制代码
1 r+ J6 ? ^0 o5 [- X0 w1 Y d9 ?. {2 d1 p8 _4 I+ `% b5 _
M( P' Q! ?/ j" R# o! @; i
- /*************************************************************************************************************- V5 k6 N; q- y0 V/ i$ R- I7 _/ U
- * 文件名 : stm32f7_sdram.h0 g1 ^" J9 ~3 f# \/ r0 S
- * 功能 : STM32F7 外部SDRAM驱动
) R+ _( m+ ]2 j) t7 M8 {) P; Y - * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
$ X: h: q5 N6 ~# }9 N - * 创建时间 : 2019-09-08
9 L& x9 s) T+ \% S - * 最后修改时间 : 2019-09-08& m" {3 m4 r) g$ m4 n" ~/ M+ h
- * 详细:
- a$ z( k* ^0 ?0 k$ f* [ - *************************************************************************************************************/ . r+ M j. u2 h
- #ifndef __STM32F7_SDRAM_H_
3 _" L5 Y @, c! p8 l! a' n - #define __STM32F7_SDRAM_H_ , [: x% c2 [! @6 O" |. K. V: C
- #include "system.h"
0 T0 Z& X6 V% d( F+ m, ^2 h: L3 R
0 n8 k0 Q# S! X7 `- ( K) Y4 n, o! [* y
- //========================================================================4 S( K# K( i7 J f7 M
- // SRAM硬件相关配置
3 s( v0 c9 ]: p u+ w - //------------------------------------------------------------------------
$ \7 t. F/ ~% S) {1 {5 v; N# w - #define Bank5_SDRAM_ADDR ((u32)0XC0000000)
" @! L& U/ Q g A$ i @ @ -
: q, S% A) }. j1 H3 L, x - void SDRAM_Init(void); //SDRAM初始化
9 e$ ?& Y# ~2 {& n# X - " m4 Q' b5 N" Z, P* t
- 6 N4 ?. X1 }: |6 Q. z8 w
- #endif //__STM32F7_SDRAM_H_
k& x$ s2 Z) x( l7 Z! }7 V
复制代码 9 b% g3 Y! P% J) T2 c& u
$ A. Z1 Y7 u8 Q; l* _ |