【正点原子STM32连载】 第四十四章 外部SRAM实验 摘自【正点原子】APM32E103最小系统板使用指南

1)实验平台:正点原子APM32E103最小系统板
2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/docs/boards/xiaoxitongban

第四十四章 外部SRAM实验

本章将介绍使用APM32E103驱动SRAM进行SRAM的数据读写。通过本章的学习,读者将学习到EMMC中SMC的使用。
本章分为如下几个小节:
44.1 硬件设计
44.2 程序设计
44.3 下载验证

44.1 硬件设计
44.1.1 例程功能

  1. 程序运行后,可通过按下KEY0和KEY_UP按键,分别进行SRAM的容量和数据测试,测试结果将在LCD上显示
  2. 可通过USMART对外部SRAM进行数据读写的测试操作
  3. LED0闪烁,指示程序正在运行
    44.1.2 硬件资源
  4. LED
    LED0 - PB5
  5. 按键
    KEY0 - PE4
    KEY_UP - PA0
  6. USART1(PA9、PA10连接至板载USB转串口芯片上)
  7. 正点原子 2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
  8. 外部SRAM(SMC驱动)
    44.1.3 原理图
    本章实验使用了一个板载的SRAM芯片,该SRAM芯片通过MCU的SMC接口与MCU进行连接,该SRAM与MCU的连接原理图,如下图所示:
    在这里插入图片描述

图44.1.3.1 SRAM与MCU的连接原理图
44.2 程序设计
44.2.1 Geehy标准库的SMC驱动
本章实验通过SMC驱动SRAM芯片,通过SMC可以将外部SRAM芯片的数据访问映射成一段内存空间,通过访问这段内存空间,即可访问SRAM芯片中的数据,因此需要对SMC做相应的配置,SMC的配置方式,请读者查看第25.2.1小节中Geehy标准库的SMC驱动中相关的内容。
44.2.2 SRAM驱动
本章实验的SRAM驱动主要负责向应用层提供SRAM的初始化函数,因为SRAM在初始化后,SRAM将被映射为一段内存空间,对SRAM的访问操作就是访问这段内存空间。本章实验中,SRAM的驱动代码包括sram.c和sram.h两个文件。
由于SRAM需要使用大量的GPIO引脚,因此对于GPIO的相关定义,请读者自行查看sram.c和sram.h这两个文件。
SRAM驱动中,SRAM的初始化函数,如下所示:

