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

基于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的引脚以及对应的引脚功能如下图示:
0 M4 D2 y/ U% O7 m% b/ ^
微信图片_20230628153158.png

  g0 E- t- a7 }2 \
A0 ~ A16为地址线,总共17根地址线(可访问2^17 = 128K字节空间);I/O0 ~ I/O15为数据线,总共16根数据线;CS1(低电平有效)和CS2(高电平有效)都是片选信号;WE为输入使能信号(写信号);OE为输出使能信号(读信号);UB和LB分别是高字节和低字节控制信号
; Y7 S$ N$ W+ B; {# T# M1 e7 D

( n! Q6 F5 h2 g& e  |. |
2.硬件设计
D1指示灯用来提示系统运行状态,按键用来控制IS62WV12816数据读写,TFTLCD和串口1用来显示读写的内容

    ; `6 [$ r8 E4 ?
  • D1指示灯
  • K_UP/K_DOWN按键
    ' }7 s' f% y3 S
  • USART1串口
  • TFTLCD
    . S% u4 n' C* Z! E4 \6 ]! p4 T
  • IS62WV12816

    : U" a9 r/ K1 U

    : ?; Y/ H  b; F: M8 V8 L7 R, \
从电路图中可以看到IS62WV12816和STM32F1的连接线路:1 p& y: M: b. r2 z- f0 e. S( a
A0 ~ A16连接在FSMC_A0 ~ FSMC_A16上(连接顺序可以打乱,因为地址是固定的)
% A' @# C9 q& Y% l$ ?: \9 p4 JI/O0 ~ I/O15连接在FSMC_D0 ~ FSMC_D15上(连接顺序不能打乱,否则读写数据将出错)7 t$ s  ^6 v6 D# E0 s7 I, ~
UB和LB连接在FSMC_NBL1 和 FSMC_NBL0上  r1 Q" n. _7 z; q4 S
OE和WE分别连接在FSMC_NOE 和 FSMC_NWE上
1 T: x- j$ Q8 ?7 z; FCE连接在FSMC_NE3上
  j7 M+ f& T' C$ l5 r; r! \
微信图片_20230628153150.png

. V3 C6 a+ h6 D  J" t. W  N: E

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

  I; J1 g, o5 N1 q, u

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,生成工程代码

9 a) K9 K1 D: Y1 J& @

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

! F- s/ d" x" Q! d) J' _0 ]4 o

微信图片_20230628153141.png

- k( {: m" p' q/ E2 l% Y1 n
3.2 MDK-ARM软件编程
➡️ 创建按键驱动文件key.c和key.h,参考按键输入例程
➡️ 创建LCD驱动文件tftlcd.c 和tftlcd.h,参考TFTLCD显示例程
➡️ 创建IS62WV12816芯片驱动文件sram.c和sram.h

/ I3 j- D# p' Y2 G8 x/ M
  1. #define Bank1_SRAM3_ADDR    ((uint32_t)(0x68000000))//Bank1区域3的起始地址        ! s1 a1 }7 K! [
  2. SRAM_HandleTypeDef SRAM_Handler;//定义SRAM句柄: z0 x+ \, U1 T& W6 d
  3. //SRAM的FSMC初始化函数; N) ?! Q2 x1 G+ S
  4. void FSMC_SRAM_Init(void){        # B- Z, F6 ^" v- q* b
  5.   GPIO_InitTypeDef GPIO_InitStruct;
    4 y' p( X* b; }# |2 c8 f
  6.   FSMC_NORSRAM_TimingTypeDef FSMC_ReadWriteTim;
    , j; y8 y+ J  R
  7.   __HAL_RCC_FSMC_CLK_ENABLE();           
    ! O# n' Q; l. m" c/ [5 v) {
  8.   __HAL_RCC_GPIOD_CLK_ENABLE();              
    ( v: I$ F2 a: ]
  9.   __HAL_RCC_GPIOE_CLK_ENABLE();               % j) A# T1 F. I1 Y. F5 p
  10.   __HAL_RCC_GPIOF_CLK_ENABLE();              
    0 h2 s9 M# u: w9 @  X! p" \; `* Q
  11.   __HAL_RCC_GPIOG_CLK_ENABLE();               , I; X1 j  _( ]9 b5 x9 z! N: s+ I( \' V
  12.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
    ( r" w2 s; t* L' F+ {
  13.                      |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13
    - x" ]! @* V7 V+ Z! _
  14.                      |GPIO_PIN_14|GPIO_PIN_15;! {1 I2 P0 p4 j6 V4 F. O, t5 ?5 T+ B
  15.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    2 O& q) g8 K+ v; L/ x) y' N
  16.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    3 i- [) H) g# w. B6 A6 P5 W( H
  17.   HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);) o/ O" p0 E& D, C
  18.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 % F3 V0 S/ G7 j  v6 O0 [. p% K
  19.                      |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_10;
    2 t( N# w* \. B9 e" u2 F. V1 W/ D
  20.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;, h% ], h% }$ p% X6 d1 u
  21.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;1 I* {  i2 b9 y) m# M
  22.   HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
    ' b9 D& {# s/ h0 H
  23.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
    * j4 p9 P# J, @8 ?4 R
  24.                      |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 ' F! N9 C( }& A/ O
  25.                      |GPIO_PIN_15;7 T  ^0 H7 j, Z3 g
  26.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;1 K0 {# B! A* ^* T; r- ]
  27.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;3 C$ X" [0 b& ?0 \. i
  28.   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);8 ], K. S! }) j& g3 O" ~
  29.   GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
    + z0 W% Q/ ?/ b5 Z! s6 ~+ T0 d* X
  30.                      |GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1 # ~9 u9 H5 i7 @$ r
  31.                      |GPIO_PIN_4|GPIO_PIN_5;
    4 o  i, K3 _8 [) \9 E! F1 y
  32.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;& Y$ \) X5 c& a
  33.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;! H* e/ k7 b9 ^- {6 b; H
  34.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);  
    ( Y7 x) R( ^% B  U( z" I
  35.         6 S- w4 J* U2 b; A3 G, v
  36.   SRAM_Handler.Instance=FSMC_NORSRAM_DEVICE;                # q: b7 Y3 O& P" |6 Y5 A
  37.   SRAM_Handler.Extended=FSMC_NORSRAM_EXTENDED_DEVICE;     
    % j/ U6 S7 C3 H9 J) [$ R
  38.   SRAM_Handler.Init.NSBank=FSMC_NORSRAM_BANK3;        //使用NE3
    6 f5 e2 P- S; \8 |
  39.   SRAM_Handler.Init.DataAddressMux=FSMC_DATA_ADDRESS_MUX_DISABLE;//地址/数据线不复用
    5 o) p- n) z2 B* L% J
  40.   SRAM_Handler.Init.MemoryType=FSMC_MEMORY_TYPE_SRAM;            //SRAM* L: B; H. \, f$ h" Y( Z/ T
  41.   SRAM_Handler.Init.MemoryDataWidth=FSMC_NORSRAM_MEM_BUS_WIDTH_16;//16位数据宽度; j% a9 J6 M" ]  A2 ]( V/ g8 d2 a
  42.   SRAM_Handler.Init.BurstAccessMode=FSMC_BURST_ACCESS_MODE_DISABLE;//不使能突发访问/ p8 B4 ^. E( s
  43.   SRAM_Handler.Init.WaitSignalPolarity=FSMC_WAIT_SIGNAL_POLARITY_LOW;//等待信号的极性(突发模式)
    9 r& o8 ]5 }. {" Z) X
  44.   SRAM_Handler.Init.WaitSignalActive=FSMC_WAIT_TIMING_BEFORE_WS;          
    / b. A. P0 l; q7 s
  45.   SRAM_Handler.Init.WriteOperation=FSMC_WRITE_OPERATION_ENABLE;    //写使能
    . g8 j: P$ J2 a7 `$ }
  46.   SRAM_Handler.Init.WaitSignal=FSMC_WAIT_SIGNAL_DISABLE;         
    ' |6 D  D' }9 }5 e, ^7 E- P, w" H
  47.   SRAM_Handler.Init.ExtendedMode=FSMC_EXTENDED_MODE_DISABLE;       //读写使用相同的时序
    0 v  t" A% R* f0 q0 d& @" ^1 a
  48.   SRAM_Handler.Init.AsynchronousWait=FSMC_ASYNCHRONOUS_WAIT_DISABLE;
    8 u$ a' [6 Q3 J* ?5 V7 ?
  49.   SRAM_Handler.Init.WriteBurst=FSMC_WRITE_BURST_DISABLE;           //禁止突发写% B! m, \* S4 h6 c1 p8 i
  50.   //FSMC读时序控制器
    4 C/ I: U9 j1 |/ z& N8 V: @
  51.   FSMC_ReadWriteTim.AddressSetupTime=0x00;      //地址建立时间(ADDSET)为1个HCLK
    8 Z% F  A/ U( m( _6 _
  52.   FSMC_ReadWriteTim.AddressHoldTime=0x00;        //地址保持时间(ADDHLD)模式A未用到
    ) y" H% z; W4 X/ e
  53.   FSMC_ReadWriteTim.DataSetupTime=0x08;                //数据保持时间(DATAST)为9个HCLK
    4 i. K2 H. Y2 W) O- z' U: w7 ]
  54.   FSMC_ReadWriteTim.BusTurnAroundDuration=0X00;+ k/ Z" R1 B* x7 i1 k! {
  55.   FSMC_ReadWriteTim.AccessMode=FSMC_ACCESS_MODE_A;//模式A
    8 K1 w( z9 V$ \' W- x, z+ B3 q
  56.   HAL_SRAM_Init(&SRAM_Handler,&FSMC_ReadWriteTim,&FSMC_ReadWriteTim);        ! E3 O# g5 W4 R1 q9 ^2 d4 ]7 m
  57. }
    % m  Y0 X& {$ `- B( ]- R2 l1 Q
  58. //n向指定地址写数据
    * |% l  G6 c8 Q$ A
  59. void FSMC_SRAM_WriteBuffer(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t n){
    ! ^, l& L0 e) p
  60.   for(;n!=0;n--){        // n表示要连续写入的字节个数. z) @2 e& \3 g9 N9 I% g
  61.     *(vu8*)(Bank1_SRAM3_ADDR + WriteAddr) = *pBuffer;* O# P) @) v6 H
  62.     WriteAddr++;        //要写入的地址
    6 X/ j2 [) }5 ]) Y2 U8 l- u$ r6 }
  63.     pBuffer++;                //要写入的数据的指针0 _' m' Y% G9 e. t( A
  64.   }
    + {8 Y+ }1 x" o5 N+ w
  65. }
    " q# K9 `  L; G- P+ O9 ]5 ~5 w7 A
  66. //从指定地址读数据" q# M0 U. l1 R; g) i0 }9 ~! a3 [- b5 _, a
  67. void FSMC_SRAM_ReadBuffer(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t n){4 o( t* p; t  @& P9 J4 E# P7 `: ~4 b
  68.   for(;n!=0;n--){        // n表示要连续读出的字节个数+ `7 _: W3 k' K' W( h6 a" F, A/ _
  69.     *pBuffer++=*(vu8*)(Bank1_SRAM3_ADDR+ReadAddr);//存放读出的数据1 D3 a. A" {9 }) C) c4 D
  70.     ReadAddr++;                //要读出的起始地址
    & E& F# H# v8 C3 p% }: N
  71.   }+ Y7 i0 n. Z* k0 ^( T" H
  72. }
    9 C! E$ ?0 l; ]" k$ I/ V
  73. //            
    ' e. F  x: O( x+ l
  74. void ExSRAM_Cap_Test(uint16_t x,uint16_t y){3 b  O, `! q: A$ f' L4 a" X. F
  75.   uint8_t writeData = 0xf0, readData;! A) q) h0 q# @3 P8 o& z
  76.   uint16_t cap=0;
    3 C9 f& D) G' ?) U! d1 z
  77.   uint32_t addr;        2 H* q( t) Q& m7 m$ O, _% S1 p
  78.   addr = 1024;         //从1KB位置开始计算       
    4 F% [3 N7 L. Z# l# K3 z
  79.   LCD_ShowString(x,y,239,y+16,16,"ExSRAM Cap:   0KB"); 2 N  R1 n7 m, y) R" g
  80.        
    8 x: K; f2 `* x$ a* K& ?
  81.   while(1){
    % T& `$ `) L8 e2 J
  82.     FSMC_SRAM_WriteBuffer(&writeData, addr, 1);
    & v1 A. K- q/ e. Z& P2 g' B$ Q, F
  83.     FSMC_SRAM_ReadBuffer(&readData,addr,1);# B3 p  A2 F$ [
  84.        
    2 t) f: ^+ }: ~' \' S
  85.     if(readData == writeData){//检查读出的数据是否与写入的数据一样5 Q8 f% i0 B  O/ q
  86.       cap++;                //如果相同表示写入/读出成功,容量加1(单位KB)$ @/ @( _) o9 X
  87.       addr += 1024;        //地址加1024' ]2 M9 T' {6 O# i# k
  88.       readData = 0;+ d: S2 P2 K6 [2 J( N9 b6 k, d0 r
  89.       if(addr > 256 * 1024)//IS62WV12816的容量为256KB
    5 P, ?$ f9 U. H" i
  90.         break;   + k: K1 u) Y8 d) }, T7 R- [: I1 r
  91.     }2 B  z) A; Q/ E  f
  92.     else7 s- }5 e0 H$ J9 u
  93.       break;  
      R# i. |% T4 ?! R6 w& |
  94.   }5 s4 I+ N- z7 H
  95.   LCD_ShowxNum(x+11*8,y,cap,4,16,0);//LCD上显示内存容量. {# R$ w5 ^0 ]' n8 E$ s! L
  96.   printf("SRAM Menmory Size:%dKB\r\n",cap);, l  Z1 x+ k9 b
  97. }
