你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32CubeMX 外部SRAM经验分享

[复制链接]
攻城狮Melo 发布时间:2023-6-28 15:32
1.外部SRAM简介
本例程使用的STM32F103ZET6本身有64K字节的SRAM,一般应用已经足够;不过在一些对内存要求高的场合,比如跑算法或者GUI等,就需要外扩SRAM来满足大内存使用的需求。这里我们使用了一颗256K字节容量的SRAM芯片:IS62WV12816,利用STM32F1的FSMC控制该SRAM芯片,实现对该SRAM芯片的访问控制
IS62WV12816是ISSI公司生产的16位宽128K(128*2,即256K字节)容量的CMOS静态内存芯片,它有高速访问、低功耗、兼容TTL电平接口、全静态操作(不需要刷新和时钟电路)、三态输出和字节控制(支持高/低字节控制)等特点。IS62WV12816的引脚以及对应的引脚功能如下图示:
$ a3 l1 W# I; ~
微信图片_20230628153158.png
0 o% G, {; s0 e& P, D3 h) ]
A0 ~ A16为地址线,总共17根地址线(可访问2^17 = 128K字节空间);I/O0 ~ I/O15为数据线,总共16根数据线;CS1(低电平有效)和CS2(高电平有效)都是片选信号;WE为输入使能信号(写信号);OE为输出使能信号(读信号);UB和LB分别是高字节和低字节控制信号
/ ]! K+ q7 b1 x. |% j* S4 M
6 b$ E) y1 x, @6 O. Q
2.硬件设计
D1指示灯用来提示系统运行状态,按键用来控制IS62WV12816数据读写,TFTLCD和串口1用来显示读写的内容
    / M, E: G& N- c% f1 W- ]
  • D1指示灯
  • K_UP/K_DOWN按键. G) P& y4 [: F- J% n
  • USART1串口
  • TFTLCD

    3 w8 Q3 J4 n/ B
  • IS62WV12816

    % l/ P& S4 n' c* e1 m
    7 x8 Y+ l. C, |7 h6 W3 @; o( `
从电路图中可以看到IS62WV12816和STM32F1的连接线路:. P6 r; E" f! s' M/ X# N- d  M2 Y
A0 ~ A16连接在FSMC_A0 ~ FSMC_A16上(连接顺序可以打乱,因为地址是固定的)
& e: v" v( v4 S& U( |7 c. d) CI/O0 ~ I/O15连接在FSMC_D0 ~ FSMC_D15上(连接顺序不能打乱,否则读写数据将出错)
: R8 P* z- B' ]: N7 @UB和LB连接在FSMC_NBL1 和 FSMC_NBL0上+ N5 {" _1 S* r# ]) ?, w. C
OE和WE分别连接在FSMC_NOE 和 FSMC_NWE上3 ?1 ^- a: ?% K3 D1 q
CE连接在FSMC_NE3上

, Q! J' U) A/ Q, M, b) v
微信图片_20230628153150.png

& h7 q' s) W4 b! @2 j

由于TFTLCD核SRAM共用FSMC总线,因此他们通过不同片选分时复用,互不影响

1 W8 N5 ~$ q6 E3 Y5 X, F

3.软件设计
3.1 STM32CubeMX设置
➡️ RCC设置外接HSE,时钟设置为72M
➡️ PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平
➡️ PA0设置为GPIO输入模式、下拉模式;PE3设置为GPIO输入模式、上拉模式
➡️ USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位
➡️ 激活FSMC
➡️ 输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码
6 o2 \3 J' Z# k8 v

由于TFTLCD使用的Bank1_sector4和SRAM使用的Bank1_sector3无法同时在CubeMX里设置分时复用,因此需要单独创建SRAM的FSMC初始化函数(可自行创建,也可另外创建一个CubeMX工程,按下图设置后将生成的相关FSMC初始化代码拷贝到当前工程源码中并稍作修改)

' `1 p( O$ V$ ?( N- ]5 r

微信图片_20230628153141.png

& t; Z& H0 `, f% L: y! Y5 P& `
3.2 MDK-ARM软件编程
➡️ 创建按键驱动文件key.c和key.h,参考按键输入例程
➡️ 创建LCD驱动文件tftlcd.c 和tftlcd.h,参考TFTLCD显示例程
➡️ 创建IS62WV12816芯片驱动文件sram.c和sram.h

9 K# t2 q5 @+ A' P# c4 O# }  S
  1. #define Bank1_SRAM3_ADDR    ((uint32_t)(0x68000000))//Bank1区域3的起始地址        8 ^$ A% V4 @; @
  2. SRAM_HandleTypeDef SRAM_Handler;//定义SRAM句柄$ X$ y  Y- d8 o9 a8 P# I! d9 ~
  3. //SRAM的FSMC初始化函数( Z# @+ T  v9 I+ V" Z# K2 x6 B9 K4 Z
  4. void FSMC_SRAM_Init(void){       
    ! h, W2 V9 t% T, _/ z/ m& X) f
  5.   GPIO_InitTypeDef GPIO_InitStruct;
    # w4 z" S% b1 ^6 w' O9 n
  6.   FSMC_NORSRAM_TimingTypeDef FSMC_ReadWriteTim;
    1 e: D4 E4 P6 \  s0 K
  7.   __HAL_RCC_FSMC_CLK_ENABLE();           
    * q; _) \) q. k
  8.   __HAL_RCC_GPIOD_CLK_ENABLE();              
    + k, _7 Y6 G  n  Z3 b
  9.   __HAL_RCC_GPIOE_CLK_ENABLE();               & i% h& }0 e1 Y. o& ~5 ~0 ^, ]
  10.   __HAL_RCC_GPIOF_CLK_ENABLE();              & s4 H6 A- _6 r1 T* }  c# H$ `
  11.   __HAL_RCC_GPIOG_CLK_ENABLE();               ) p- ?: o9 D3 A' q6 _0 a* n
  12.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
    & ]+ o. I3 P" Z1 B: Z7 D/ B
  13.                      |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13
    3 x1 u5 Z5 y3 e; g4 b" o' V8 \% l
  14.                      |GPIO_PIN_14|GPIO_PIN_15;
    6 l% ^" s0 I2 t( ?4 D" R
  15.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    3 b/ k; o3 T2 v% n
  16.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;" B2 U2 Y# x, u' _! _/ w) F
  17.   HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
    " R5 }5 v: Z% O: w" ^: i: v
  18.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
    ( V( g* q& E7 x, D  _' D  ?
  19.                      |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_10;9 s& {4 A5 J3 k% J! W
  20.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    , f; [/ Y$ E* ^  H  e$ n
  21.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    2 W5 Z7 t; W/ V' @' ~. c* {: w
  22.   HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
    " j, B( Q+ w% P) T
  23.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 ; c1 ]! x* ?: l1 }6 F) ?
  24.                      |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
    / b: C; T8 |1 G- g& k
  25.                      |GPIO_PIN_15;
    # z7 v7 q  a: ]+ m2 n
  26.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;7 |6 ?' A2 D3 j4 G# N/ O4 D
  27.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;3 H' Q* I8 b1 ], q8 o9 w
  28.   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    8 T. F9 |  L. X) Y" R
  29.   GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
    ; S' u, G2 ~' u: F
  30.                      |GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1
    ! _7 ]! X8 L' a# \
  31.                      |GPIO_PIN_4|GPIO_PIN_5;
    " K( U6 @0 C7 `9 l" p' X6 I
  32.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;5 ?1 O; t. r$ u" D
  33.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;  e9 `, [/ [0 C2 h
  34.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);  
    0 n: s* l# H" [4 C) V5 z
  35.        
    4 ]8 d4 K1 W9 {8 [
  36.   SRAM_Handler.Instance=FSMC_NORSRAM_DEVICE;                1 [6 O4 n% E- `* D
  37.   SRAM_Handler.Extended=FSMC_NORSRAM_EXTENDED_DEVICE;     
    5 S) H% D6 S/ x
  38.   SRAM_Handler.Init.NSBank=FSMC_NORSRAM_BANK3;        //使用NE33 i7 J( i1 D/ t$ G6 z
  39.   SRAM_Handler.Init.DataAddressMux=FSMC_DATA_ADDRESS_MUX_DISABLE;//地址/数据线不复用9 j# D& {# j; {7 h7 y& X' G
  40.   SRAM_Handler.Init.MemoryType=FSMC_MEMORY_TYPE_SRAM;            //SRAM
    * t8 O! k1 h. _- `1 H$ v
  41.   SRAM_Handler.Init.MemoryDataWidth=FSMC_NORSRAM_MEM_BUS_WIDTH_16;//16位数据宽度: Y$ d8 ^& o8 |  g2 n. H, A" l
  42.   SRAM_Handler.Init.BurstAccessMode=FSMC_BURST_ACCESS_MODE_DISABLE;//不使能突发访问  ~* j% m, \+ A. z. _7 F
  43.   SRAM_Handler.Init.WaitSignalPolarity=FSMC_WAIT_SIGNAL_POLARITY_LOW;//等待信号的极性(突发模式)3 q, J4 O! Q: Y$ R6 S
  44.   SRAM_Handler.Init.WaitSignalActive=FSMC_WAIT_TIMING_BEFORE_WS;           ; v) f1 w9 I& V- }" U; a8 _2 D) r/ Y% P
  45.   SRAM_Handler.Init.WriteOperation=FSMC_WRITE_OPERATION_ENABLE;    //写使能
    9 R  P$ ~. R) A3 @5 p# L/ h
  46.   SRAM_Handler.Init.WaitSignal=FSMC_WAIT_SIGNAL_DISABLE;          " @+ N& j7 h) |% V
  47.   SRAM_Handler.Init.ExtendedMode=FSMC_EXTENDED_MODE_DISABLE;       //读写使用相同的时序
    2 x* [' z+ d- _. D6 H6 {
  48.   SRAM_Handler.Init.AsynchronousWait=FSMC_ASYNCHRONOUS_WAIT_DISABLE;# L$ b! C5 G  ]$ o
  49.   SRAM_Handler.Init.WriteBurst=FSMC_WRITE_BURST_DISABLE;           //禁止突发写
    * Q- ?2 ~+ d3 N7 x% n7 j# {1 f
  50.   //FSMC读时序控制器" ~, @& b  w$ }  T9 ^/ d
  51.   FSMC_ReadWriteTim.AddressSetupTime=0x00;      //地址建立时间(ADDSET)为1个HCLK/ D0 f: ?2 R5 M7 D2 C6 X& I
  52.   FSMC_ReadWriteTim.AddressHoldTime=0x00;        //地址保持时间(ADDHLD)模式A未用到& B" w4 u% E: C% u' f. B
  53.   FSMC_ReadWriteTim.DataSetupTime=0x08;                //数据保持时间(DATAST)为9个HCLK/ y6 l9 _" Q9 A0 ?9 [
  54.   FSMC_ReadWriteTim.BusTurnAroundDuration=0X00;5 l3 o% C0 h5 A6 e& J
  55.   FSMC_ReadWriteTim.AccessMode=FSMC_ACCESS_MODE_A;//模式A
    + x8 c4 h) _7 _' l- I& a& Y0 ?
  56.   HAL_SRAM_Init(&SRAM_Handler,&FSMC_ReadWriteTim,&FSMC_ReadWriteTim);        9 N- ~# s/ ~4 p, v9 A  i
  57. }4 c' T  S' D- X) j8 M$ g3 o3 M' ?
  58. //n向指定地址写数据
    6 f/ s' H! p- `) G8 T( X
  59. void FSMC_SRAM_WriteBuffer(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t n){0 b1 d# R3 E" ]# M  b. Y& H
  60.   for(;n!=0;n--){        // n表示要连续写入的字节个数( S9 A/ z6 Z+ h$ v3 \' y
  61.     *(vu8*)(Bank1_SRAM3_ADDR + WriteAddr) = *pBuffer;
    , o; f# e8 U+ o2 Z+ o
  62.     WriteAddr++;        //要写入的地址; J* U% e* |1 B) d( ^* {
  63.     pBuffer++;                //要写入的数据的指针
    4 @( d( n7 [& [% Y7 d6 {
  64.   }4 F+ k$ [' G% @$ b
  65. }
    3 j$ Q" t* D0 h
  66. //从指定地址读数据  o5 E/ U+ }( |5 n- u8 ~- K
  67. void FSMC_SRAM_ReadBuffer(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t n){+ A( k8 X+ |' D" I/ c% k  L
  68.   for(;n!=0;n--){        // n表示要连续读出的字节个数) z( e- Y1 P( o7 z
  69.     *pBuffer++=*(vu8*)(Bank1_SRAM3_ADDR+ReadAddr);//存放读出的数据' x# S' D. M$ g/ N7 |; }
  70.     ReadAddr++;                //要读出的起始地址9 t: q6 ~2 D2 z6 b; y; e8 L8 d
  71.   }
    0 P& Y0 m# [* ^
  72. }2 f3 T+ V" }% |0 N# P/ [6 R, g2 D
  73. //            
    ! q7 u) W  U* x, i! T; c+ i; K
  74. void ExSRAM_Cap_Test(uint16_t x,uint16_t y){+ p. f: }& a3 C
  75.   uint8_t writeData = 0xf0, readData;
    4 y8 t( {) |- O6 w3 j4 V2 Y1 L
  76.   uint16_t cap=0;( h, ^0 O+ J0 J* ?+ W
  77.   uint32_t addr;       
    7 J( j. Z7 }& a. E& Y- Q" ]
  78.   addr = 1024;         //从1KB位置开始计算        $ C) h3 H  s5 t8 w$ ^4 r* K$ v) r
  79.   LCD_ShowString(x,y,239,y+16,16,"ExSRAM Cap:   0KB"); 8 R  M. }( k$ \4 P! P( G8 T
  80.         ( @/ p! l" n( P5 t
  81.   while(1){& T" O! }. J% ~# _- Q5 S
  82.     FSMC_SRAM_WriteBuffer(&writeData, addr, 1);
    % y! r3 \5 Z0 T# o0 _6 M% a& ^' {
  83.     FSMC_SRAM_ReadBuffer(&readData,addr,1);- S5 N' X# B* |; [
  84.        
    # `: D' o- B  D/ B
  85.     if(readData == writeData){//检查读出的数据是否与写入的数据一样
    8 N% g: q  g6 @6 M0 k/ g( n
  86.       cap++;                //如果相同表示写入/读出成功,容量加1(单位KB)
    ' {6 h+ w/ G( l
  87.       addr += 1024;        //地址加1024/ r+ [$ u" r  _. u  |4 S* T
  88.       readData = 0;
    . w0 g- w" K1 e& N: T
  89.       if(addr > 256 * 1024)//IS62WV12816的容量为256KB% F% z* d! `* F: Y) @' ?
  90.         break;   
    , z* s5 D0 {5 M  Q
  91.     }
    + G/ }! }: }6 x
  92.     else
    ( m+ j; X( o# a# v' w
  93.       break;  5 [5 C6 a/ S% l+ E9 z
  94.   }
    3 Y( K7 n( x. k2 n
  95.   LCD_ShowxNum(x+11*8,y,cap,4,16,0);//LCD上显示内存容量
    : w4 ]+ @- R" ?4 u0 {" r: Q
  96.   printf("SRAM Menmory Size:%dKB\r\n",cap);& K  |0 L3 a( y
  97. }
复制代码

$ U3 _& ~' |% D& j8 u* q7 V
➡️ 在main.c文件下编写SRAM测试代码
, T* x  y5 g2 l- \9 Z
  1. int main(void){
    & m+ a) C5 m, I! \7 a
  2.   /* USER CODE BEGIN 1 */
    6 Z# b* A$ t" X  v  Y% y
  3.   uint8_t key;
    + s$ s5 U6 O5 y6 f  c' g+ X
  4.   uint8_t text_buf[] = "This is SRAM testing...";
    ! m& s+ d5 `% u
  5.   uint8_t textlen = sizeof(text_buf);" u. N, v3 Z' T; F' i# \1 e& e  j
  6.   uint8_t read_buf[textlen];
    + K4 H) @1 V7 N( ~. A
  7.   /* USER CODE END 1 */' B$ X& X: G" M! v
  8.   HAL_Init();2 C& L$ o- D' g4 D/ D7 v0 \5 \
  9.   SystemClock_Config();1 S! i+ v9 N$ a/ |% e& _
  10.   MX_GPIO_Init();( h, }5 o; ]! f& J
  11.   MX_FSMC_Init();! ~8 ^/ l& m6 q$ R$ E
  12.   MX_USART1_UART_Init();- K3 [8 G" f% H- d0 E* Y
  13.   /* USER CODE BEGIN 2 */1 S$ f( m. ?9 n6 B* N  q$ j4 m& l
  14.   TFTLCD_Init();
    # Q' D, Q. G& x* g& P
  15.   FSMC_SRAM_Init();
    + ], S4 w1 \; ^9 ~, S8 [
  16.   FRONT_COLOR=BROWN;9 B$ T. G9 D% h1 ~, ?
  17.   LCD_DrawRectangle(5,5,235,95);5 w' ]; S, C" k/ _# a; L5 v; V
  18.   FRONT_COLOR=BLACK;& d, T: v) d) |( s5 q8 ^$ t
  19.   LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,16,"ANDYXI STM32F1");: ?: i) J9 ~& s/ g( y
  20.   LCD_ShowString(10,30,tftlcd_data.width,tftlcd_data.height,16,"STM32CubeMx SRAM");6 T9 G. |: z$ m! w- M  i, z
  21.   LCD_ShowString(10,50,tftlcd_data.width,tftlcd_data.height,16,"ExSRAM Test");
    , w* v  P" I7 }5 m6 y: G
  22.   LCD_ShowString(10,70,tftlcd_data.width,tftlcd_data.height,16,"K_UP:Write   K_DOWN:Read");       
    6 M: u% |) ^9 l- I; B# o* e, T
  23.   FRONT_COLOR=RED;
    . k* n; J9 R6 @) i$ y3 I! \) v% M5 \
  24.   ExSRAM_Cap_Test(10,110);
    + F: k& [% j% B& V) Y
  25.   FRONT_COLOR=MAGENTA;) e" L& y7 X6 Q9 X( J
  26.   LCD_ShowString(10,130,tftlcd_data.width,tftlcd_data.height,16,"Write:");
    , ^( {7 n* \% q$ R. h4 ]
  27.   LCD_ShowString(10,150,tftlcd_data.width,tftlcd_data.height,16,"Read :");  o( w% s' g  \
  28.   /* USER CODE END 2 */
    6 S: C; a: s8 v! d3 ?+ n' y
  29.   /* Infinite loop */5 F: |7 Y7 @4 _8 }& S5 w$ v8 [! n5 ?
  30.   /* USER CODE BEGIN WHILE */
    4 {& Y: M0 C2 P1 J5 Z
  31.   while(1){2 V* g' s  n8 i% f1 o: c4 f
  32.     key = KEY_Scan(0);
    ! U0 ~1 U, J2 K, N1 Q0 |& b
  33.     if(key == KEY_UP_PRES){        //KEY_UP按下写数据到SRAM) c( _5 x4 }8 T4 T) M. H, e
  34.       FSMC_SRAM_WriteBuffer(text_buf,0,textlen);
    ) @3 ]: Y* P7 {- _6 M0 d
  35.       printf("SRAM_Write:%s\r\n",text_buf);: m/ O$ o3 A: C
  36.       LCD_ShowString(10+6*8,130,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)text_buf);/ [; ?) k- m) p( ~- U
  37.     }
    $ O7 v: a% t& |# P* M
  38.     if(key == KEY_DOWN_PRES){        //KEY_DOWN按下从SRAM读出数据& R" e8 J, R4 f, b$ J) l
  39.       FSMC_SRAM_ReadBuffer(read_buf,0,textlen);
    5 I/ O& w3 F5 ^8 ^* [+ p
  40.       printf("SRAM_Read:%s\r\n",read_buf);
    9 ~& L: r+ b: b+ D* G% {6 j
  41.       LCD_ShowString(10+6*8,150,tftlcd_data.width,tftlcd_data.height,16,read_buf);; k% v+ k3 I2 m' o4 I
  42.     }               
    ! H4 x9 [  F" B& K& }- ^; i
  43.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
    + w' q; H1 I5 x# r% I' Z7 F6 ?/ m- e
  44.     HAL_Delay(200);! i* B" T- H; X' J0 t
  45.   }
    $ o) t* z( ?5 O7 |# ^4 F' u
  46. }
复制代码

- y" \- c# W. ^9 c3 h
4.下载验证
7 B% M$ D% L' I4 V$ D' F
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,KEY_UP按下写数据到SRAM,KEY_DOWN按下从SRAM读出数据,并将写入和读出的数据显示在LCD屏上,并通过串口1打印出来
微信图片_20230628153134.png

( v" a; Y3 k6 M
转载自: 嵌入式攻城狮
如有侵权请联系删除8 V3 |+ Y9 O! \, x/ h+ N+ c0 [

" C4 {3 H/ I/ D" W2 P1 B
赞 收藏 评论0 发布时间:2023-6-28 15:32

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版