/*** @brief       初始化外部SRAM* @param       无* @retval      无*/
void sram_init(void)
{GPIO_Config_T gpio_init_struct;SMC_NORSRAMConfig_T smc_norsram_init_struct;SMC_NORSRAMTimingConfig_T smc_timing_struct;/* 使能时钟 */RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_SMC);	/* 使能SMC时钟 */SRAM_WR_GPIO_CLK_ENABLE();						/* 使能SMC_NWE引脚端口时钟 */SRAM_RD_GPIO_CLK_ENABLE();						/* 使能SMC_NOE引脚端口时钟 */
SRAM_CS_GPIO_CLK_ENABLE();						/* 使能SMC_NE3引脚端口时钟 */
/* 使能SMC_D0/1/2/3/13/14/15、SMC_A16/17/18引脚端口时钟 */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOD);
/* 使能SMC_D4/5/6/7/8/9/10/11/12、SMC_NBL0/1引脚端口时钟 */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOE);/* 使能SMC_A0/1/2/3/4/5/6/7/8/9引脚端口时钟 */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOF);
/* 使能SMC_A10/11/12/13/14/15引脚端口时钟 */RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOG);/* 配置SMC_NWE引脚 */
gpio_init_struct.pin = SRAM_WR_GPIO_PIN;
/* 高速 */
gpio_init_struct.speed = GPIO_SPEED_50MHz;
/* 复用功能推挽输出模式 */
gpio_init_struct.mode = GPIO_MODE_AF_PP; 
/* 配置SMC_NOE引脚 */GPIO_Config(SRAM_WR_GPIO_PORT, &gpio_init_struct);/* SMC_NOE引脚 */gpio_init_struct.pin = SRAM_RD_GPIO_PIN;                                       	/* 配置SMC_NEx引脚 */GPIO_Config(SRAM_RD_GPIO_PORT, &gpio_init_struct);/* SMC_NEx引脚 */gpio_init_struct.pin = SRAM_CS_GPIO_PIN;                                                	/* 配置SMC_NEx引脚 */GPIO_Config(SRAM_CS_GPIO_PORT, &gpio_init_struct);/* 配置SMC_NBLn引脚省略 *//* 地址建立时间 */
smc_timing_struct.addressSetupTime = 0x02;
/* 地址保持时间 */
smc_timing_struct.addressHodeTime = 0x00;
/* 数据建立时间 */
smc_timing_struct.dataSetupTime = 0x02;
/* 访问模式 */
smc_timing_struct.accessMode = SMC_ACCESS_MODE_A;
/* 根据配置选择SMC_NE1~4 */smc_norsram_init_struct.bank = (SRAM_SMC_NEX == 1) ? SMC_BANK1_NORSRAM_1 :(SRAM_SMC_NEX == 2) ? SMC_BANK1_NORSRAM_2 :(SRAM_SMC_NEX == 3) ? SMC_BANK1_NORSRAM_3 :SMC_BANK1_NORSRAM_4;/* 禁止数据、地址总线复用 */
smc_norsram_init_struct.dataAddressMux = SMC_DATA_ADDRESS_MUX_DISABLE;
/* SRAM类型 */
smc_norsram_init_struct.memoryType = SMC_MEMORY_TYPE_SRAM;/* 16位数据宽度 */
smc_norsram_init_struct.memoryDataWidth = SMC_MEMORY_DATA_WIDTH_16BIT;
/* 禁止突发访问 */
smc_norsram_init_struct.burstAcceesMode = SMC_BURST_ACCESS_MODE_DISABLE;
/* 禁止异步传输期间的等待信号 */
smc_norsram_init_struct.asynchronousWait = SMC_ASYNCHRONOUS_WAIT_DISABLE;
/* 配置等待信号极性,仅在突发访问模式下有效 */
smc_norsram_init_struct.waitSignalPolarity = SMC_WAIT_SIGNAL_POLARITY_LOW;
/* 禁止非对齐的突发访问 */
smc_norsram_init_struct.wrapMode = SMC_WRAP_MODE_DISABLE;
/* 配置等待时序 */smc_norsram_init_struct.waitSignalActive = 	SMC_WAIT_SIGNAL_ACTIVE_BEFORE_WAIT_STATE;
/* 使能写存储器 */
smc_norsram_init_struct.writeOperation = SMC_WRITE_OPERATION_ENABLE;
/* 禁止等待信号 */
smc_norsram_init_struct.waiteSignal = SMC_WAITE_SIGNAL_DISABLE;
/* 禁止扩展模式 */
smc_norsram_init_struct.extendedMode = SMC_EXTENDEN_MODE_DISABLE;
/* 禁止突发写 */
smc_norsram_init_struct.writeBurst = SMC_WRITE_BURST_DISABLE;
/* 读时序 */
smc_norsram_init_struct.readWriteTimingStruct = &smc_timing_struct;
/* 写时序 */
smc_norsram_init_struct.writeTimingStruct = NULL;
/* 配置SMC */
SMC_ConfigNORSRAM(&smc_norsram_init_struct);
/* 根据配置使能存储块1区域块1~4 */SMC_EnableNORSRAM((SRAM_SMC_NEX == 1) ? SMC_BANK1_NORSRAM_1 :(SRAM_SMC_NEX == 2) ? SMC_BANK1_NORSRAM_2 :(SRAM_SMC_NEX == 3) ? SMC_BANK1_NORSRAM_3 :SMC_BANK1_NORSRAM_4);
}

