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

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

微信图片_20230628153158.png

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


2.硬件设计
D1指示灯用来提示系统运行状态,按键用来控制IS62WV12816数据读写,TFTLCD和串口1用来显示读写的内容

  • D1指示灯
  • K_UP/K_DOWN按键
  • USART1串口
  • TFTLCD

  • IS62WV12816


从电路图中可以看到IS62WV12816和STM32F1的连接线路:
A0 ~ A16连接在FSMC_A0 ~ FSMC_A16上(连接顺序可以打乱,因为地址是固定的)
I/O0 ~ I/O15连接在FSMC_D0 ~ FSMC_D15上(连接顺序不能打乱,否则读写数据将出错)
UB和LB连接在FSMC_NBL1 和 FSMC_NBL0上
OE和WE分别连接在FSMC_NOE 和 FSMC_NWE上
CE连接在FSMC_NE3上

微信图片_20230628153150.png

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


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

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


微信图片_20230628153141.png


3.2 MDK-ARM软件编程
➡️ 创建按键驱动文件key.c和key.h,参考按键输入例程
➡️ 创建LCD驱动文件tftlcd.c 和tftlcd.h,参考TFTLCD显示例程
➡️ 创建IS62WV12816芯片驱动文件sram.c和sram.h

  1. #define Bank1_SRAM3_ADDR    ((uint32_t)(0x68000000))//Bank1区域3的起始地址       
  2. SRAM_HandleTypeDef SRAM_Handler;//定义SRAM句柄
  3. //SRAM的FSMC初始化函数
  4. void FSMC_SRAM_Init(void){       
  5.   GPIO_InitTypeDef GPIO_InitStruct;
  6.   FSMC_NORSRAM_TimingTypeDef FSMC_ReadWriteTim;
  7.   __HAL_RCC_FSMC_CLK_ENABLE();           
  8.   __HAL_RCC_GPIOD_CLK_ENABLE();              
  9.   __HAL_RCC_GPIOE_CLK_ENABLE();               
  10.   __HAL_RCC_GPIOF_CLK_ENABLE();              
  11.   __HAL_RCC_GPIOG_CLK_ENABLE();               
  12.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
  13.                      |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13
  14.                      |GPIO_PIN_14|GPIO_PIN_15;
  15.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  16.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  17.   HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
  18.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
  19.                      |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_10;
  20.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  21.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  22.   HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
  23.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
  24.                      |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
  25.                      |GPIO_PIN_15;
  26.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  27.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  28.   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
  29.   GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
  30.                      |GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1
  31.                      |GPIO_PIN_4|GPIO_PIN_5;
  32.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  33.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  34.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);  
  35.        
  36.   SRAM_Handler.Instance=FSMC_NORSRAM_DEVICE;               
  37.   SRAM_Handler.Extended=FSMC_NORSRAM_EXTENDED_DEVICE;     
  38.   SRAM_Handler.Init.NSBank=FSMC_NORSRAM_BANK3;        //使用NE3
  39.   SRAM_Handler.Init.DataAddressMux=FSMC_DATA_ADDRESS_MUX_DISABLE;//地址/数据线不复用
  40.   SRAM_Handler.Init.MemoryType=FSMC_MEMORY_TYPE_SRAM;            //SRAM
  41.   SRAM_Handler.Init.MemoryDataWidth=FSMC_NORSRAM_MEM_BUS_WIDTH_16;//16位数据宽度
  42.   SRAM_Handler.Init.BurstAccessMode=FSMC_BURST_ACCESS_MODE_DISABLE;//不使能突发访问
  43.   SRAM_Handler.Init.WaitSignalPolarity=FSMC_WAIT_SIGNAL_POLARITY_LOW;//等待信号的极性(突发模式)
  44.   SRAM_Handler.Init.WaitSignalActive=FSMC_WAIT_TIMING_BEFORE_WS;          
  45.   SRAM_Handler.Init.WriteOperation=FSMC_WRITE_OPERATION_ENABLE;    //写使能
  46.   SRAM_Handler.Init.WaitSignal=FSMC_WAIT_SIGNAL_DISABLE;         
  47.   SRAM_Handler.Init.ExtendedMode=FSMC_EXTENDED_MODE_DISABLE;       //读写使用相同的时序
  48.   SRAM_Handler.Init.AsynchronousWait=FSMC_ASYNCHRONOUS_WAIT_DISABLE;
  49.   SRAM_Handler.Init.WriteBurst=FSMC_WRITE_BURST_DISABLE;           //禁止突发写
  50.   //FSMC读时序控制器
  51.   FSMC_ReadWriteTim.AddressSetupTime=0x00;      //地址建立时间(ADDSET)为1个HCLK
  52.   FSMC_ReadWriteTim.AddressHoldTime=0x00;        //地址保持时间(ADDHLD)模式A未用到
  53.   FSMC_ReadWriteTim.DataSetupTime=0x08;                //数据保持时间(DATAST)为9个HCLK
  54.   FSMC_ReadWriteTim.BusTurnAroundDuration=0X00;
  55.   FSMC_ReadWriteTim.AccessMode=FSMC_ACCESS_MODE_A;//模式A
  56.   HAL_SRAM_Init(&SRAM_Handler,&FSMC_ReadWriteTim,&FSMC_ReadWriteTim);       
  57. }
  58. //n向指定地址写数据
  59. void FSMC_SRAM_WriteBuffer(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t n){
  60.   for(;n!=0;n--){        // n表示要连续写入的字节个数
  61.     *(vu8*)(Bank1_SRAM3_ADDR + WriteAddr) = *pBuffer;
  62.     WriteAddr++;        //要写入的地址
  63.     pBuffer++;                //要写入的数据的指针
  64.   }
  65. }
  66. //从指定地址读数据
  67. void FSMC_SRAM_ReadBuffer(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t n){
  68.   for(;n!=0;n--){        // n表示要连续读出的字节个数
  69.     *pBuffer++=*(vu8*)(Bank1_SRAM3_ADDR+ReadAddr);//存放读出的数据
  70.     ReadAddr++;                //要读出的起始地址
  71.   }
  72. }
  73. //            
  74. void ExSRAM_Cap_Test(uint16_t x,uint16_t y){
  75.   uint8_t writeData = 0xf0, readData;
  76.   uint16_t cap=0;
  77.   uint32_t addr;       
  78.   addr = 1024;         //从1KB位置开始计算       
  79.   LCD_ShowString(x,y,239,y+16,16,"ExSRAM Cap:   0KB");
  80.        
  81.   while(1){
  82.     FSMC_SRAM_WriteBuffer(&writeData, addr, 1);
  83.     FSMC_SRAM_ReadBuffer(&readData,addr,1);
  84.        
  85.     if(readData == writeData){//检查读出的数据是否与写入的数据一样
  86.       cap++;                //如果相同表示写入/读出成功,容量加1(单位KB)
  87.       addr += 1024;        //地址加1024
  88.       readData = 0;
  89.       if(addr > 256 * 1024)//IS62WV12816的容量为256KB
  90.         break;   
  91.     }
  92.     else
  93.       break;  
  94.   }
  95.   LCD_ShowxNum(x+11*8,y,cap,4,16,0);//LCD上显示内存容量
  96.   printf("SRAM Menmory Size:%dKB\r\n",cap);
  97. }
