13.STM32F103C8使用PSRAM64H外扩RAM空间

这篇具有很好参考价值的文章主要介绍了13.STM32F103C8使用PSRAM64H外扩RAM空间。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、简介

最近在调试STM32F103C8驱动墨水屏的实验,在使用过程中,需要使用大内存的RAM需要,由于C8T6的RAM空间只有20KB,而墨水屏的需要的内存为800*480*2/8=93.75KB。

13.STM32F103C8使用PSRAM64H外扩RAM空间,STM32,stm32,单片机,嵌入式硬件,外扩RAM

在网上查了相关的方案,都是使用STM32F103ZE外扩IS62WV51216这种并口SRAM的,使用IS62WV51216需要使用多引脚的STM32F103Zx系列,对于我这种使用背景,不需要上Zx系列,想查找下有没有串口的SRAM方案,但是并没有找到。

网上有成熟的TM32F103Cx系列外扩W25Qxx芯片的方案,但是这是FLASH,不是RAM,也不是我想要的方案。

所以干脆自己做个方案,找到了一块乐鑫的外扩RAM芯片,ESP-PSRAM64H。

13.STM32F103C8使用PSRAM64H外扩RAM空间,STM32,stm32,单片机,嵌入式硬件,外扩RAM

查看其引脚分布,W25Qxx和PSRAM64H的引脚基本一致,都是SPI接口的,并且都支持QSPI。

所以直接使用【WeAct Studio】家的BluePill板子,其自带了W25Qxx接口,但是未焊接,所以直接买了一块,准备焊接PSRAM64进行验证测试。

13.STM32F103C8使用PSRAM64H外扩RAM空间,STM32,stm32,单片机,嵌入式硬件,外扩RAM

使用的STM32库是标准库,为了保证速度,使用的是硬件SPI。

二、使用

2.1 电路图

STM32F103C8核心板W25Qxx电路图

13.STM32F103C8使用PSRAM64H外扩RAM空间,STM32,stm32,单片机,嵌入式硬件,外扩RAM

ESP-PSRAM64的芯片接口

13.STM32F103C8使用PSRAM64H外扩RAM空间,STM32,stm32,单片机,嵌入式硬件,外扩RAM

2.2 代码

2.2.1 SPI

使用的是SPI1的接口,为了保证传输速度,使用硬件SPI而不是软件SPI,所以需要先完成SPI的初始化。相关代码:

#include "spi.h"

void SPI1_Init(void)
{
 	GPIO_InitTypeDef GPIO_InitStructure;
  SPI_InitTypeDef  SPI_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );//PORTA时钟使能 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,  ENABLE );//SPI1时钟使能 	

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PA5/6/7复用推挽输出 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA
 	GPIO_SetBits(GPIOA, GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);  //PA5/6/7上拉
	
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//设置SPI工作模式:设置为主SPI
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//设置SPI的数据大小:SPI发送接收8位帧结构
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;		//串行同步时钟的空闲状态为高电平
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;	//串行同步时钟的第二个跳变沿(上升或下降)数据被采样
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;		//定义波特率预分频的值:波特率预分频值为256
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
	SPI_InitStructure.SPI_CRCPolynomial = 7;	//CRC值计算的多项式
	SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
 
	SPI_Cmd(SPI1, ENABLE); //使能SPI外设
	
	SPI1_ReadWriteByte(0xff);//启动传输
//	SPI1_SetSpeed(SPI_BaudRatePrescaler_2);//设置为18M时钟,高速模式
}

//SPI 速度设置函数
//SpeedSet:
//SPI_BaudRatePrescaler_2   2分频   
//SPI_BaudRatePrescaler_8   8分频   
//SPI_BaudRatePrescaler_16  16分频  
//SPI_BaudRatePrescaler_256 256分频 
void SPI1_SetSpeed(u8 SPI_BaudRatePrescaler)
{
  assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
	SPI1->CR1&=0XFFC7;
	SPI1->CR1|=SPI_BaudRatePrescaler;	//设置SPI1速度 
	SPI_Cmd(SPI1, ENABLE); 
}