从原理图中可以看到,SRAM芯片的CE引脚连接到了PG10引脚(FSMC_NE3信号),因此在进行SRAM初始化后,SRAM映射的内存基地址为0x68000000,访问SRAM中存储的数据仅需访问0x68000000加上数据偏移后的地址即可。
44.2.3 实验应用代码
本章实验的应用代码,如下所示:

/* 定义测试数组* 起始地址为SRAM_BASE_ADDR*/
uint32_t g_test_buffer[250000] __attribute__((at(SRAM_BASE_ADDR)));int main(void)
{uint32_t ts;uint8_t t = 0;uint8_t key;NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_4);  /* 设置中断优先级分组为组4 */sys_apm32_clock_init(15);                         /* 配置系统时钟 */delay_init(120);                                  /* 初始化延时功能 */usart_init(115200);                               /* 初始化串口 */usmart_dev.init(120);                             /* 初始化USMART */led_init();                                       /* 初始化LED */key_init();                                       /* 初始化按键 */lcd_init();                                       /* 初始化LCD */sram_init();                                      /* 初始化外部SRAM */lcd_show_string(30, 50, 200, 16, 16, "APM32", RED);lcd_show_string(30, 70, 200, 16, 16, "SRAM TEST", RED);lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);lcd_show_string(30, 110, 200, 16, 16, "KEY0:Test SRAM", RED);lcd_show_string(30, 130, 200, 16, 16, "KEY_UP:Test Data", RED);for (ts=0; ts<250000; ts++)                       /* 创建测试数据 */{g_test_buffer[ts] = ts;}while (1){t++;key = key_scan(0);if (key == KEY0_PRES)                         /* 测试外部SRAM容量 */{smc_sram_test(30, 150);}else if (key == WKUP_PRES){for (ts=0; ts<250000; ts++){
/* 显示测试数据 */lcd_show_xnum(30, 170, g_test_buffer[ts], 6, 16, 0, BLUE);  }}if (t == 20){LED0_TOGGLE();t = 0;}delay_ms(10);}
}

可以看到,应用代码中定义了一个起始地址为SRAM_BASE_ADDR的数组,SRAM_BASE_ADDR是在sram.h文件中的一个宏定义,该宏定义用于表示SRAM进行映射后的内存起始地址,因此访问数组g_test_buffer就能访问SRAM中的数据。
在完成SRAM初始化后,便往SRAM中填充数据,随后便不断地检测按键输入,若检测到KEY_UP按键被按下,则将SRAM中的数据逐一地读出,然后在LCD上进行显示,这实际是测试了SRAM的读操作,若检测到KEY0按键被按下,则调用函数smc_sram_test()对SRAM进行读写测试,该函数如下所示:

/*** @brief       测试外部SRAM容量* @note        最大支持1MB容量的SRAM* @param       x: LCD上显示提示信息的起始X坐标* @param       y: LCD上显示提示信息的起始Y坐标* @retval      无*/
static void smc_sram_test(uint16_t x, uint16_t y)
{uint32_t i;uint8_t temp;uint8_t sval;lcd_show_string(x, y, 239, y + 16, 16, "Ex Memory Test:   0KB", BLUE);/* 每间隔4KB写入一个数据,总共写入256个数据,刚好为1MB */for (temp=0, i=0; i<(1 * 1024 * 1024); i+=4096){sram_write(&temp, i, 1);temp++;}/* 读出写入的数据进行校验 */for (i=0; i<(1 * 1024 * 1024); i+=4096){sram_read(&temp, i, 1);if (i == 0){sval = temp;}else if (temp <= sval){break;}/* 显示内存容量 */lcd_show_xnum(	x + 15 * 8,y,(uint16_t)(temp - sval + 1) * 4,4,16,0,BLUE);}
}

