STM32CubeMX教程23 FSMC - IS62WV51216(SRAM)驱动

这篇具有很好参考价值的文章主要介绍了STM32CubeMX教程23 FSMC - IS62WV51216(SRAM)驱动。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、准备材料

开发板(正点原子stm32f407探索者开发板V2.4)

STM32CubeMX软件(Version 6.10.0)

野火DAP仿真器

keil µVision5 IDE(MDK-Arm)

ST-LINK/V2驱动

XCOM V2.6串口助手

2、实验目标

使用STM32CubeMX软件配置STM32F407开发板的FSMC实现以轮询或DMA的方式读写IS62WV51216(SRAM)芯片

3、轮询方式读写SRAM

3.0、前提知识

关于FSMC的内容读者可阅读“STM32CubeMX教程22 FSMC - 8080并行接口TFT-LCD驱动”实验“3.0、前提知识”小节

本实验使用的SRAM芯片为IS62WV51216,其为16位宽512K容量的静态随机存取存储器,开发板使用FSMC Bank 1-NOR/PSRAM3,片选信号为NE3(PG10),地址线A[0:18],数据线D[0:15]来控制该存储芯片,如下图所示为该存储芯片的硬件原理图

FSMC的地址线是按照字节寻址的,因此19根地址线的寻址范围应该为0x0 0000~0x7 FFFF(2^19=524288=0x8 0000)

但是由于该存储器为16位(2个字节),因此其实际容量应该为2*512KB=1024KB,其需要的寻址范围为0x0 0000~0xF FFFF

再考虑到FSMC Bank 1-NOR/PSRAM3起始地址为0x6800 0000,因此如果要访问IS62WV51216芯片全部的1024KB数据的地址范围应该为0x6800 0000~0x680F FFFF

19根地址线做不到,那怎么办?

解决方法就是将16位宽分为高字节和低字节,通过FSMC的字节控制引脚FSMC_NBL0/1实现全部1024KB存储空间的访问

3.1、CubeMX相关配置

3.1.0、工程基本配置

打开STM32CubeMX软件,单击ACCESS TO MCU SELECTOR选择开发板MCU(选择你使用开发板的主控MCU型号),选中MCU型号后单击页面右上角Start Project开始工程,具体如下图所示

开始工程之后在配置主页面System Core/RCC中配置HSE/LSE晶振,在System Core/SYS中配置Debug模式,具体如下图所示

详细工程建立内容读者可以阅读“STM32CubeMX教程1 工程建立”

3.1.1、时钟树配置

系统时钟使用8MHz外部高速时钟HSE,HCLK、PCLK1和PCLK2均设置为STM32F407能达到的最高时钟频率,具体如下图所示

3.1.2、外设参数配置

本实验需要需要初始化开发板上KEY1和KEY0两个用户按键,具体配置步骤请阅读“STM32CubeMX教程3 GPIO输入 - 按键响应”

本实验需要需要初始化USART1作为输出信息渠道,具体配置步骤请阅读“STM32CubeMX教程9 USART/UART 异步通信”

本实验写入SRAM数据时使用到了STM32的随机数RNG功能,读者直接在Security/RNG中将其激活即可

单击Pinout & Configuration页面左边Connectivity/FSMC选项,在右边的Mode下点开NORFIash/PSRAM/SRAM/ROM/LCD3选项卡(因为SRAM使用的是使用FSMC Bank 1-NOR/PSRAM3),然后按照下面顺序配置

  1. 选择片选信号NE3
  2. 内存类型为SRAM
  3. FSMC地址线19位
  4. 数据Data为16位宽度(D0-D15)
  5. 使能字节控制Byte enable

下方的读写时序参数配置可阅读“STM32CubeMX教程22 FSMC - 8080并行接口TFT-LCD驱动”实验“3.0、前提知识”小节,具体配置如下图所示

配置完成之后请读者对照STM32CubeMX中配置的默认功能引脚是否和开发板硬件原理图每个引脚对应,防止出现默认功能引脚与开发板设计的引脚不一致的现象

3.1.3、外设中断配置

轮询方式读写SRAM无需配置任何中断

3.2、生成代码

3.2.0、配置Project Manager页面

单击进入Project Manager页面,在左边Project分栏中修改工程名称、工程目录和工具链,然后在Code Generator中勾选“Gnerate peripheral initialization as a pair of 'c/h' files per peripheral”,最后单击页面右上角GENERATE CODE生成工程,具体如下图所示