//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI1_ReadWriteByte(u8 TxData)
{		
	u8 retry=0;				 	
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
	{
		retry++;
		if(retry>200)return 0;
	}
	SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个数据
	retry=0;

	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
	{
		retry++;
		if(retry>200)return 0;
	}
	return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据					    
}

2.2.2 PSRAM64

psram64.c文件

#include "psram64.h"
#include "spi.h"
#include "usart.h"
#include "delay.h"

/*
CS<--->PA4
SCLK<--->PA5
MISO<--->PA6
MOSI<--->PA7
*/

u8 PSRAM64_ReadID(void)
{
	u8 MFID,KGD,EID[6],i;
	PSRAM64_CS=0;
	SPI1_ReadWriteByte(0x9F);//发送读取ID命令	    
	SPI1_ReadWriteByte(0x00);
	SPI1_ReadWriteByte(0x00);
	SPI1_ReadWriteByte(0x00);
	MFID = SPI1_ReadWriteByte(0xFF);
	KGD = SPI1_ReadWriteByte(0xFF);
	for(i=0; i<6; i++)
		EID[i] = SPI1_ReadWriteByte(0xFF);
	PSRAM64_CS=1;
	printf("MDIF=0x%02X\r\n", MFID);
	printf("KGD=0x%02X\r\n", KGD);
	printf("EID=0x%02X%02X%02X%02X%02X%02X\r\n",EID[0],EID[1],EID[2],EID[3],EID[4],EID[5]);
	return KGD;
}

void PSRAM64_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)
{
	u16 i;
	PSRAM64_CS=0;
	SPI1_ReadWriteByte(PSRAM64_ReadData);       //写读数据命令
	SPI1_ReadWriteByte((u8)((ReadAddr)>>16));  	//写读数据地址  
	SPI1_ReadWriteByte((u8)((ReadAddr)>>8));
	SPI1_ReadWriteByte((u8)ReadAddr);
	for(i=0;i<NumByteToRead;i++)								//读数据
	{
		pBuffer[i]=SPI1_ReadWriteByte(0XFF);
	}
	PSRAM64_CS=1;
}

void PSRAM64_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToRead)
{
	u16 i;
	PSRAM64_CS=0;
	SPI1_ReadWriteByte(PSRAM64_WriteData);       	//写写数据命令
	SPI1_ReadWriteByte((u8)((WriteAddr)>>16));  	//写写数据地址
	SPI1_ReadWriteByte((u8)((WriteAddr)>>8));
	SPI1_ReadWriteByte((u8)WriteAddr);
	for(i=0;i<NumByteToRead;i++)							//写数据
	{ 
		SPI1_ReadWriteByte(pBuffer[i]);
	}
	PSRAM64_CS=1;
}

void PSRAM64_DataReset(u32 WriteAddr,u16 NumByteToRead)
{
	u16 i;
	PSRAM64_CS=0;
	SPI1_ReadWriteByte(PSRAM64_WriteData);        //写写数据命令
	SPI1_ReadWriteByte((u8)((WriteAddr)>>16));  	//写写数据地址
	SPI1_ReadWriteByte((u8)((WriteAddr)>>8));
	SPI1_ReadWriteByte((u8)WriteAddr);
	for(i=0;i<NumByteToRead;i++)								//复位数据,写0x00
	{ 
		SPI1_ReadWriteByte(0x00);
	}
	PSRAM64_CS=1;
}

void PSRAM64_Reset(void)
{
	PSRAM64_CS=0;
	SPI1_ReadWriteByte(PSRAM64_RESET_ENABLE);   //复位使能
	SPI1_ReadWriteByte(PSRAM64_RESET_CMD);  		//复位
	PSRAM64_CS=1;
}