复制代码

➡️ 在main.c文件下编写SRAM测试代码

  1. int main(void){
  2.   /* USER CODE BEGIN 1 */
  3.   uint8_t key;
  4.   uint8_t text_buf[] = "This is SRAM testing...";
  5.   uint8_t textlen = sizeof(text_buf);
  6.   uint8_t read_buf[textlen];
  7.   /* USER CODE END 1 */
  8.   HAL_Init();
  9.   SystemClock_Config();
  10.   MX_GPIO_Init();
  11.   MX_FSMC_Init();
  12.   MX_USART1_UART_Init();
  13.   /* USER CODE BEGIN 2 */
  14.   TFTLCD_Init();
  15.   FSMC_SRAM_Init();
  16.   FRONT_COLOR=BROWN;
  17.   LCD_DrawRectangle(5,5,235,95);
  18.   FRONT_COLOR=BLACK;
  19.   LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,16,"ANDYXI STM32F1");
  20.   LCD_ShowString(10,30,tftlcd_data.width,tftlcd_data.height,16,"STM32CubeMx SRAM");
  21.   LCD_ShowString(10,50,tftlcd_data.width,tftlcd_data.height,16,"ExSRAM Test");
  22.   LCD_ShowString(10,70,tftlcd_data.width,tftlcd_data.height,16,"K_UP:Write   K_DOWN:Read");       
  23.   FRONT_COLOR=RED;
  24.   ExSRAM_Cap_Test(10,110);
  25.   FRONT_COLOR=MAGENTA;
  26.   LCD_ShowString(10,130,tftlcd_data.width,tftlcd_data.height,16,"Write:");
  27.   LCD_ShowString(10,150,tftlcd_data.width,tftlcd_data.height,16,"Read :");
  28.   /* USER CODE END 2 */
  29.   /* Infinite loop */
  30.   /* USER CODE BEGIN WHILE */
  31.   while(1){
  32.     key = KEY_Scan(0);
  33.     if(key == KEY_UP_PRES){        //KEY_UP按下写数据到SRAM
  34.       FSMC_SRAM_WriteBuffer(text_buf,0,textlen);
  35.       printf("SRAM_Write:%s\r\n",text_buf);
  36.       LCD_ShowString(10+6*8,130,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)text_buf);
  37.     }
  38.     if(key == KEY_DOWN_PRES){        //KEY_DOWN按下从SRAM读出数据
  39.       FSMC_SRAM_ReadBuffer(read_buf,0,textlen);
  40.       printf("SRAM_Read:%s\r\n",read_buf);
  41.       LCD_ShowString(10+6*8,150,tftlcd_data.width,tftlcd_data.height,16,read_buf);
  42.     }               
  43.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
  44.     HAL_Delay(200);
  45.   }
  46. }
复制代码

4.下载验证

编译无误下载到开发板后,可以看到D1指示灯不断闪烁,KEY_UP按下写数据到SRAM,KEY_DOWN按下从SRAM读出数据,并将写入和读出的数据显示在LCD屏上,并通过串口1打印出来
微信图片_20230628153134.png

转载自: 嵌入式攻城狮
如有侵权请联系删除

收藏 评论0 发布时间:2023-6-28 15:32

举报

0个回答

所属标签

相似分享

官网相关资源

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