详细Project Manager配置内容读者可以阅读“STM32CubeMX教程1 工程建立”实验3.4.3小节

3.2.1、外设初始化调用流程

请阅读“STM32CubeMX教程22 FSMC - 8080并行接口TFT-LCD驱动”实验3.2.1小节

3.2.2、外设中断调用流程

轮询方式读写SRAM无需配置任何中断

3.2.3、添加其他必要代码

在main.c文件中添加SRAM读写测试函数,具体函数源代码如下所示

/*用HAL函数写入数据*/
void SRAM_WriteByFunc(void)
{
    //1.写入字符串
    uint32_t *pAddr = (uint32_t *)(SRAM_ADDR_BEGIN);	//给指针赋值
    uint8_t strIn[] = "Moment in UPC";
    uint16_t dataLen = sizeof(strIn); //数据长度,字节数,包括最后的结束符'\0’
    if(HAL_SRAM_Write_8b(&hsram3, pAddr, strIn, dataLen) == HAL_OK)
    {
        printf("Write string at 0x6800 0000:");
        printf("%s\r\n",strIn);
    }
 
    //2.写入一个随机数
    uint32_t num=0;
    pAddr=(uint32_t *)(SRAM_ADDR_BEGIN+256);	//指针重新赋值
    HAL_RNG_GenerateRandomNumber(&hrng, &num);	//产生32位随机数
    if(HAL_SRAM_Write_32b(&hsram3, pAddr, &num, 1) == HAL_OK)
    {
        printf("Write 32b number at 0x6800 0100");
        printf("0x%x\r\n", num);	
    }
    printf("-----------------------------------------\r\n");
}
 
/*用HAL函数读取数据*/
void SRAM_ReadByFunc(void)
{
    //1.读取字符串
    uint32_t *pAddr = (uint32_t *)(SRAM_ADDR_BEGIN);	//给指针赋值
    uint8_t strOut[30];
    uint16_t dataLen = 30;
    if(HAL_SRAM_Read_8b(&hsram3, pAddr, strOut, dataLen) == HAL_OK)
    {
        printf("Read string at 0x6800 0000:");
        printf("%s\r\n", strOut); 
    }
 
    //2.读取一个uint32_t数
    uint32_t num=0;
    pAddr=(uint32_t *)(SRAM_ADDR_BEGIN+256);	//指针重新赋值,指向一个新的地址
    if(HAL_SRAM_Read_32b(&hsram3, pAddr, &num, 1) == HAL_OK)
    {
        printf("Read 32b number at 0x6800 0100:");
        printf("0x%x\r\n", num);
    }
    printf("-----------------------------------------\r\n");
}

在main.c文件中添加使用到的SRAM起始/中间/结束地址,并对定义的函数声明,源代码如下所示

/*定义SRAM地址*/
#define SRAM_ADDR_BEGIN		0x68000000UL //Bank1 子区3的 SRAM起始地址
#define SRAM_ADDR_HALF		0x68080000UL //SRAM 中间地址 512K字节
#define SRAM_ADDR_END	    0x680FFFFFUL //SRAM 结束地址 1024K字节
 
/*读写测试函数声明*/
void SRAM_ReadByFunc(void);
void SRAM_WriteByFunc(void);

最后在主函数主循环while(1)中使用用户按键调用SRAM读写测试函数即可,源代码如下所示

/*KEY1被按下*/
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_RESET)
{
    HAL_Delay(50);
    if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_RESET)
    {
        //SRAM写测试函数
        SRAM_WriteByFunc();
        while(!HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin));
    }
}
 
/*KEY0被按下*/
if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == GPIO_PIN_RESET)
{
    HAL_Delay(50);
    if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == GPIO_PIN_RESET)
    {
        //SRAM读测试函数
        SRAM_ReadByFunc();
        while(!HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin));
    }
}

4、常用函数

/*向SRAM中写8位缓存数据*/
HAL_StatusTypeDef HAL_SRAM_Write_8b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pSrcBuffer, uint32_t BufferSize)
 
/*从SRAM中读8位缓存数据*/
HAL_StatusTypeDef HAL_SRAM_Read_8b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pDstBuffer, uint32_t BufferSize)
 