u8 PSRAM64_Test(void)
{
	u32 addr=0,data,ret=0;
	for(addr=0; addr<PSRAM64_SIZE; addr+=4)
	{
		PSRAM64_Write((u8*)&addr, addr, 4);
		if((addr&0xFFFF)==0)
			printf("write %d/%d\r\n", addr>>16, PSRAM64_SIZE>>16);
	}
	for(addr=0; addr<PSRAM64_SIZE; addr+=4)
	{
		PSRAM64_Read((u8*)&data, addr, 4);
		if(data!=addr)
		{
			printf("read error, addr(0x%08X),data(0x%08X)\r\n", addr, data);
			ret++;
		}
		if((addr&0xFFFF)==0)
			printf("read %d/%d\r\n", addr>>16, PSRAM64_SIZE>>16);
	}
	if(ret==0)
		printf("PSRAM64 测试成功\r\n");
	else
		printf("PSRAM64 测试失败,ret(%d)\r\n",ret);
	return ret;
}

void PSRAM64_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );//PORTA时钟使能 

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;  // PA4 推挽 
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);
 	GPIO_SetBits(GPIOA, GPIO_Pin_4);
	PSRAM64_CS=1;				//SPI FLASH不选中
	
	SPI1_Init();
	
	delay_ms(10);
	PSRAM64_Reset();
	PSRAM64_ReadID();
	
	PSRAM64_Test();
}

实现了对PSRAM64的测试,按照4字节为单位,对整块芯片的内存进行写,再对写入的数据进行读,对比写入的数据和读出的数据是否一致。

psram64.h文件

#ifndef __PSRAM64_H__
#define __PSRAM64_H__	 
#include "sys.h"

//容量:64Mb=8MB
#define PSRAM64_SIZE 					8388608//8*1024*1024

#define PSRAM64_ReadData			0x03
#define PSRAM64_WriteData			0x02
#define PSRAM64_RESET_ENABLE	0x66
#define PSRAM64_RESET_CMD			0x99


#define	PSRAM64_CS 		PAout(4)  		//PSRAM64的片选信号


u8 PSRAM64_ReadID(void);
void PSRAM64_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead);
void PSRAM64_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToRead);
void PSRAM64_DataReset(u32 WriteAddr,u16 NumByteToRead);
void PSRAM64_Init(void);
#endif

三、测试结果

3.1 读取ID及写数据

13.STM32F103C8使用PSRAM64H外扩RAM空间,STM32,stm32,单片机,嵌入式硬件,外扩RAM

3.2 读数据

13.STM32F103C8使用PSRAM64H外扩RAM空间,STM32,stm32,单片机,嵌入式硬件,外扩RAM文章来源地址https://www.toymoban.com/news/detail-607762.html

四、后记

  1. PSRAM64也是支持QSPI的,但是由于目前对QSPI不太熟悉,并且F103也不支持QSPI,后续准备使用QSPI完成对此芯片的读取。
  2. 对于数据手册中的多种读取方式并没有深入了解,不太明白相关概念,后续有机会再继续研究。比如32字节/1K字节突发wrap模式,不太明白是什么意思。也不太清楚低频率和高频率的读是什么区别。
  3. 对于其他外扩串口RAM芯片,比如LY68L6400、APS6404L,也需要完成相关功能的验证。

