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

基于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的引脚以及对应的引脚功能如下图示:

! X; s/ d: f- i3 W5 ~! f
微信图片_20230628153158.png

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

3 |# {6 _3 t+ J# L; t7 F1 b
8 ~5 R& N- V1 L& M
2.硬件设计
D1指示灯用来提示系统运行状态,按键用来控制IS62WV12816数据读写,TFTLCD和串口1用来显示读写的内容

    2 G! M5 `% v8 z0 i0 |2 d  \; d
  • D1指示灯
  • K_UP/K_DOWN按键9 ^4 ^5 t3 j" E6 L; p4 L; B
  • USART1串口
  • TFTLCD

    , y. E  c6 N3 o, }; p1 I/ P! n9 ~* T
  • IS62WV12816
    5 N# h( H; A5 B, G: S! F* K

      w5 l  E" G0 ^+ c
从电路图中可以看到IS62WV12816和STM32F1的连接线路:! O: A3 k$ \" U# p4 F" m
A0 ~ A16连接在FSMC_A0 ~ FSMC_A16上(连接顺序可以打乱,因为地址是固定的)
/ W9 j7 a4 a" g" |- xI/O0 ~ I/O15连接在FSMC_D0 ~ FSMC_D15上(连接顺序不能打乱,否则读写数据将出错)+ s& M% f2 B/ \; D4 Z/ b
UB和LB连接在FSMC_NBL1 和 FSMC_NBL0上
% z+ M# \  Z: \, S9 BOE和WE分别连接在FSMC_NOE 和 FSMC_NWE上
# j7 W3 `6 Q' T4 x# t; ^; Y0 p4 ^CE连接在FSMC_NE3上

; r# |: m6 A3 p, v
微信图片_20230628153150.png
" d4 g8 O4 `5 F9 G

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

* _& d2 t4 d; s6 w9 x# j* 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,生成工程代码
5 _' d: u* S/ T. {" G0 S# m* ]1 Z: V

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


1 A* ~1 q" n0 U  b( P# S8 W+ Y# U

微信图片_20230628153141.png