/*向SRAM中写16位缓存数据*/
HAL_StatusTypeDef HAL_SRAM_Write_16b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pSrcBuffer, uint32_t BufferSize)
 
/*从SRAM中读16位缓存数据*/
HAL_StatusTypeDef HAL_SRAM_Read_16b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pDstBuffer, uint32_t BufferSize)
 
/*向SRAM中写32位缓存数据*/
HAL_StatusTypeDef HAL_SRAM_Write_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pSrcBuffer, uint32_t BufferSize)
 
/*从SRAM中读32位缓存数据*/
HAL_StatusTypeDef HAL_SRAM_Read_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pDstBuffer, uint32_t BufferSize)
 
/*向SRAM中写32位缓存数据*/
HAL_StatusTypeDef HAL_SRAM_Write_DMA(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pSrcBuffer, uint32_t BufferSize)
 
/*从SRAM中读32位缓存数据*/
HAL_StatusTypeDef HAL_SRAM_Read_DMA(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pDstBuffer, uint32_t BufferSize)

5、烧录验证

烧录程序,开发板上电后打开串口助手,按下KEY0按键从SRAM中指定位置读取数据,发现读取到错误乱码信息;按下KEY1按键将准备好的数据写入SRAM指定位置,再次按下KEY0按键从该指定位置读取数据,发现和我们写入的数据一致,可重复多次尝试,发现读取的信息均和写入信息一致,如下图所示为串口输出详细信息

6、DMA方式读写SRAM

6.1、前提知识

读写SRAM还可以使用DMA的方式进行,但是由于SRAM属于存储设备,因此读写SRAM的DMA方向应该为内存到内存

在“STM32CubeMX教程12 DMA 直接内存读取”我们提到只有DAM2的8个通道可以实现从存储器到存储器这种传输模式,由于该模式比较特殊,因此读者可以发现不同于其他外设DMA的配置,在FSMC选项卡我们配置SRAM的页面中根本没有DMA选项卡可以设置,因此想要设置从存储器到存储器这种传输模式的DMA必须在System Core/DMA选项卡中设置

另外在其他外设设置DMA时,DMA流与外设关联的函数__HAL_LINKDMA()会被自动生成在HAL_xxx_MspInit()函数中

但是如果DMA为存储器到存储器这种传输模式,则生成的工程代码中不会自动关联DMA流与外设(他也不知道该如何关联),因此在DMA及外设均初始化完毕之后,需要用户手动增加__HAL_LINKDMA()函数将外设与DMA流关联

6.2、CubeMX相关配置

请读者先按照本实验“3.1、CubeMX相关配置” 小节配置RCC、SYS、用户按键、串口USART1和FSMC模式和基本参数

如果读者对DMA参数不理解,请阅读“STM32CubeMX教程12 DMA 直接内存读取”实验,然后按下方顺序配置DMA参数

  1. 单击Pinout & Configuration页面左边System Core/DMA选项卡
  2. 在Configuration中选择MemToMem
  3. 单击下方的增加按钮选择增加DMA请求
  4. 单击增加的DMA请求
  5. 在下方对其参数进行配置,模式为Normal
  6. 源/目标内存地址均递增
  7. 数据宽度选择word(因为HAL库提供的DMA写入SRAM函数数据为32位的)

其他参数默认,具体配置参看下图

在Pinout & Configuration页面左边System Core/NVIC中勾选DMA2 Stream0 全局中断,然后选择合适的中断优先级即可

6.3、DMA中断调用流程

DMA触发中断,其回调函数是一个函数指针的形式,在外设使用DMA启动传输的时候会将外设对应的中断回调函数赋值给DMA中断回调函数指针,具体请阅读“STM32CubeMX教程12 DMA 直接内存读取”实验实验3.2.2小节,流程大致一致

这里读者只需知道,在STM32CubeMX开启FSMC配置的SRAM DMA中断之后,在工程代码中使用HAL_SRAM_Read_DMA() / HAL_SRAM_Write_DMA()函数传输完毕之后,都会调用HAL_SRAM_DMA_XferCpltCallback()虚函数,用户重新实现该虚函数即可

由于以DMA方式读和写SRAM传输完成的回调函数为同一个,因此用户可以自己设定标志位,从而可以在中断回调函数中判断是读完成还是写完成

6.4、添加其他必要代码

配置工程并单击页面右上角GENERATE CODE生成工程

在main.c文件中FSMC初始化完毕之后添加DMA流与外设关联的函数

