STM32f746gdiscovery 开发板使用的是16MB的SDRAM,由于少了一根地址线,只有8MB可用。
6 u: T$ d+ }0 _' |1 Y
% @5 I2 N1 C3 f) K! s8 D" [& Z5 [
0 w6 ^6 n" m% j2 }* b$ R7 k, s
$ z0 Q9 A1 Z5 I% x. o `, s' E) j& d- x( T: y0 B
- /*************************************************************************************************************
7 F3 q- D. Z$ J4 u7 {, f1 o7 e - * 文件名 : stm32f7_sdram.c# {: i3 x! i6 ]
- * 功能 : STM32F7 外部SDRAM驱动
. ^0 Z W7 j% f$ }( i/ {% F - * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>, m( w$ r! z6 z+ c1 Q
- * 创建时间 : 2019-09-084 I- Y: @- `0 R
- * 最后修改时间 : 2019-09-08
& W: }) w# M8 g V" a* j4 t - * 详细 : 2019-10-31 设置突发长度:4(可以是1/2/4/8)-测试过1/2/4发现都正常,唯独8的时候,屏幕会出现随机噪点
! W0 e- ^4 r: g) \ - *************************************************************************************************************/ 1 a5 Z: F9 o1 D( b+ y' \* L) l
- #include "stm32f7_sdram.h"
9 V, X2 _, P Y M0 ?' ] - #include "SYSTEM.H" # Q& i* _. L/ u0 g) g
* O# _; B: x. f+ q+ s* i3 d- $ f3 a& Z) z: t! ?
* S; s) i/ a9 E3 Y& U, B3 g1 S; t( }- //BANK选择
* D3 ~* [7 p+ n7 F0 x7 q - typedef enum7 A } I# U1 ^" } I8 _4 z( W
- {
* L: L: f2 a5 P+ O! v7 ` - SDRAM_CMD_BANK1 = 2, //命令模板存储区域13 k; @7 t4 }9 z4 v
- SDRAM_CMD_BANK2 = 1, //命令模板存储区域2
8 F" X: k" e h5 ^4 \ - SDRAM_CMD_BANK1_2 = 3, //命令模板存储区域1与2) d5 a" {1 G4 k
- }SDRAM_CMD_BANK_SELECT;
4 D, `; C) p, y+ o0 `1 P - # O$ A0 f) r# X" @+ q
- 0 S5 Y! O" j) S. Y& T( l/ j
- //命令
5 R, V% C* R( Z - typedef enum 3 x- x8 y P" n4 G6 Y3 F3 X
- {
* s7 }! q& K& ~ C5 q - SDRAM_CMD_NORMAL = 0, //正常模式% y2 a3 }6 F, K8 ?/ G
- SDRAM_CMD_CLOCK_CONFIG = 1, //时钟配置使能
Y6 H. z q* q& l& |+ C7 \" Q - SDRAM_CMD_PALL = 2, //预充电所有存储区域( t! ]- f8 `$ g5 [ S
- SDRAM_CMD_AR = 3, //自刷新命令3 m( f2 c# @! V, k/ i% Q
- SDRAM_CMD_LOAD_MODE = 4, //加载模式寄存器
( K7 K3 }3 G% ]3 U- ?: p: N5 N - //SDRAM_CMD_AR = 5, //自刷新命令. i2 p- \- N# T7 m3 S
- SDRAM_CMD_POWER_DOWN = 6, //掉电命令! B- ?; B, e/ v" W: M, X' O( v
- }SDRAM_CMD_TYPE;
: N/ S* I& {' b# D8 z) E - & m3 Z% p1 \* K9 b$ `' M# }1 H
. l) e6 g" c! ]$ n- bool SDRAM_SendCmd(SDRAM_CMD_BANK_SELECT BankSelect, u16 mode, u8 AutoRefresh, SDRAM_CMD_TYPE cmd);//SDRAM 命令模式设置
7 p5 O6 S/ `* p K/ g3 `
1 } V& C J$ P0 X& a3 Q, ?
4 w8 L: l$ @ ^5 k9 }7 }- /*************************************************************************************************************************, i& K1 ^5 w @! S
- * 函数 : void SDRAM_Init(void)- b) t; M9 s* ^% } J
- * 功能 : SDRAM 接口初始化9 `/ e5 R0 T" L; v* b. [% D
- * 参数 : 无5 P) X/ ^) g/ s# C
- * 返回 : 无
; O" `. n$ x# k - * 依赖 : 底层宏定义+ o( v9 F' L. M4 }* U
- * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>$ m6 }, B1 f! c' `9 n3 E
- * 时间 : 2019-09-08
# U: M- u; x5 P1 r& a - * 最后修改时间 : 2019-09-08
' \$ h* Q* r3 L. F) K, M1 X - * 说明 : 用于初始化STM32F7 SDRAM 接口0 s+ H, w2 O% o- }
- *************************************************************************************************************************/
7 D. ^% y( G8 @ - void SDRAM_Init(void)# W* F0 |$ }( @9 L
- {
* L& y5 ~' q4 B ?' E& h; h0 N - u32 temp;. M( e) A- `9 G1 \
-
0 @6 H8 v% Y% I! |' t0 R5 \0 t- | - SYS_DeviceClockEnable(DEV_FSMC, TRUE); //FSMC时钟使能
) O0 v6 `' L9 m1 w: b6 F - SYS_DeviceClockEnable(DEV_GPIOC, TRUE); //使能GPIOC时钟- g1 l; J8 B$ P h& v
- SYS_DeviceClockEnable(DEV_GPIOD, TRUE); //使能GPIOD时钟
* s6 Q n' c7 B e - SYS_DeviceClockEnable(DEV_GPIOE, TRUE); //使能GPIOE时钟2 t$ U; E2 d4 |' |
- SYS_DeviceClockEnable(DEV_GPIOF, TRUE); //使能GPIOF时钟0 T3 p% G( t8 b2 `8 s
- SYS_DeviceClockEnable(DEV_GPIOG, TRUE); //使能GPIOG时钟( o% E) r( w" r( p' g; ], S
- SYS_DeviceClockEnable(DEV_GPIOH, TRUE); //使能GPIOH时钟: k4 T. f( T0 @5 [1 J7 B
-
( A( b8 M2 U/ c - //初始化IO/ `0 w4 o3 i$ ^/ U) \( c1 f
- SYS_GPIOx_Init(GPIOC, BIT3, AF_PP_OPU, SPEED_100M); //PC3
" O& r; M E. O( t& ]& z$ N - SYS_GPIOx_Init(GPIOD, BIT0|BIT1|BIT8|BIT9|BIT10|BIT14|BIT15, AF_PP_OPU, SPEED_100M); //PD0/1/8/9/10/14/15 / \7 Z$ o, i5 S% P I% p
- SYS_GPIOx_Init(GPIOE, BIT0|BIT1|(0X1FF<<7), AF_PP_OPU, SPEED_100M); //PE0/1/7~15
7 h0 n) Q* C& q8 i5 }5 B* p - SYS_GPIOx_Init(GPIOF, BIT0|BIT1|BIT2|BIT3|BIT4|BIT5|BIT11|BIT12|BIT13|BIT14|BIT15, AF_PP_OPU, SPEED_100M); //PF0~5/11~15
! r9 d/ W7 z2 c - SYS_GPIOx_Init(GPIOG, BIT0|BIT1|BIT4|BIT5|BIT8|BIT15, AF_PP_OPU, SPEED_100M); //PG0/1/4/5/8/15* t3 u! e2 o5 ^! ]4 e |9 \
- SYS_GPIOx_Init(GPIOH, BIT3|BIT5, AF_PP_OPU, SPEED_100M);
& c& o M! i H5 M. g8 G$ v4 [+ |, e - & h4 s2 @& y+ K
- SYS_GPIOx_SetAF(GPIOC, 3, AF12_FSMC); //PC3,AF12
7 s1 D, m; R/ w6 a! Z: o# L ` - ( M2 n9 U- l0 t2 z7 X
- SYS_GPIOx_SetAF(GPIOD, 0, AF12_FSMC); //PD0,AF12
1 ?2 `' N5 L5 Z. p. B' _ - SYS_GPIOx_SetAF(GPIOD, 1, AF12_FSMC); //PD1,AF12 9 M' @' B' |6 d1 Z" k
- SYS_GPIOx_SetAF(GPIOD, 8, AF12_FSMC); //PD8,AF129 O5 X ~* O0 D" x7 b5 u
- SYS_GPIOx_SetAF(GPIOD, 9, AF12_FSMC); //PD9,AF12: P5 Z3 H) x, t* F4 e4 q/ ?
- SYS_GPIOx_SetAF(GPIOD, 10, AF12_FSMC); //PD10,AF12
1 t' D* d# _% A2 C2 { - SYS_GPIOx_SetAF(GPIOD, 14, AF12_FSMC); //PD14,AF123 X D# ?2 G8 x8 c
- SYS_GPIOx_SetAF(GPIOD, 15, AF12_FSMC); //PD15,AF12
& S k: v3 n+ H0 _9 `0 Y7 C+ x - 7 k2 i/ k1 M+ ^, Y. q
- SYS_GPIOx_SetAF(GPIOE, 0, AF12_FSMC); //PE0,AF12 0 _- _2 @6 [& W- u" C% u, p6 ~. Y
- SYS_GPIOx_SetAF(GPIOE, 1, AF12_FSMC); //PE1,AF12 9 x! \) |5 A& D3 V1 A6 w; |: A
- SYS_GPIOx_SetAF(GPIOE, 7, AF12_FSMC); //PE7,AF124 d4 O, Y* X8 _6 C
- SYS_GPIOx_SetAF(GPIOE, 8, AF12_FSMC); //PE8,AF120 o9 k+ A4 c. i% t- j* i/ g
- SYS_GPIOx_SetAF(GPIOE, 9, AF12_FSMC); //PE9,AF12
9 U5 o/ @: S% w5 M; B - SYS_GPIOx_SetAF(GPIOE, 10, AF12_FSMC); //PE10,AF12( y& {- t% l* r; R) O& O
- SYS_GPIOx_SetAF(GPIOE, 11, AF12_FSMC); //PE11,AF127 Y# G' F o/ e! s9 h3 i7 F5 ~2 h
- SYS_GPIOx_SetAF(GPIOE, 12, AF12_FSMC); //PE12,AF12
9 n& y0 E: W8 y& h/ H2 Q" e2 }* h - SYS_GPIOx_SetAF(GPIOE, 13, AF12_FSMC); //PE13,AF12
1 Y& H/ n+ d1 X% j' C# K2 x @ - SYS_GPIOx_SetAF(GPIOE, 14, AF12_FSMC); //PE14,AF12/ |0 `# @& j& O8 F5 Z$ P( d
- SYS_GPIOx_SetAF(GPIOE, 15, AF12_FSMC); //PE15,AF12
& g/ N' t3 `+ G% G - 6 X; B( b2 P/ o# h$ p
- SYS_GPIOx_SetAF(GPIOF, 0, AF12_FSMC); //PF0,AF12
0 K, x' V5 i( c2 C$ n% V - SYS_GPIOx_SetAF(GPIOF, 1, AF12_FSMC); //PF1,AF12 . A- t4 A4 R0 O. |' L' v
- SYS_GPIOx_SetAF(GPIOF, 2, AF12_FSMC); //PF2,AF12
$ j, Q' p1 |4 @ - SYS_GPIOx_SetAF(GPIOF, 3, AF12_FSMC); //PF3,AF12( @, M& P% s! q F5 }
- SYS_GPIOx_SetAF(GPIOF, 4, AF12_FSMC); //PF4,AF12 D/ E4 V+ [- W5 D& P
- SYS_GPIOx_SetAF(GPIOF, 5, AF12_FSMC); //PF5,AF12) m6 T! y' i* b8 P5 C% f
- SYS_GPIOx_SetAF(GPIOF, 11, AF12_FSMC); //PF11,AF12
% [. F* O! {& J, e - SYS_GPIOx_SetAF(GPIOF, 12, AF12_FSMC); //PF12,AF12; h" W j0 I% d: o6 Z' I
- SYS_GPIOx_SetAF(GPIOF, 13, AF12_FSMC); //PF13,AF12, B; S T, C6 d
- SYS_GPIOx_SetAF(GPIOF, 14, AF12_FSMC); //PF14,AF12
0 \% V5 y# y2 J% x* s# x/ S - SYS_GPIOx_SetAF(GPIOF, 15, AF12_FSMC); //PF15,AF12
/ v# f) U( ~3 L - : v9 L( X6 e' i
- SYS_GPIOx_SetAF(GPIOG, 0, AF12_FSMC); //PG0,AF12
: C0 H) X6 n4 }! b3 V( Q I - SYS_GPIOx_SetAF(GPIOG, 1, AF12_FSMC); //PG1,AF12 " i4 S9 K4 O* K
- SYS_GPIOx_SetAF(GPIOG, 4, AF12_FSMC); //PG4,AF12
% R7 f$ y( o( W( w( z; x, V - SYS_GPIOx_SetAF(GPIOG, 5, AF12_FSMC); //PG5,AF12
6 N, E* ^. z9 S v0 a9 F - SYS_GPIOx_SetAF(GPIOG, 8, AF12_FSMC); //PG8,AF12
1 |$ n8 ^2 ~& e0 a9 k# |" ?, |/ z - SYS_GPIOx_SetAF(GPIOG, 15, AF12_FSMC); //PG15,AF12! o$ K* ~# }% @+ \+ A& x# J
-
- z- h/ G# U" b# S( H - SYS_GPIOx_SetAF(GPIOH, 3, AF12_FSMC); //PH3,AF12. t$ P' p" X% w0 f) g& o
- SYS_GPIOx_SetAF(GPIOH, 5, AF12_FSMC); //PH5,AF12
P5 G' X6 \ \! l% P$ K - / ?' E9 v, Y$ e- n/ Z7 {
0 ^4 F3 [, Q4 l; @# D8 X& n- temp = 0;& k; y. M6 U: Q
- temp |= 0<<0; //8位列地址
0 h3 c& Z- X+ y- R- j1 c8 o5 A - temp |= 1<<2; //12位行地址* S5 c2 A% [% H" A% l0 f/ {7 t9 I
- temp |= 1<<4; //16位数据位宽" u) v8 T3 y) L0 c6 { \
- temp |= 1<<6; //4个内部存区(4 BANKS)) V9 K8 _- `. `+ c1 f( E- H
- temp |= 2<<7; //2个CAS延迟; L$ _9 ?' G1 a2 k
- temp |= 0<<9; //允许写访问8 ?! m- h" F+ y
- temp |= 2<<10; //SDRAM时钟=HCLK/2
2 |- v3 w6 Y2 N9 P9 W: v6 x - temp |= 1<<12; //使能突发访问
: k: R1 n5 {: g- f# u - temp |= 0<<13; //读通道延迟0个HCLK" V! W3 G2 G8 b( H' r$ _, w3 ?+ K: p
- FMC_Bank5_6->SDCR[0] = temp; //设置FMC BANK5 SDRAM控制寄存器(BANK5和6用于管理SDRAM).
7 ?+ Z9 H/ y5 g9 X$ c - 0 t0 }8 W, c) N& F v; `
- temp = 0;! e. K d( W. a) J ^6 _
- temp|=1<<0; //加载模式寄存器到激活时间的延迟为2个时钟周期' C2 I2 R8 a0 L6 u+ G
- temp|=5<<4; //退出自刷新延迟为6个时钟周期& u1 l) c$ F, x7 M* q2 S
- temp|=3<<8; //自刷新时间为4个时钟周期# I8 A! y1 H p9 G7 v: L
- temp|=5<<12; //行循环延迟为6个时钟周期) j- c5 m. b& c) \- l
- temp|=1<<16; //恢复延迟为2个时钟周期' T, q$ i7 I- j N( M
- temp|=1<<20; //行预充电延迟为2个时钟周期& [! R* I+ H2 L6 H e3 Y9 e: f
- temp|=1<<24; //行到列延迟为2个时钟周期( N6 z% w* s3 ?4 o& f$ Q
- FMC_Bank5_6->SDTR[0] = temp; //设置FMC BANK5 SDRAM时序寄存器 $ h# d% ^2 x! j+ P4 P! y
5 I! L* J5 W) t& y! C0 x( I- SDRAM_SendCmd(SDRAM_CMD_BANK1, 0, 1, SDRAM_CMD_CLOCK_CONFIG); //时钟配置使能 9 Z4 w+ |3 {: `" M; z0 m
- Delay_US(300); //至少延迟200us.
" y0 R3 E; F$ _0 L/ m7 k) j5 l8 a - SDRAM_SendCmd(SDRAM_CMD_BANK1,0, 1, SDRAM_CMD_PALL); //对所有存储区预充电
# k+ a: m' H& K. R/ L - SDRAM_SendCmd(SDRAM_CMD_BANK1,0, 8, SDRAM_CMD_AR); //设置自刷新次数 ( h7 @# H P2 Z
- % [2 Q: I, d% B, l* J: s
- temp = 0;9 z6 D# T: |- i3 D
- temp |= 2<<0; //设置突发长度:4(可以是1/2/4/8) -测试过1/2/4发现都正常,唯独8的时候,屏幕会出现随机噪点( o6 {% t ?; S; L
- temp |= 0<<3; //设置突发类型:连续(可以是连续/交错)
2 D7 }; {: |# H' K% K/ z: v - temp |= 2<<4; //设置CAS值:2$ A g# O: i3 q% p t
- temp |= 0<<7; //设置操作模式:0,标准模式% i6 Y& ?- `3 d k0 K
- temp |= 1<<9; //设置突发写模式:1,单点访问
2 y' C' ]$ H+ K: e+ h2 T - SDRAM_SendCmd(SDRAM_CMD_BANK1,temp, 1, SDRAM_CMD_LOAD_MODE); //设置SDRAM模式9 w: R8 b ?; d+ R* y$ r5 ?/ M
-
3 P2 r3 I/ c5 S- e# |1 r - //COUNT=SDRAM刷新周期/行数-20
5 L/ C. [1 \, ~* o9 s" W - //SDRAM刷新周期为64ms,SDCLK=AHB/2=100Mhz,行数为4096.! f# _7 S- E- e2 `
- //计算方法为64*1000*AHB/2/4096-20& \& w5 ^0 _; L W0 f' t! O3 a1 s
- temp = 64*1000*(SYS_GetAHBClockSpeed()/1000000/2)/4096-20;9 X3 ^4 I. B. } H" y
- FMC_Bank5_6->SDRTR = temp<<1; //设置刷新频率计数器
3 ^- n- i6 Q* ^. p/ j - }2 G* B, x G' @9 S7 @/ f( z
% g0 F: s2 C8 |3 x, u- # n$ H! Y: b5 V7 Z! s/ B' i% y
- /*************************************************************************************************************************
/ C1 M7 v; k' N- n' ?# z - * 函数 : bool SDRAM_SendCmd(SDRAM_CMD_BANK_SELECT BankSelect, u16 mdr, u8 AutoRefresh, SDRAM_CMD_TYPE mode)6 u! P& ~: P; ~( ~1 Z+ e& L5 ~
- * 功能 : SDRAM 命令模式设置9 g0 {4 ?( V% K. c8 L9 q4 _
- * 参数 : BankSelect:bank选择;mdr:模式;AutoRefresh:自刷新设置;mode:模式命令+ D3 j8 a3 ]* W6 L2 p
- * 返回 : TRUE:成功;FALSE:失败. d5 k& x+ ?3 h* O
- * 依赖 : 底层宏定义
; K: R, U4 `' @ - * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
% i. ~5 O. O! V. X: K, h - * 时间 : 2019-09-08+ a3 m; A( \8 N2 g
- * 最后修改时间 : 2019-09-08
' w- f) P5 b8 e8 o/ Q+ v - * 说明 :
: I! h F6 X; M3 @% i! W - *************************************************************************************************************************/ 3 l; C8 J+ h# f4 F% f- N
- bool SDRAM_SendCmd(SDRAM_CMD_BANK_SELECT BankSelect, u16 mdr, u8 AutoRefresh, SDRAM_CMD_TYPE mode), e% O& `! L; P, ?( l0 K6 |
- {
. Z6 R8 S) B2 z' ] - u32 retry=0;
% q6 J1 |2 I1 i& I( k. { - u32 temp = 0;
& h, E% l9 H: W. `! t -
/ T2 A+ G( i9 u - temp |= mode<<0; //设置指令1 g" m+ ]" g& P8 C. S" }
- temp |= BankSelect<<3; //设置发送指令到bank5还是6
, G) U1 Z5 m. g1 t4 o2 [& V: M5 J - temp |= (AutoRefresh&0xf)<<5; //设置自刷新次数
* y# n& |* v& S* Z6 @* e& v& o7 ^ - temp |= mdr<<9; //设置模式寄存器的值
6 e* y6 m3 d h; h- w/ w - FMC_Bank5_6->SDCMR = temp; //配置寄存器: @, y5 _+ W5 n
- ( |/ S6 r% {3 I- ]$ q
- //temp = FMC_Bank5_6->SDCMR;. I1 F0 r. Z! J1 }7 e2 P
- //uart_printf("FMC_Bank5_6->SDCMR=%X\r\n", temp);
3 Y5 H) V) F* ^4 v - while((FMC_Bank5_6->SDSR&(1<<5))) //等待指令发送完成
6 u6 S+ y! Q$ S. j& z& E - {" f, o% U; p D' t% |% {( F
- retry++;
) l! K p9 \* i- b! P - Delay_US(1);
8 t" q" f2 I B l - if(retry > 50000)return FALSE; 0 F0 v- i$ M7 @% B) l, ?* z8 ^
- }
$ L9 ?6 x/ N( A9 d R* e+ ] - & N2 i2 {( _; N* `
-
) [$ ]9 P) _- @0 M3 M - return TRUE;
1 e7 s4 D7 t- K5 b- V/ N6 g - }
复制代码
. R& s$ n Q9 Q, k' [( S8 E
' _8 _4 ~6 M! Y
3 |" b- F3 b# \1 `- /*************************************************************************************************************! a r2 |" p- M+ Z# H
- * 文件名 : stm32f7_sdram.h
" Q1 ]0 }0 i& W& X/ ?1 R7 Z6 m: G - * 功能 : STM32F7 外部SDRAM驱动
4 u( x0 S7 n9 L/ @8 W - * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
9 f9 z( e7 P' E# g5 E - * 创建时间 : 2019-09-08& r4 \$ G* p: g; w
- * 最后修改时间 : 2019-09-08
$ B- Q( _- D- O( V - * 详细:
) c- h7 j# [2 a6 @8 @( c* ^ - *************************************************************************************************************/
4 C8 F1 Z4 T8 A; S5 a( z! @ - #ifndef __STM32F7_SDRAM_H_, Q$ P; M) t! z6 K5 x6 j
- #define __STM32F7_SDRAM_H_ " V! V8 w2 p0 h# C# ~0 E
- #include "system.h"
' f8 } G1 W9 ~1 _2 h
, ^8 z# F, L. l7 L- 2 r+ q! Y5 N8 ^7 A9 P
- //======================================================================== [. h# t* U* b
- // SRAM硬件相关配置
4 D+ ^3 k9 u/ G' \ - //------------------------------------------------------------------------ L, w. G2 k0 H$ b# J( {3 ~7 S
- #define Bank5_SDRAM_ADDR ((u32)0XC0000000)
) |# Y c, L9 Z C. A! ~. V. b - 8 C w) u1 o P/ X {
- void SDRAM_Init(void); //SDRAM初始化
$ d' U c. [: C
k& o$ W- L, y2 |- t7 X' F! d! c+ [9 r& h( @
- #endif //__STM32F7_SDRAM_H_' _& A- J; O, ` @1 V! @6 ^
复制代码 : b: H. E0 c" I7 o
+ ~6 K. q; z. S! h! Y |