可以看到,函数smc_sram_test()就是往SRAM中写入数据,然后再读出校验,一次来进行SRAM的读写测试。
44.3 下载验证
在完成编译和烧录操作后,可以看到LCD上显示了本实验的实验信息,此时按下KEY_0按键对SRAM进行读写测试,便可以看到LCD上提示了测试外部SRAM的容量结果,如果一切正常,将提示“Ex Memory Test:1024KB”,其中1024KB也就是开发板板载SRAM的实际容量(1M字节),接着按下KEY_UP按键对SRAM进行读测试,可以看到LCD上不断地刷新显示一串数字,这便是从SRAM中读出的在SRAM初始化后被写入SRAM的250000个数据(0~249999)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/635374.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【备战蓝桥杯】快来学吧~ 图论巩固,Delia的生物考试

蓝桥杯备赛 | 洛谷做题打卡day12 文章目录 蓝桥杯备赛 | 洛谷做题打卡day12最大食物链计数题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示题解代码总的思路&#xff1a;拓扑排序 我的一些话 最大食物链计数 题目背景 你知道食物链吗&#xff1f;Delia 生…

SSM汽车维修管理系统

工具使用情况&#xff1a; eclipsetomcatmysqljdk 技术架构&#xff1a; 后台&#xff1a;springspring mvcmybatis 前台&#xff1a;easyui 功能介绍&#xff1a; 汽车维修管理、车辆接待、维修项目登记、维修领料、质检完工、消费结算 配件管理、财务管理、基础数据管理…

二进制表示(14)