//将外设与DMA流关联
__HAL_LINKDMA(&hsram3, hdma, hdma_memtomem_dma2_stream0);

在main.c文件中增加以DMA方式读写SRAM的测试函数,源代码如下

/*以DMA方式写入数据*/
void SRAM_WriteDMA(void)													
{
    printf("Write 32bit array by DMA:");
    uint32_t Value=3000;	
    for(uint8_t i=0; i<COUNT; i++)
    {
        txBuffer[i] = Value;
        printf("%d,",Value);
        Value += 6;
    }
    printf("\r\n");
    //DMA传输方向,1=write, 0=read
    DMA_Direction=1;					
    //表示DMA正在传输,1=working, 0=idle	
    DMA_Busy=1;																			
    //给指针赋值
    uint32_t *pAddr_32b=(uint32_t *)(SRAM_ADDR_BEGIN);			
    //DMA方式写入SRAM	
    HAL_SRAM_Write_DMA(&hsram3, pAddr_32b, txBuffer, COUNT);	
}
 
/*以DMA方式读取数据*/
void SRAM_ReadDMA(void)														
{
    printf("Read 32bit array by DMA\r\n");
    DMA_Direction=0;													
    DMA_Busy=1;			
    uint32_t *pAddr_32b=(uint32_t *)(SRAM_ADDR_BEGIN);	
    //以DMA方式读取SRAM
    HAL_SRAM_Read_DMA(&hsram3, pAddr_32b, rxBuffer, COUNT);
}

在main.c文件头部增加函数声明及使用到的一些变量定义,源代码如下

/*函数声明*/
void SRAM_WriteDMA(void);
void SRAM_ReadDMA(void);
 
/*变量定义*/
#define COUNT 5                      //缓存区数据个数
uint32_t txBuffer[COUNT];            //DMA发送缓存区
uint32_t rxBuffer[COUNT];            //DMA接收缓存区
uint8_t DMA_Direction = 1;           //DMA传输方向,1=write, 0=read
uint8_t DMA_Busy = 0;                //DMA工作状态,1=busy, 0=idle

最后在主循环中使用用户按键调用SRAM读写测试函数即可,源代码如下所示

/*KEY1被按下*/
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_RESET)
{
    HAL_Delay(50);
    if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_RESET)
    {
        //SRAM DMA写测试函数
        SRAM_WriteDMA();
        while(!HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin));
    }
}
 
/*KEY0被按下*/
if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == GPIO_PIN_RESET)
{
    HAL_Delay(50);
    if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == GPIO_PIN_RESET)
    {
        //SRAM DMA读测试函数
        SRAM_ReadDMA();
        while(!HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin));
    }
}

6.5、实验现象

烧录程序,开发板上电后打开串口助手,按下KEY0按键以DMA方式从SRAM中指定位置读取数据,发现读取到错误的5个数据;按下KEY1按键将3000,3006,3012,3018,3024五个数据以DMA方式写入SRAM指定位置,再次按下KEY0按键以DMA方式从SRAM中指定位置读取数据,发现和我们写入的数据一致,整个过程读者也可以发现每次以DMA方式写入/读取SRAM完成之后都会进入DMA传输完成回调函数中,如下图所示为整个过程串口输出的详细信息

参考资料

STM32Cube高效开发教程(基础篇)文章来源地址https://www.toymoban.com/news/detail-820206.html