到了这里,关于13.STM32F103C8使用PSRAM64H外扩RAM空间的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 手把手带你使用ESP8266 与 STM32F103C8实现网络服务器

    随着现在物联网设备的而越来越多,现在市场上出现越来越多的物联网设备,其中 ESP8266 是最受欢迎、价格便宜且易于使用的模块,它可以将您的硬件连接到互联网。 今天我们就以ESP8266和STM32来实现一台网络服务器,我们使用 ESP8266 将 STM32F103C8 连接到互联网。 ESP8266 Wi-Fi 模

    2024年01月23日
    浏览(30)
  • 直流减速编码电机的使用(STM32f103c8t6)L298N电机驱动模块

    直接减速电机就是在直流电机上加上霍尔编码器,霍尔编码器可用于电机转动的测速,A、B相会产生相位相差90°的方波信号。stm32可以使用硬件资源或者软件模拟来捕获编码器信号。这里我介绍的是stm32自带的编码器模式来使用直流减速电机。 以下是直流减速电机的商品图 ​

    2024年02月13日
    浏览(46)
  • 【STM32】使用RTE ,从 0 开始创建一个 (keil) ARM MDK工程(纯keil,标准库,以STM32F103C8T6为例)

    学习相关的基础知识请阅读本专栏其他文章,一定有你想要的。 https://blog.csdn.net/weixin_43764974/category_11021363.html 本文软硬件: STM32F103C8T6 ARM MDK 5.38 ARM complier 6 ST-Link v2 StdPeriph Drivers(标准库) 文章开始前,我想再次说一下: keil 、 μvision 、 ARM MDK 这几个名词(尽管前面的额文

    2024年02月16日
    浏览(29)
  • STM32---stm32f103c8t6与stm32f103zet6之间的代码移植转换

    目录 一、将c8t6转换为zet6 1、修改启动文件 2、修改芯片 3、将MD修改为HD  4、下载器的修改 5、修改完成,编译成功  二、将zet6转换为c8t6 最终结果如下:   将STM32F103C8改为STM32F103ZE   基本相同,反向即可。    

    2024年02月06日
    浏览(45)
  • stm32f103VET6和stm32f103c8t6有什么区别?

    我来终结下这个问题。 这两款单片机我都用过,其中无际单片机特训营其中一款wifi报警主机项目就是用了stm32f103c8t6。  stm32f103VET6和stm32f103c8t6都是STMicroelectronics公司推出基于ARM Cortex-M3内核的单片机。 它们在硬件规格和性能上存在一些差异,下面我详细讲解下它们的差异之处

    2024年02月15日
    浏览(37)
  • STM32CubeMX配置--STM32F103C8T6最小系统板

    首先是新建工程选择左上角的 File 然后点击 NewProject ,或者直接使用快捷键 Ctrl+N 新建工程 然后选择开发板型号,在 Commercial Part Number 处输入 STM32F103C8T6 然后在下方会有选择 直接双击型号 就会进入配置界面 PINoutConfiguration (1)RCC修改 首先点击左上角的 System Core 然后点击

    2024年02月04日
    浏览(51)
  • 使用USB转TTL下载器将固件烧写到STM32F103C8T6最小系统板中

    ch340驱动下载地址: https://www.wch.cn/download/CH341SER_EXE.html mcuisp下载地址: 百度云盘资源: 链接:https://pan.baidu.com/s/1TuecWD0T1HTMkEpobuesFw 提取码:visk Flymcu下载地址: 百度云盘资源 链接:https://pan.baidu.com/s/1VxMUZFOVvpAf-L_YbATMag 提取码:fasf usb转TTL下载器的跳线帽接3V3 开发板BOOT0跳线

    2024年01月18日
    浏览(35)
  • 舵机控制(STM32F103C8T6)

            本文是以 STM32F103C8T6 作为主控芯片,通过PB6端口输出PWM,实现控制180°舵机。 (一)概述         舵机是一种位置伺服驱动器器,是一种带有输出轴的小装置。当我们向伺服器发送一个控制信号时,输出轴就可以转到特定的位置。只在控制信号持续不变,伺服机构就

    2023年04月09日
    浏览(41)
  • STM32F103C8T6系统板

    1.电源部分 2.复位 3.晶振 4. 电源电路——防反接 有关二极管 漫谈二极管防电源反接电路 本次采用上图右下角的NMOS防反接电路。 电源电路——电源芯片 AMS1117是AMS公司的 ,LM1117是NS(美国国家半导体)的,LM1117要贵很多,所以一般的用AMS1117就可以了。 (以下分析参考STM32F10

    2024年02月02日
    浏览(58)
  • 功耗测评 | STM32F103C8T6

    STM32F103C8T6 MCU越来越广泛的应用在生产生活的各个领域,外接丰富的传感器、功能模块、通信模块、显示存储等可以形成各种可样的产品项目应用。对于功耗要求比较高的产品,一般会选择STM32L系列的MCU,但是从功耗的评测角度,逻辑上是基本相似的。 在很多应用场合中都对

    2024年02月07日
    浏览(33)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包