题目 public class Main {public static String con01(int x,int n) {StringBuffer s new StringBuffer();while(x!0) {s.append(x%n);x/n;}return s.reverse().toString();}public static int con02(int x,int n) {StringBuffer s new StringBuffer();int sum 0;while(x!0…

二、VS2019编译的VTK9.0.0 + Qt 5.14.2 环境测试

1. 使用CMake VS2019 编译vtk 9.0.0 时,需要启用支持Qt开关、如下图 如果不会编译的可以参见我的这篇文章: 一、VTK 9.0.0 编译安装步骤 VS2019 CMake3.26.0-CSDN博客 打开Qt5.14.2 ,创建Qt Widget 项目: 构建设置选择 MSVC2017 64bit pro 项目文件加入两行配置: …

鸿蒙开发系列教程(四)--ArkTS语言:基础知识

1、ArkTS语言介绍 ArkTS是HarmonyOS应用开发语言。它在保持TypeScript&#xff08;简称TS&#xff09;基本语法风格的基础上&#xff0c;对TS的动态类型特性施加更严格的约束&#xff0c;引入静态类型。同时&#xff0c;提供了声明式UI、状态管理等相应的能力&#xff0c;让开…

GetShell的姿势

0x00 什么是WebShell 渗透测试工作的一个阶段性目标就是获取目标服务器的操作控制权限&#xff0c;于是WebShell便应运而生。Webshell中的WEB就是web服务&#xff0c;shell就是管理攻击者与操作系统之间的交互。Webshell被称为攻击者通过Web服务器端口对Web服务器有一定的操作权…

javaWebssh运动会管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh运动会管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,M…

Beyond Compare ubuntu 安装

文章目录 参考 具体方法请参考【1】、【2】&#xff0c;亲测有效。 参考 【1】deepin深度系统 BeyondCompare 4.3.4破解教程 【2】Beyond-Compare 4 -linux 破解

Java医药WMS进销存系统

技术架构&#xff1a; jdk8 IntelliJ IDEA maven Mysql5.7 有需要的可以私信我。 系统功能与介绍&#xff1a; 医药进销存系统&#xff0c;主要分两种角色&#xff1a;员工、客户。本系统具有进销存系统的通用性&#xff0c;可以修改为其它进销存系统&#xff0c;如家电进…

JUC并发编程-线程和进程、Synchronized 和 Lock、生产者和消费者问题

1、什么是JUC 源码 官方文档 面试高频问&#xff01; java.util 工具包、包、分类 业务&#xff1a;普通的线程代码 Thread Runnable Runnable 没有返回值、效率相比入 Callable 相对较低&#xff01; 2、线程和进程 线程、进程&#xff0c;如果不能使用一句话说出来的技术…

创建SERVLET

创建SERVLET 要创建servlet,需要执行以下任务: 编写servlet。编译并封装servlet。将servlet部署为Java EE应用程序。通过浏览器访问servlet。编写servlet 要编写servlet,需要扩展HttpServlet接口的类。编写servlet是,需要合并读取客户机请求和返回响应的功能。 读取和处…

Qt 状态机框架:The State Machine Framework (二)

传送门: Qt 状态机框架:The State Machine Framework (一) Qt 状态机框架:The State Machine Framework (二) 1、利用并行态避免态的组合爆炸 假设您想在单个状态机中对汽车的一组互斥属性进行建模。假设我们感兴趣的属性是干净与肮脏,以及移动与不移动。需要四个相互排斥的…

去掉element-ui的el-table的所有边框+表头+背景颜色

实例: 1.去掉table表头(加上:show-header"false") <el-table:data"tableData":show-header"false"style"width: 100%"> </el-table> 2.去掉table所有边框 ::v-deep .el-table--border th.el-table__cell, ::v-deep .el…

【人工智能平台】ubuntu22.04.3部署cube-studio

简介&#xff1a;本次安装是在虚拟机上进行&#xff0c;需要给虚拟机至少分配16GB&#xff0c;分配8GB时系统会卡死。 一、环境&#xff1a; 主机环境&#xff1a;win11&#xff08;全程科学&#xff09;vm虚拟机 虚拟机&#xff1a;ubuntu22.04.3桌面版&#xff08;新装&…

什么是OSPF?为什么需要OSPF?OSPF基础概念

什么是OSPF&#xff1f; 开放式最短路径优先OSPF&#xff08;Open Shortest Path First&#xff09;是IETF组织开发的一个基于链路状态的内部网关协议&#xff08;Interior Gateway Protocol&#xff09;。 目前针对IPv4协议使用的是OSPF Version 2&#xff08;RFC2328&#x…

多维时序 | Matlab实现CNN-BiLSTM-Mutilhead-Attention卷积双向长短期记忆神经网络融合多头注意力机制多变量时间序列预测

多维时序 | Matlab实现CNN-BiLSTM-Mutilhead-Attention卷积双向长短期记忆神经网络融合多头注意力机制多变量时间序列预测 目录 多维时序 | Matlab实现CNN-BiLSTM-Mutilhead-Attention卷积双向长短期记忆神经网络融合多头注意力机制多变量时间序列预测效果一览基本介绍程序设计…

layui文本编译器支持多图上传,图片上传排序,删除图片功能

layui编译器支持多图上传&#xff0c;图片上传排序&#xff0c;删除图片功能 效果图如下&#xff1a; <div class"layui-tab-item"><textarea id"content" class"js-ueditor" name"content"></textarea> </di…

Django使用session管理购物车

购物车允许用户选择产品并设置他们想要订购的数量&#xff0c;然后在他们浏览网站时临时存储这些信息&#xff0c;直到最终下订单。购物车必须在会话中持久化&#xff0c;以便在用户访问期间维护购物车项目。 使用Django的session框架来持久化购物车。购物车将保持在session中&…

微软使其AI驱动的阅读导师免费

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Flutter GetX 之 国际化

今天给大家介绍一下 GetX 的国际化功能,在日常开发过程中,我们经常会使用到国际化功能,需要们的应用支持 国际化,例如我们需要支持 简体、繁体、英文等等。 上几篇文章介绍了GetX的 路由管理 和 状态管理,看到大家的点赞和收藏,还是很开心的,说明这两篇文章给大家起到了…