到了这里,关于STM32CubeMX教程23 FSMC - IS62WV51216(SRAM)驱动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32】FSMC—扩展外部 SRAM 初步使用 1

    基于野火指南者《零死角玩转 STM32F103—指南者》的学习 STM32F103系列 1.详细功能参看《STM32F10x参考手册》,这边是概述 是一个外设,挂载在AHB总线下。 可以用于驱动包括 SRAM 、 NOR FLASH 以及 NAND FLSAH 类型的存储器,不能驱动如 SDRAM 这种动态的存储器 STM32F429 系列的控制器中,

    2024年02月20日
    浏览(31)
  • STM32 FSMC接口驱动4.3寸TFT LCD屏

    STM32的FSMC接口是并行总线接口,可以用于驱动存储芯片如FLASH/SRAM等,也可以用于驱动并口LCD屏。 这里以STM32F103VET6开发板连接4.3寸TFT LCD屏,将正点原子的参考代码,移植到STM32CUBEIDE开发环境,实现TFT LCD屏的显示。 TFT LCD模块的管脚连接: 其中: LCD_CS是总线片选, WR/CLK是写使

    2024年02月10日
    浏览(43)
  • 【STM32CubeMX】教程二_IIC驱动0.96oled屏幕(SSD1306)

    本篇博客涉及以下内容 IIC通讯原理讲解、代码编写 SSD1306驱动芯片datasheet讲解、驱动代码编写、0.96oled模块原理图说明 STM32CubeMX配置IIC 使用硬件:STM32F103C8T6 使用软件:STM32CubeMX、keil5(MDK)、VSCode(搭载keil assistant插件) 提示:以下是本篇文章正文内容   在计算机科学里,大

    2023年04月21日
    浏览(40)
  • STM32 SPI+DMA 驱动 SRAM LY68L6400SLIT 应用笔记

    : 库函数,STM32F407,SPI+DMA ,SPI-DMA,SRAM , LY68L6400SLIT,STM32CubeMX 编 辑: 大黄蜂 说明: 本笔记记录 基于 STM32F407 + RT RTOS 采用 SPI接口和 SPI+DMA接口 调试 SRAM LY68L6400SLIT (8M 字节 SRAM) 重点: STM32 HAL SPI 库函数;STM32CubeMX SPI 配置;STM32CubeMX SPI 配置+DMA配置;SPI+DMA 读写SR

    2024年02月12日
    浏览(33)
  • 【CubeMX配置STM32驱动MPU6050】

    一、使用CubeMX进行相关配置 1、配置OLED的IIC接口 OLED的具体使用方法我就不细说了,我前面的文章里面有讲OLED的,如果有需要可以去看看。 2、配置MPU6050的接口 我用MPU6050使用的是 软件IIC (其实是只找到软件IIC的驱动),所以我们只需要配置两个GPIO口就可以实现对MPU6050的控

    2024年02月12日
    浏览(38)
  • STM32CubeMX ULN2003步进电机驱动

    一、28BYJ-48 步进电机  28BYJ-48是一款5线单极步进电机,运行电压为5V。 根据数据表,当28BYJ-48电机在全步模式下运行时,每步对应于11.25°的旋转。这意味着每转有32步 (360°/11.25° = 32)。 如上图所示,步距角=5.625°/64 意思就是每64个脉冲步进电机就会转5.625度,因此我们很容易得

    2024年01月18日
    浏览(48)
  • STM32CubeMX驱动4x4键盘模块

    4x4键盘模块是一种常用的电子组件,它由16个按钮或开关以矩阵方式排列而成,可以与微控制器或其他数字电路设备一起使用。该模块通常用于数据输入、操作界面等各种应用场合。 如果你的单片机已经有足够的GPIO引脚可供使用,可以把4x4键盘模块中的16个按键分别连接到

    2024年01月21日
    浏览(41)
  • 【STM32+CUBEMX】TMC5160电机驱动简要配置

    TMC5160简介                 1.1、引脚图          1.2、关键引脚                1.2.1 模式选择引脚                  1.2.2 时钟和SPI引脚                   1.2.3 驱动使能引脚  2.SPI发送数据结构         发送到 TMC5160 的每个数据报由一个地

    2024年02月06日
    浏览(38)
  • STM32初学入门笔记(5):使用STM32CubeMX通过SPI,IIC驱动OLED屏幕

    随着时代的进步,OLED显示屏成为了继LCD显示屏之后的新一代显示屏技术,OLED具有可视角高,功耗低,厚度薄,耐冲击、振动能力强,像素响应时间低等优点,在嵌入式开发中,OLED显示器也是一个主要的部分,制作OLED显示模块的驱动也是学习STM32路上的重要一部分,本篇将从

    2024年02月04日
    浏览(35)
  • STM32配合CubeMX硬件SPI驱动0.96寸OLED

    目录 一、简单介绍 1.1 OLED 1.2 SPI协议 接口 优点 缺点 数据传输 二、实战 2.1 工程配置 2.2 测试工程 2.3 波形分析 三、驱动OLED 3.1 初始化代码 3.2 清屏函数 3.3 设置坐标函数 3.4 显示字符函数 3.5 显示字符串函数 3.6 显示图片函数 附录 驱动代码文件 oled.c oled.h f6x8.h 1.1 OLED 有机发

    2024年02月02日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包