0 _5 _$ x: ^: ]* P5 m
3.2 MDK-ARM软件编程
➡️ 创建按键驱动文件key.c和key.h,参考按键输入例程
➡️ 创建LCD驱动文件tftlcd.c 和tftlcd.h,参考TFTLCD显示例程
➡️ 创建IS62WV12816芯片驱动文件sram.c和sram.h
' @; ~1 d; ~/ e  V* T. {- u& L
  1. #define Bank1_SRAM3_ADDR    ((uint32_t)(0x68000000))//Bank1区域3的起始地址        0 a5 C0 F  m: J5 J* V
  2. SRAM_HandleTypeDef SRAM_Handler;//定义SRAM句柄/ D( \  t2 o- v7 N" c1 ]
  3. //SRAM的FSMC初始化函数
    $ u+ Z) D6 Z, j* ]8 x; z! F2 x# g
  4. void FSMC_SRAM_Init(void){       
    ; g2 V4 U3 H3 F
  5.   GPIO_InitTypeDef GPIO_InitStruct;* h7 U9 i* D6 U9 N8 }
  6.   FSMC_NORSRAM_TimingTypeDef FSMC_ReadWriteTim; 1 }( M! m* u& D8 c: E
  7.   __HAL_RCC_FSMC_CLK_ENABLE();           
    ' Y+ L. ?/ v/ T+ U; q: C
  8.   __HAL_RCC_GPIOD_CLK_ENABLE();              
    $ M* \* [1 n, I! Y0 B
  9.   __HAL_RCC_GPIOE_CLK_ENABLE();               
    # y  T8 T# ?: J$ E% e" `) F9 |
  10.   __HAL_RCC_GPIOF_CLK_ENABLE();              
    . k! e2 o0 F; L
  11.   __HAL_RCC_GPIOG_CLK_ENABLE();               
    " R# w! N2 K! x+ w
  12.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 3 \0 x0 g: m5 A) l( c3 @! L
  13.                      |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13
      g, f' g. o$ a. O, @! l
  14.                      |GPIO_PIN_14|GPIO_PIN_15;
    " a# N7 Y' m2 Y: V" w
  15.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;; o* }( X$ A8 y3 }! A' L8 F4 m
  16.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;8 u7 T# G. W2 N2 B* G; k1 \
  17.   HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
    + }  L6 r; s: a% d. ~
  18.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 $ G9 U. K1 ?: O2 S* z/ k
  19.                      |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_10;* z- N/ Y. b3 w' o. ?; m+ c: O
  20.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;* w; h! e5 N# P" n4 A5 ?' l
  21.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
      Z6 ], z7 U1 A& z; h( g( D+ U
  22.   HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
    # F% Z7 i' K( l
  23.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
    & v+ [8 g8 b6 l' X0 i* _
  24.                      |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
    5 A" k! D, K. ~
  25.                      |GPIO_PIN_15;
      P8 T# M$ j5 `& ^. h8 F
  26.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;. Q1 `: G% r- n# p% o
  27.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    4 }5 ^* P$ |' H4 \* C5 b: c0 T0 k/ L
  28.   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    * X; M( l1 m: B1 W5 M
  29.   GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
    6 L" J7 e8 N1 F
  30.                      |GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1 ( I# }+ p- O9 K( W
  31.                      |GPIO_PIN_4|GPIO_PIN_5;9 h* Z# I% v' R: G
  32.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;- Z9 K# \0 Y: x: B5 R) X* |0 R
  33.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;. ~( p2 z5 w: o
  34.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);  
    ' x) L; L, I9 e: I+ z
  35.         ( F. a' t. H8 f
  36.   SRAM_Handler.Instance=FSMC_NORSRAM_DEVICE;               
    8 Q0 G9 i' O5 V" a& I# k
  37.   SRAM_Handler.Extended=FSMC_NORSRAM_EXTENDED_DEVICE;     ' ?* m; l4 x3 x: g3 V5 N
  38.   SRAM_Handler.Init.NSBank=FSMC_NORSRAM_BANK3;        //使用NE34 e0 f% R) U& q7 q8 a4 o" P# n: T
  39.   SRAM_Handler.Init.DataAddressMux=FSMC_DATA_ADDRESS_MUX_DISABLE;//地址/数据线不复用
    8 h/ |$ P. z) c5 X  J
  40.   SRAM_Handler.Init.MemoryType=FSMC_MEMORY_TYPE_SRAM;            //SRAM
    : {3 Y$ a  C$ V( N
  41.   SRAM_Handler.Init.MemoryDataWidth=FSMC_NORSRAM_MEM_BUS_WIDTH_16;//16位数据宽度
      `2 B' a4 o0 H6 V% ]
  42.   SRAM_Handler.Init.BurstAccessMode=FSMC_BURST_ACCESS_MODE_DISABLE;//不使能突发访问
    * T- [5 @+ w; g5 x
  43.   SRAM_Handler.Init.WaitSignalPolarity=FSMC_WAIT_SIGNAL_POLARITY_LOW;//等待信号的极性(突发模式)8 f3 |4 \/ X$ S7 t$ M2 N
  44.   SRAM_Handler.Init.WaitSignalActive=FSMC_WAIT_TIMING_BEFORE_WS;           4 o/ H/ D4 |! A+ {, B5 \9 Z
  45.   SRAM_Handler.Init.WriteOperation=FSMC_WRITE_OPERATION_ENABLE;    //写使能' t" v+ i5 \; e* Q' |2 K0 @! D; b
  46.   SRAM_Handler.Init.WaitSignal=FSMC_WAIT_SIGNAL_DISABLE;          ; g! ?( p: `  j7 s* L
  47.   SRAM_Handler.Init.ExtendedMode=FSMC_EXTENDED_MODE_DISABLE;       //读写使用相同的时序  X. t( b& [4 g1 T+ y' y+ Q; t6 `
  48.   SRAM_Handler.Init.AsynchronousWait=FSMC_ASYNCHRONOUS_WAIT_DISABLE;5 b6 K' g, j4 p7 }" `+ {
  49.   SRAM_Handler.Init.WriteBurst=FSMC_WRITE_BURST_DISABLE;           //禁止突发写
    1 q# s+ \& @6 D, B7 M0 O
  50.   //FSMC读时序控制器
    - e( O6 z4 Y: f7 @1 f$ m: _! w7 |7 B- w
  51.   FSMC_ReadWriteTim.AddressSetupTime=0x00;      //地址建立时间(ADDSET)为1个HCLK
    * H# o% \7 Q3 e' B
  52.   FSMC_ReadWriteTim.AddressHoldTime=0x00;        //地址保持时间(ADDHLD)模式A未用到
    $ J" m) {3 V: ?9 J( ]" z3 o" ]$ A
  53.   FSMC_ReadWriteTim.DataSetupTime=0x08;                //数据保持时间(DATAST)为9个HCLK0 H/ W9 D1 w+ O  `: H
  54.   FSMC_ReadWriteTim.BusTurnAroundDuration=0X00;
    " @" J" z, b+ [% c" m
  55.   FSMC_ReadWriteTim.AccessMode=FSMC_ACCESS_MODE_A;//模式A
    3 \/ E$ z1 R/ w5 |* W
  56.   HAL_SRAM_Init(&SRAM_Handler,&FSMC_ReadWriteTim,&FSMC_ReadWriteTim);       
    6 j, g" [6 j  G* U
  57. }
    , G" [) d* w/ Y1 F5 o+ N) e, i
  58. //n向指定地址写数据
    5 O& }% E. A+ W% g
  59. void FSMC_SRAM_WriteBuffer(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t n){
    5 _( v" b) e1 ^& N0 P3 p
  60.   for(;n!=0;n--){        // n表示要连续写入的字节个数) l# G1 @$ M1 }5 U- n3 w
  61.     *(vu8*)(Bank1_SRAM3_ADDR + WriteAddr) = *pBuffer;
    8 s) D3 V) w7 j2 P0 m, j/ S6 k' f# d
  62.     WriteAddr++;        //要写入的地址
    & ^7 t! p* U, t3 w% @" o( ?7 U
  63.     pBuffer++;                //要写入的数据的指针- d, _* q$ E% ~( y
  64.   }
    ' {& S' R' v; s% r
  65. }
    / b* R7 ?( A4 p! i, T1 F
  66. //从指定地址读数据0 N/ J* @9 _/ F
  67. void FSMC_SRAM_ReadBuffer(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t n){; O# Z  d5 ^& m, h8 g5 a' O) E; R
  68.   for(;n!=0;n--){        // n表示要连续读出的字节个数
    7 _4 |: Y; u  D  G. Y. o) a5 Q
  69.     *pBuffer++=*(vu8*)(Bank1_SRAM3_ADDR+ReadAddr);//存放读出的数据- Z& p. G; w# X. O  {
  70.     ReadAddr++;                //要读出的起始地址
    8 i" C1 v6 P8 @& c
  71.   }
    0 }& N- s3 o( a5 P/ t
  72. }# G. P2 p& @( Q% a0 f6 {
  73. //            4 \8 }; w, N2 {9 J
  74. void ExSRAM_Cap_Test(uint16_t x,uint16_t y){$ c. S: h, h  ?0 ]" e  d6 z
  75.   uint8_t writeData = 0xf0, readData;5 I; z$ Q& i8 |- `0 ^4 Z) c
  76.   uint16_t cap=0;
    / O1 B9 b* b+ p" n0 Q; k
  77.   uint32_t addr;        % C& J4 S" m/ X
  78.   addr = 1024;         //从1KB位置开始计算        3 V/ @  q# y2 m# ]1 n
  79.   LCD_ShowString(x,y,239,y+16,16,"ExSRAM Cap:   0KB");
    * k6 l1 ^5 O" D; T
  80.         ) P5 B" f6 Q- z! P$ l9 x
  81.   while(1){
    7 b1 L* T' ~. w
  82.     FSMC_SRAM_WriteBuffer(&writeData, addr, 1);
    3 C# ]- `# Q' \# k
  83.     FSMC_SRAM_ReadBuffer(&readData,addr,1);% A' m9 ?) L0 G7 W, z, R
  84.         # ?9 A; Q  n: V+ m
  85.     if(readData == writeData){//检查读出的数据是否与写入的数据一样
    - r, @# j6 v* D& h- X2 a
  86.       cap++;                //如果相同表示写入/读出成功,容量加1(单位KB)
    . R5 H7 c+ m, R9 M' ?
  87.       addr += 1024;        //地址加1024! ]" ^6 L: A- J. c2 r
  88.       readData = 0;
    7 P- A- h. d6 A8 w6 L9 M) d
  89.       if(addr > 256 * 1024)//IS62WV12816的容量为256KB
    % p$ ~) h- ?( l# Y
  90.         break;   
    - K9 Y; o4 o# I: q* O/ M
  91.     }" i7 b7 n8 F3 t, \- ?2 P8 W" B
  92.     else) L( s/ u$ t( |
  93.       break;  5 |; ~& `, o& H
  94.   }7 d/ k+ C! j$ Q
  95.   LCD_ShowxNum(x+11*8,y,cap,4,16,0);//LCD上显示内存容量+ W# p, ^2 }* y8 O) U3 q
  96.   printf("SRAM Menmory Size:%dKB\r\n",cap);2 A+ }! Z. h3 e# ~! P+ s
  97. }
复制代码

- g" @+ T+ z  D& f2 T) U* O
➡️ 在main.c文件下编写SRAM测试代码
" u0 H6 {0 y9 l( w; W7 t
  1. int main(void){: M/ T1 i# M) r* ~
  2.   /* USER CODE BEGIN 1 */- T4 ~; P5 s2 M5 x
  3.   uint8_t key;
    * Z  {: c- O' [
  4.   uint8_t text_buf[] = "This is SRAM testing...";# b* F' s* l5 I  h2 T+ }8 a# [
  5.   uint8_t textlen = sizeof(text_buf);: e  v9 t% B' }
  6.   uint8_t read_buf[textlen];
    5 f! D3 m+ O+ X! a- R; b4 U
  7.   /* USER CODE END 1 */7 D  a6 r# x: o$ j* |3 w. j" C
  8.   HAL_Init();
    . N5 b# E* q/ e
  9.   SystemClock_Config();
    5 K: J9 |5 u5 Z7 N: x! t
  10.   MX_GPIO_Init();1 g( G! F+ _( [2 m' G2 _9 D$ t
  11.   MX_FSMC_Init();
    + G! B& P) w- t, S+ w: ~6 {. g- Y
  12.   MX_USART1_UART_Init();
    2 @& A% W; }0 d# p
  13.   /* USER CODE BEGIN 2 */$ w7 M$ _1 @. K; [0 \; a1 ^' I
  14.   TFTLCD_Init();
    6 g4 o' l7 U% y
  15.   FSMC_SRAM_Init();% O3 w5 F* U# p
  16.   FRONT_COLOR=BROWN;9 z4 d' A. _& E! I& b
  17.   LCD_DrawRectangle(5,5,235,95);
    / i# ~. i- f. B& g/ N" d/ X2 J
  18.   FRONT_COLOR=BLACK;) m9 p4 m8 O% T9 l, W
  19.   LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,16,"ANDYXI STM32F1");) z( s8 d/ r3 {1 Q6 X$ ?- w! A, c
  20.   LCD_ShowString(10,30,tftlcd_data.width,tftlcd_data.height,16,"STM32CubeMx SRAM");
    . d) E8 F5 ^: y8 Y) I8 @
  21.   LCD_ShowString(10,50,tftlcd_data.width,tftlcd_data.height,16,"ExSRAM Test");1 O$ }* l" v6 t- i% P& ?2 l; y
  22.   LCD_ShowString(10,70,tftlcd_data.width,tftlcd_data.height,16,"K_UP:Write   K_DOWN:Read");       
    $ m  E& ^* n( w/ u) G7 z5 F
  23.   FRONT_COLOR=RED;
    - v6 v( ^8 i; f: |
  24.   ExSRAM_Cap_Test(10,110); 2 L7 R& [+ M/ V2 w; h0 K
  25.   FRONT_COLOR=MAGENTA;
    & L4 X* j8 D1 ^% D
  26.   LCD_ShowString(10,130,tftlcd_data.width,tftlcd_data.height,16,"Write:");
    & b, r* C4 V- U  b$ X: f4 H1 Q
  27.   LCD_ShowString(10,150,tftlcd_data.width,tftlcd_data.height,16,"Read :");2 Y5 T6 Q8 g9 b
  28.   /* USER CODE END 2 */1 F! w$ z. v) w. m9 W
  29.   /* Infinite loop */
      b; r( [5 x: E( H' T
  30.   /* USER CODE BEGIN WHILE */
    2 e; ]9 W) S7 \  _
  31.   while(1){
    ) [+ j( A/ A) X- N) F' H5 o
  32.     key = KEY_Scan(0);( Y$ t" f3 o  m. `
  33.     if(key == KEY_UP_PRES){        //KEY_UP按下写数据到SRAM
    ( c/ l2 K: ]* `; F% k' y2 n9 K9 f7 o
  34.       FSMC_SRAM_WriteBuffer(text_buf,0,textlen);
    ! A( H  j8 Z" n& d
  35.       printf("SRAM_Write:%s\r\n",text_buf);. I# j& T* I2 K! I1 u
  36.       LCD_ShowString(10+6*8,130,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)text_buf);
    2 `- B% y0 h, f, C) f0 F0 p9 p
  37.     }
    + z% C. J; |% l- {6 w
  38.     if(key == KEY_DOWN_PRES){        //KEY_DOWN按下从SRAM读出数据# K, K3 K: s( x" v
  39.       FSMC_SRAM_ReadBuffer(read_buf,0,textlen);
      Y0 K* T* d9 i7 t* C4 w
  40.       printf("SRAM_Read:%s\r\n",read_buf);
    % L& @# H8 z. F
  41.       LCD_ShowString(10+6*8,150,tftlcd_data.width,tftlcd_data.height,16,read_buf);
    2 ~; F& ?4 r6 O0 {- }
  42.     }               
    . Y! Y0 ?3 ?0 c: W3 Z
  43.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
    ; p0 W% N7 f; E
  44.     HAL_Delay(200);: H, ]9 J' j7 f# \' D4 `' N, s( N- r
  45.   }
    * b7 ]5 c$ U1 d" m5 D9 j
  46. }
复制代码

- j* _& s& L" w* x" H
4.下载验证

0 g6 B# `5 s' t" i: O' _3 Z+ u) u
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,KEY_UP按下写数据到SRAM,KEY_DOWN按下从SRAM读出数据,并将写入和读出的数据显示在LCD屏上,并通过串口1打印出来
微信图片_20230628153134.png
) v2 Y0 X1 M/ T1 S$ f
转载自: 嵌入式攻城狮
如有侵权请联系删除- W4 I" h! m) S3 g: _
; |  [7 }( \1 l. W( j+ j8 {* q
赞 收藏 评论0 发布时间:2023-6-28 15:32

举报

0个回答

所属标签

相似技术帖

官网相关资源

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