复制代码

  Z, v( ~3 N& U% A6 J+ F' `6 v
➡️ 在main.c文件下编写SRAM测试代码
* s' V, G! k! o0 V1 `4 b. L0 P
  1. int main(void){% F8 w& K9 m: T# h* v
  2.   /* USER CODE BEGIN 1 */; L0 Z" `2 C! J+ M4 ~& p
  3.   uint8_t key;
    5 Z! l' z3 ^" z; R2 G% }. P, W2 @$ b2 H
  4.   uint8_t text_buf[] = "This is SRAM testing...";( e1 h: {6 Y1 `
  5.   uint8_t textlen = sizeof(text_buf);( N8 B; i; t+ M
  6.   uint8_t read_buf[textlen];
    ) D6 W7 _$ @2 i1 o9 F
  7.   /* USER CODE END 1 */
    ' G7 ]& b' I* Y$ P- J8 W$ [5 y
  8.   HAL_Init();5 j9 _/ e: {6 W2 Y7 [" k
  9.   SystemClock_Config();
    6 l2 X3 q. B& S, y! M
  10.   MX_GPIO_Init();+ p$ E4 ^* n; ~7 |( Q' m
  11.   MX_FSMC_Init();. A# }7 q* X0 L' X4 O2 I% r
  12.   MX_USART1_UART_Init();
    / U8 K1 b. A, k$ o4 G  G3 r
  13.   /* USER CODE BEGIN 2 */
    9 f) \( `. Q% b" x' u; N& ^( W
  14.   TFTLCD_Init();
    & \5 C* W  |9 n2 n5 s' ?
  15.   FSMC_SRAM_Init();
    9 ^; P0 Y/ _' d) o* ]( c. K
  16.   FRONT_COLOR=BROWN;
    5 ?4 c6 e) e9 B& _5 e* p) p
  17.   LCD_DrawRectangle(5,5,235,95);( ?; V; b. V7 k  O
  18.   FRONT_COLOR=BLACK;, Z- J: O9 N# d  [. j% x
  19.   LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,16,"ANDYXI STM32F1");
    - N6 r# b/ l3 X% G9 l0 {, P- t( I
  20.   LCD_ShowString(10,30,tftlcd_data.width,tftlcd_data.height,16,"STM32CubeMx SRAM");
    5 x% M) Q/ ^' I! T8 u5 Y7 i  Y, i
  21.   LCD_ShowString(10,50,tftlcd_data.width,tftlcd_data.height,16,"ExSRAM Test");) s- h1 ~, w$ c1 X; n
  22.   LCD_ShowString(10,70,tftlcd_data.width,tftlcd_data.height,16,"K_UP:Write   K_DOWN:Read");       
    1 |+ a/ L* i1 D; Y3 e3 O/ i
  23.   FRONT_COLOR=RED;% a# @9 ]6 U! L- C0 w7 `
  24.   ExSRAM_Cap_Test(10,110);
    , G& @+ y! G/ e$ ?9 n
  25.   FRONT_COLOR=MAGENTA;$ _& G$ U; x* A, p
  26.   LCD_ShowString(10,130,tftlcd_data.width,tftlcd_data.height,16,"Write:");
    - q& j& ^+ K: l) L$ O1 G
  27.   LCD_ShowString(10,150,tftlcd_data.width,tftlcd_data.height,16,"Read :");
    2 R2 h, f/ h" O; _! |1 p* x- T/ }7 k
  28.   /* USER CODE END 2 */
    ' ~: I1 q8 S3 w. Z- J+ a1 S& U: m( v
  29.   /* Infinite loop */% |8 a" ~0 R" V5 |" j1 P& ^' u
  30.   /* USER CODE BEGIN WHILE */
    7 z  h; B7 K0 e2 [* M! ?( g8 R4 O# z
  31.   while(1){: i% ?% a6 G7 P. ^3 j7 q- O9 i
  32.     key = KEY_Scan(0);/ u* b- D6 ]+ D
  33.     if(key == KEY_UP_PRES){        //KEY_UP按下写数据到SRAM) X0 t! |& ?4 M; o$ e  ^% S1 D
  34.       FSMC_SRAM_WriteBuffer(text_buf,0,textlen);$ J! q0 x8 {8 q8 N7 {; D: k; s
  35.       printf("SRAM_Write:%s\r\n",text_buf);
    " ?* x# a1 R$ W. K7 J4 p# A/ i
  36.       LCD_ShowString(10+6*8,130,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)text_buf);
    ' p* M  K9 M2 U8 ?+ }; a
  37.     }
    0 l+ K; D7 F7 X# `
  38.     if(key == KEY_DOWN_PRES){        //KEY_DOWN按下从SRAM读出数据
    " J5 ?$ c# `9 q" q& q, O0 B5 K
  39.       FSMC_SRAM_ReadBuffer(read_buf,0,textlen);+ S/ U2 |8 G9 _6 l" i
  40.       printf("SRAM_Read:%s\r\n",read_buf);) x! _2 u/ q, D& Y- n8 k
  41.       LCD_ShowString(10+6*8,150,tftlcd_data.width,tftlcd_data.height,16,read_buf);5 l5 o; G, F; _
  42.     }               
    # _" H" ?$ [$ b' k7 C
  43.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);/ h, {4 [2 ~- |2 _
  44.     HAL_Delay(200);, Y  x. z. M; q5 w: g  z  {$ u4 C
  45.   }
    , o$ ]$ z3 \- j  B. l4 f' H
  46. }
复制代码

- w& R% \8 F: G) N9 }) t5 I
4.下载验证
( p# S- o$ u+ B3 @/ f# _% n3 t# {' E
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,KEY_UP按下写数据到SRAM,KEY_DOWN按下从SRAM读出数据,并将写入和读出的数据显示在LCD屏上,并通过串口1打印出来
微信图片_20230628153134.png

# ^  F7 `. {: ]$ q; w3 t
转载自: 嵌入式攻城狮
如有侵权请联系删除& `9 m9 b! X$ A5 _; l

/ |/ M( B; F  g# @' i3 n
收藏 评论0 发布时间:2023-6-28 15:32

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版