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

基于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的引脚以及对应的引脚功能如下图示:
! v% Y& z0 L$ A$ o' t" T
微信图片_20230628153158.png

! m" l1 Q) ?, b
A0 ~ A16为地址线,总共17根地址线(可访问2^17 = 128K字节空间);I/O0 ~ I/O15为数据线,总共16根数据线;CS1(低电平有效)和CS2(高电平有效)都是片选信号;WE为输入使能信号(写信号);OE为输出使能信号(读信号);UB和LB分别是高字节和低字节控制信号

" ]4 l) h$ }* H! b

4 @2 l, Z8 U6 Y' w1 D$ a
2.硬件设计
D1指示灯用来提示系统运行状态,按键用来控制IS62WV12816数据读写,TFTLCD和串口1用来显示读写的内容
    . ]  z# h  a$ F
  • D1指示灯
  • K_UP/K_DOWN按键
    , y3 Y" p  Q1 c7 F- I3 R
  • USART1串口
  • TFTLCD
    , T9 m/ c/ Z* s6 ^, j  [
  • IS62WV12816
    2 S! J! B  u$ S! R% V6 H! e
    ! _9 q' ^3 q' r' \/ e0 [- F" u6 g0 r
从电路图中可以看到IS62WV12816和STM32F1的连接线路:
0 y" M+ K' {1 I6 C, l2 ]A0 ~ A16连接在FSMC_A0 ~ FSMC_A16上(连接顺序可以打乱,因为地址是固定的)
! h; Q  V8 T8 Y% J# r0 xI/O0 ~ I/O15连接在FSMC_D0 ~ FSMC_D15上(连接顺序不能打乱,否则读写数据将出错)2 t* t( v) P# U% y3 ^1 Z
UB和LB连接在FSMC_NBL1 和 FSMC_NBL0上, {& P5 ~4 `2 L( g2 _( ~1 s* M1 d
OE和WE分别连接在FSMC_NOE 和 FSMC_NWE上
! X! B0 J6 F2 sCE连接在FSMC_NE3上

/ I$ X( \+ w- ~- Z# e% F
微信图片_20230628153150.png

2 C8 s$ P2 U& u4 @" s) C

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


+ P2 \- g' k; H/ ?  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,生成工程代码

" z7 T: t( R9 n' S5 e' ^1 f

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

8 h5 M  `; n) h/ i/ r& Z" a

微信图片_20230628153141.png

( H! X0 P0 {* e! b7 t+ _( {
3.2 MDK-ARM软件编程
➡️ 创建按键驱动文件key.c和key.h,参考按键输入例程
➡️ 创建LCD驱动文件tftlcd.c 和tftlcd.h,参考TFTLCD显示例程
➡️ 创建IS62WV12816芯片驱动文件sram.c和sram.h

, P4 i# O: o& Q1 F+ ^
  1. #define Bank1_SRAM3_ADDR    ((uint32_t)(0x68000000))//Bank1区域3的起始地址        : _/ h5 q% {; d3 U
  2. SRAM_HandleTypeDef SRAM_Handler;//定义SRAM句柄, }& j* B" G" O8 ?/ N9 }
  3. //SRAM的FSMC初始化函数
    5 u. E7 u* s* o" f
  4. void FSMC_SRAM_Init(void){        - T" O8 I3 o9 ]5 P  z5 V+ s4 a# e
  5.   GPIO_InitTypeDef GPIO_InitStruct;
    / \1 f9 F7 }- D, K8 N1 Q  d6 L' l
  6.   FSMC_NORSRAM_TimingTypeDef FSMC_ReadWriteTim;
    ( p) m( P8 w$ Y6 j# V
  7.   __HAL_RCC_FSMC_CLK_ENABLE();           6 P8 U1 r0 j, I1 Y1 j
  8.   __HAL_RCC_GPIOD_CLK_ENABLE();              
      S  T9 }3 A, Z3 E- @4 q; C$ r
  9.   __HAL_RCC_GPIOE_CLK_ENABLE();               
    0 G6 a+ c3 D; R- ^
  10.   __HAL_RCC_GPIOF_CLK_ENABLE();              ' A: H6 t) _3 x7 U+ n$ O% X( }
  11.   __HAL_RCC_GPIOG_CLK_ENABLE();               5 ^6 d: @# d" y3 T6 h  c+ p& t8 c3 Y
  12.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
    ' a, J! ]' w0 b5 B3 Q3 a: M
  13.                      |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13 * x& b% T7 K3 J2 J4 p) D3 G2 d, {
  14.                      |GPIO_PIN_14|GPIO_PIN_15;
    4 j' ^2 F, }* P+ i  @" \
  15.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;. e* \0 s# P/ S0 e
  16.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;8 o# e5 x3 c, R
  17.   HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
    * G5 E2 ~* V9 M5 }! K4 A) _
  18.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 9 [. |/ S7 X* Y# s6 O2 s
  19.                      |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_10;
    # P* ]5 d. B8 i5 [2 N- A
  20.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;3 E' v' \3 B# O( u
  21.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    0 z% a* s$ y. J3 S$ k
  22.   HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);  o# `2 e( g) f0 P
  23.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 $ l$ u  L9 U+ c/ g& K: c( |! d
  24.                      |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 " a* L9 |# M9 q8 G
  25.                      |GPIO_PIN_15;% b/ _+ b- I$ a7 K4 N3 Q& h! H1 |2 ~
  26.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    5 e  l+ g! r9 U
  27.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;# J) Z( o$ E- [6 E3 V" u1 T
  28.   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);2 X8 W8 {* Z6 ]! z5 \
  29.   GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 " K" a" J/ g5 \. y( n- W# `
  30.                      |GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1 & h% F3 \4 e; j9 v8 l: {
  31.                      |GPIO_PIN_4|GPIO_PIN_5;. v8 `! j& [7 E( u. N
  32.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;/ h0 j9 {! Y9 H9 i/ W
  33.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;" v% M% S! W$ |3 D# K- c9 a% R
  34.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);  6 [* g; p8 b- X8 H6 o
  35.         9 ]. s9 ]. ~+ m/ ~  U# O8 g5 S
  36.   SRAM_Handler.Instance=FSMC_NORSRAM_DEVICE;               
    % g7 ]2 o5 t" U; j+ I
  37.   SRAM_Handler.Extended=FSMC_NORSRAM_EXTENDED_DEVICE;     # P1 J/ f) G8 f+ ?- n* d) g
  38.   SRAM_Handler.Init.NSBank=FSMC_NORSRAM_BANK3;        //使用NE3
    * r! d3 D% e7 C
  39.   SRAM_Handler.Init.DataAddressMux=FSMC_DATA_ADDRESS_MUX_DISABLE;//地址/数据线不复用
    3 p' E# r' u' [
  40.   SRAM_Handler.Init.MemoryType=FSMC_MEMORY_TYPE_SRAM;            //SRAM
    0 z+ R0 A5 p/ U
  41.   SRAM_Handler.Init.MemoryDataWidth=FSMC_NORSRAM_MEM_BUS_WIDTH_16;//16位数据宽度
    " c9 i/ _6 }) _  X8 m$ j( C
  42.   SRAM_Handler.Init.BurstAccessMode=FSMC_BURST_ACCESS_MODE_DISABLE;//不使能突发访问" l( C6 I2 M! z3 B2 \* j% J2 t/ ^
  43.   SRAM_Handler.Init.WaitSignalPolarity=FSMC_WAIT_SIGNAL_POLARITY_LOW;//等待信号的极性(突发模式)* t6 F5 P0 J1 c( k6 e# G
  44.   SRAM_Handler.Init.WaitSignalActive=FSMC_WAIT_TIMING_BEFORE_WS;           + |: \" d) \( G% U6 ]
  45.   SRAM_Handler.Init.WriteOperation=FSMC_WRITE_OPERATION_ENABLE;    //写使能. A1 D% n9 c% n- d/ h: E
  46.   SRAM_Handler.Init.WaitSignal=FSMC_WAIT_SIGNAL_DISABLE;         
    " c9 B* W9 U/ }, [
  47.   SRAM_Handler.Init.ExtendedMode=FSMC_EXTENDED_MODE_DISABLE;       //读写使用相同的时序
    0 K/ ]' S* x- a, f% G+ R; b
  48.   SRAM_Handler.Init.AsynchronousWait=FSMC_ASYNCHRONOUS_WAIT_DISABLE;
    . [; j" E- Z( c3 e
  49.   SRAM_Handler.Init.WriteBurst=FSMC_WRITE_BURST_DISABLE;           //禁止突发写9 f& D* Y, L) `1 a- @
  50.   //FSMC读时序控制器! T) J0 R/ B; S3 g  C5 h$ i
  51.   FSMC_ReadWriteTim.AddressSetupTime=0x00;      //地址建立时间(ADDSET)为1个HCLK& @8 y) H1 G0 T. ^# @" K* C
  52.   FSMC_ReadWriteTim.AddressHoldTime=0x00;        //地址保持时间(ADDHLD)模式A未用到
    % w7 O# J, R; r3 W) T# j
  53.   FSMC_ReadWriteTim.DataSetupTime=0x08;                //数据保持时间(DATAST)为9个HCLK
    0 d# G; y. n: U( K! {1 H3 U) A
  54.   FSMC_ReadWriteTim.BusTurnAroundDuration=0X00;
    / q1 t+ u  d" l$ y* P  _9 `; |% x
  55.   FSMC_ReadWriteTim.AccessMode=FSMC_ACCESS_MODE_A;//模式A
    & U  B( b" p. A
  56.   HAL_SRAM_Init(&SRAM_Handler,&FSMC_ReadWriteTim,&FSMC_ReadWriteTim);        & |* N# S: O9 J/ \+ p, p; U
  57. }
    " A3 @8 {7 {( j$ R8 h" i
  58. //n向指定地址写数据
    2 V1 j+ j) _( a, a" m2 \& c
  59. void FSMC_SRAM_WriteBuffer(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t n){
    ( Q) u: f0 m1 z5 A
  60.   for(;n!=0;n--){        // n表示要连续写入的字节个数
    % t/ p1 i' W; q- o  g
  61.     *(vu8*)(Bank1_SRAM3_ADDR + WriteAddr) = *pBuffer;) W/ g) q4 N) ^8 D6 g- W: K
  62.     WriteAddr++;        //要写入的地址
    7 V; F1 Z5 H3 ^) X  }/ _* U0 H7 d
  63.     pBuffer++;                //要写入的数据的指针
    # j' J1 A, K  S
  64.   }
    * Z9 E/ ]! k) Q  I- r
  65. }, X+ h5 X* w, `
  66. //从指定地址读数据
    4 k; _+ W! ]# H. x9 w$ j+ ?! ?
  67. void FSMC_SRAM_ReadBuffer(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t n){
    8 B% e+ k# T% K9 q
  68.   for(;n!=0;n--){        // n表示要连续读出的字节个数
    : r# S' Z4 _2 f) `+ I8 c: ]& q: Z# }
  69.     *pBuffer++=*(vu8*)(Bank1_SRAM3_ADDR+ReadAddr);//存放读出的数据
    2 r3 m7 V/ i+ G* A* W
  70.     ReadAddr++;                //要读出的起始地址
    ' E  }& s0 P# U' X$ K7 ?8 o
  71.   }* }9 f8 i# f1 N. D* Y5 g
  72. }
    , f5 V, P6 Q0 I
  73. //            6 [5 t" y7 [  L6 [4 b  ~
  74. void ExSRAM_Cap_Test(uint16_t x,uint16_t y){& f, N% K' ?( x& J3 p7 p/ s4 U' `0 T, X
  75.   uint8_t writeData = 0xf0, readData;
    1 t% u+ }. j0 M2 h: l: {" _& Y& I  q
  76.   uint16_t cap=0;' L' E+ f8 O1 M/ V: I4 R# J7 h
  77.   uint32_t addr;        . d. i$ i% V. b' ]* C1 d; N  p/ P
  78.   addr = 1024;         //从1KB位置开始计算       
    % k/ Z. d/ Q7 @+ V
  79.   LCD_ShowString(x,y,239,y+16,16,"ExSRAM Cap:   0KB");
    + K8 \! r; ]  C+ F; D& P" P  Y
  80.         + v% @+ `: k9 Z
  81.   while(1){& Y2 l! p* L8 C5 v2 I
  82.     FSMC_SRAM_WriteBuffer(&writeData, addr, 1);
    * p4 d) m, {; F& `9 ~9 F2 R
  83.     FSMC_SRAM_ReadBuffer(&readData,addr,1);3 Y* E% J; _- F2 T$ U: [
  84.         3 [! w! {; V- I
  85.     if(readData == writeData){//检查读出的数据是否与写入的数据一样
    5 o8 L1 S( y8 Z  I2 |* `/ O& o& v" y
  86.       cap++;                //如果相同表示写入/读出成功,容量加1(单位KB)3 a/ O" r: q8 H- n& y
  87.       addr += 1024;        //地址加1024
    . s: D  y7 I/ ?# ~+ ~+ A: S
  88.       readData = 0;; A; a8 w% g% A% T( Q# m
  89.       if(addr > 256 * 1024)//IS62WV12816的容量为256KB
    $ N7 t: ]3 s( i! k
  90.         break;   
    , p: Q& D/ i* e" [
  91.     }
    . s# D0 ?+ _' q0 q5 u/ Y
  92.     else* l$ v& }( I: Z  R( \, b
  93.       break;  7 D0 K  z7 y$ N" _% w. R3 M" F. }) P
  94.   }
    9 s+ [( I" O9 ^  m$ U. f
  95.   LCD_ShowxNum(x+11*8,y,cap,4,16,0);//LCD上显示内存容量, V! r6 s3 S! ~  e9 @3 t  L
  96.   printf("SRAM Menmory Size:%dKB\r\n",cap);
    - {5 g( y: {' G$ t' t
  97. }
复制代码
! v) {! U" H# R) q
➡️ 在main.c文件下编写SRAM测试代码
% C9 F# u, J0 P& C) \" S5 `
  1. int main(void){
    8 H6 r* L; j$ I6 A# @
  2.   /* USER CODE BEGIN 1 */
    / q+ |5 n! V4 k* w: V
  3.   uint8_t key;
    . G' H4 w* ?  T
  4.   uint8_t text_buf[] = "This is SRAM testing...";
    " ?8 B5 x6 o, n" q6 x( V' M
  5.   uint8_t textlen = sizeof(text_buf);
    - R% k; X' h/ D# P
  6.   uint8_t read_buf[textlen];6 p/ _% A5 ?. y; Q1 I
  7.   /* USER CODE END 1 */
    3 x% l* T! K# p8 v! C- |3 g4 R, U- I% |
  8.   HAL_Init();2 h4 V9 j, f8 L2 A% a% G
  9.   SystemClock_Config();
    ! `- X+ l/ c! n* F! x5 O- e0 I" n
  10.   MX_GPIO_Init();& K  c/ f+ j/ s  w- V4 L
  11.   MX_FSMC_Init();
    $ Q9 l) s) ?" {- o( o
  12.   MX_USART1_UART_Init();
    0 E/ X- R0 Z: I" e' s. s' ^
  13.   /* USER CODE BEGIN 2 */# I5 p( K7 X1 n( S" ~; L
  14.   TFTLCD_Init();' A8 _5 H6 j( ^+ O) J6 M' [
  15.   FSMC_SRAM_Init();
    , q7 h& ?8 J' j; v- C# W6 g$ o
  16.   FRONT_COLOR=BROWN;
    * P$ u1 t6 I: Q% w8 Q6 I9 }
  17.   LCD_DrawRectangle(5,5,235,95);
    : F" ~' @; k1 q0 {: {. u7 Q4 @  O
  18.   FRONT_COLOR=BLACK;
    ' J5 D1 u. L' Q' s, V
  19.   LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,16,"ANDYXI STM32F1");
    % B/ H% ]& f& d
  20.   LCD_ShowString(10,30,tftlcd_data.width,tftlcd_data.height,16,"STM32CubeMx SRAM");
    ; ^1 v0 L: Q! C9 _+ a& l
  21.   LCD_ShowString(10,50,tftlcd_data.width,tftlcd_data.height,16,"ExSRAM Test");
    0 X5 E9 R; U/ R; I* t9 ~9 H
  22.   LCD_ShowString(10,70,tftlcd_data.width,tftlcd_data.height,16,"K_UP:Write   K_DOWN:Read");        ) d6 n4 H1 t* j
  23.   FRONT_COLOR=RED;5 X2 n& }4 g' V  Y. M5 X
  24.   ExSRAM_Cap_Test(10,110);
      |' Q# E9 A- B1 j* B( H
  25.   FRONT_COLOR=MAGENTA;
    7 x" Y0 s" r' Y
  26.   LCD_ShowString(10,130,tftlcd_data.width,tftlcd_data.height,16,"Write:");% g5 o- K, ~' ]0 G
  27.   LCD_ShowString(10,150,tftlcd_data.width,tftlcd_data.height,16,"Read :");: o" D0 a* [, m# k' p. J
  28.   /* USER CODE END 2 */2 @1 T" p& {" z
  29.   /* Infinite loop */
    ' d# X! h2 q5 I
  30.   /* USER CODE BEGIN WHILE */
    " |- V7 Y& A5 R! J! l. t3 @
  31.   while(1){
    6 b& s" K* e1 b4 s* T. @0 ]( K
  32.     key = KEY_Scan(0);
    1 u" d: X1 w) y7 t( G
  33.     if(key == KEY_UP_PRES){        //KEY_UP按下写数据到SRAM: p2 d. Q6 Y$ S% s  W( X. q1 r
  34.       FSMC_SRAM_WriteBuffer(text_buf,0,textlen);
    9 V$ y8 n9 z/ R0 P: l
  35.       printf("SRAM_Write:%s\r\n",text_buf);# Q5 |3 o) a7 f4 Y
  36.       LCD_ShowString(10+6*8,130,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)text_buf);
    8 b* d% i* i# y0 k  x  E
  37.     }
    + }; A8 ?5 v* S# h$ ?
  38.     if(key == KEY_DOWN_PRES){        //KEY_DOWN按下从SRAM读出数据
    1 M" n2 V: z! Z/ Q% q2 S6 r
  39.       FSMC_SRAM_ReadBuffer(read_buf,0,textlen);
    " [! o4 o# r  f) ?* W
  40.       printf("SRAM_Read:%s\r\n",read_buf);
    * C6 t, }1 ^& z6 D) Q! j
  41.       LCD_ShowString(10+6*8,150,tftlcd_data.width,tftlcd_data.height,16,read_buf);$ K1 }6 o0 ]6 d! t. F
  42.     }                6 U+ m0 Q& H9 f
  43.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
    # J, f; R1 I& _% A0 Q; Q; c
  44.     HAL_Delay(200);4 r& I, m2 L) v% }- ^, i, s
  45.   }% b  c2 S+ ^: p: x* a
  46. }
复制代码
) F% w& e% M3 F, \: k4 t* L* w
4.下载验证
- M# }1 Z; H% N3 S% H: O& j
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,KEY_UP按下写数据到SRAM,KEY_DOWN按下从SRAM读出数据,并将写入和读出的数据显示在LCD屏上,并通过串口1打印出来
微信图片_20230628153134.png
/ _2 m# @6 v: I: c9 x
转载自: 嵌入式攻城狮
如有侵权请联系删除
% `* `8 A" {+ `" E# q8 n

( a, }2 N$ W4 G7 ^, S/ @
收藏 评论0 发布时间:2023-6-28 15:32

举报

0个回答

所属标签

相似分享

官网相关资源

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