STM32使用SRAM扩展内存

2023-11-02

目录

 

一、SRAM介绍

二、STM32F103系列的FSMC模块

 三、初始化配置及数据访问

四、使全局变量定义在外部SRAM中的方法

五、参考文章及资料


一、SRAM介绍

SRAM(Static Random-Access Memory)即静态随机存取存储器,所谓“静态”是指这种存储器只要保持通电,里面存储的数据就可以一直保持,但是掉电之后就会丢失。与DRAM(动态随机存取存储器)相比它不需要周期性的刷新里面的数据,操作简单,速度更快,但是更加的昂贵,集成度不如DRAM高。

本文使用的SRAM型号为 IS62WV51216,是 ISSI(Integrated Silicon Solution, Inc)公司生产的一颗16位宽 1M字节容量的CMOS静态内存芯片。

SRAM芯片(IS62WV51216)

 

IS62WV51216引脚图

 

IS62WV51216引脚描述

地址线A0到A18寻址空间是512K,因为数据宽度为16位即两个字节,所以512K*2Byte = 1MB容量。LB和UB的功能是控制高低字节的数据有效性,真值表如下:

真值表

 

二、STM32F103系列的FSMC模块

FSMC(Flexible Static Memory Controller)即可变静态存储控制器,通俗的来说是STM32的一个强大的总线控制模块,它将AHB传输信号转换到适当的外部设备协议,满足访问外部设备的时序要求。FSMC将不同的功能映射到了不同的虚拟内存块上,我们实际编程中只需要简单地往特定的虚拟内存上读写数据,便可以实现对外部模块的数据读写操作了,中间的协议操作过程由FSMC模块完成。FSMC模块涉及引脚非常的多,所以只在STM32的大容量产品上才有,我使用的型号是STM32F103ZET6。其中FSMC模块的框图如下:

STM32F103系列FSMC框图

 根据框图,FSMC又分为以下四个存储块:

FSMC存储块

我们需要用来操作哪一类的设备就用哪一部分对应的存储块,当然并不是只有图上列的这四个设备才支持,其实一个设备的操作时序只要和以上几类设备基本相似,能够互相兼容就一样可以用这个模块进行操作,就像操作TFT彩屏可以用块1一样,因为TFT的操作时序和SRAM类似。

这里选择块1来操作,然后根据芯片手册的描述,块1最大支持对4个SRAM模块的操作,所以块1又在内部被平均划分为了4小块。所以最大支持的单片SRAM为64MB。

块1的4个区域

 因为我的开发板用FSMC_NE3来做SRAM模块的片选引脚,所以我只能用“存储块1 NOR/PSRAM 3”这个区域来操作SRAM模块了,开发板上连线如下:

SRAM芯片连线(IS62WV51216)

 

 三、初始化配置及数据访问

1、初始化代码

初始化代码如下:


/****************************************************************************
* Function Name  : SRAM_Config
* Description    : 初始化FSMC
* Input          : None
* Output         : None
* Return         : None
****************************************************************************/

void SRAM_Config(void)
{  	
	/* 初始化函数 */
	GPIO_InitTypeDef GPIO_InitStructure;
	FSMC_NORSRAMInitTypeDef        FSMC_NORSRAMInitStructure;
	FSMC_NORSRAMTimingInitTypeDef  FSMC_NORSRAMTiming;

/*--------------------------------------------------------------------------------*/
/*------------------- GPIO Config ------------------------------------------------*/
/*--------------------------------------------------------------------------------*/	
	/* 打开时钟使能 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD  | RCC_APB2Periph_GPIOE
	                      | RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG,
						   ENABLE);

	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5
	                            | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 
								| GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
								
	GPIO_Init(GPIOD, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_7 | GPIO_Pin_8
	                            | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 
								| GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
								
	GPIO_Init(GPIOE, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3
	                            | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_12 
								| GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; 
	
    GPIO_Init(GPIOF, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 
	                            | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_10; 

	GPIO_Init(GPIOG, &GPIO_InitStructure);

/* ------------------------------------------------------------------------------ */
/* ------------ FSMC Config ----------------------------------------------------- */
/* ------------------------------------------------------------------------------ */
	/* 设置读写时序,给FSMC_NORSRAMInitStructure调用 */
	/* 地址建立时间,1个HCLK周期, 1/36M = 27ns */
	FSMC_NORSRAMTiming.FSMC_AddressSetupTime = 0x00;

	/* 地址保持时间,1个HCLK周期 */
	FSMC_NORSRAMTiming.FSMC_AddressHoldTime = 0x00;

	/* 数据建立时间,63个HCLK周期 4/72 = 55ns */
	FSMC_NORSRAMTiming.FSMC_DataSetupTime = 0x03;

	/* 数据保持时间,1个HCLK周期 */
	FSMC_NORSRAMTiming.FSMC_DataLatency = 0x00;

	/* 总线恢复时间设置 */
	FSMC_NORSRAMTiming.FSMC_BusTurnAroundDuration = 0x00;
	
	/* 时钟分频设置 */
	FSMC_NORSRAMTiming.FSMC_CLKDivision = 0x00;

	/* 设置模式,如果在地址/数据不复用时,ABCD模式都区别不大 */
	FSMC_NORSRAMTiming.FSMC_AccessMode = FSMC_AccessMode_A;

	/* 设置FSMC_NORSRAMInitStructure的数据 */
	/* FSMC有四个存储块(bank),我们使用第一个(bank1) */
	/* 同时我们使用的是bank里面的第 3个RAM区 */
	FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;

	/* 这里我们使用SRAM模式 */
	FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;

	/* 使用的数据宽度为16位 */
	FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
	
	// FSMC_BurstAccessMode_Disable;
	FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
	FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;
	FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
	FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;  
	FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; 
	FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;

	/* 设置写使能打开 */
	FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;

	/* 选择拓展模式使能,即设置读和写用相同的时序 */
	FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
	
	/* 设置地址和数据复用使能不打开 */
	FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
	
	/* 设置读写时序 */
	FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTiming;
	
	/* 设置写时序 */
	FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTiming;

	/* 打开FSMC的时钟 */
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
	 
	FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); 

	/*!< Enable FSMC Bank1_SRAM Bank */
	FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);
}

因为我们使用的是块1(Bank1)的第3个RAM区域,这块区域的内存映射是0x68000000到0x6BFFFFFF,所以我们可以简单的理解为外部SRAM模块的1MB数据空间被映射到了以0x68000000地址为起始的后1MB字节空间中了,我们存取数据的时候直接用个指针指向这片区域进行数据的存取操作就可以了,具体的协议操作不用我们操心了。

/* 定义SRAM的地址 */
#define Bank1_SRAM3_ADDR    ((vu32)(0x68000000))   
vu16 wReadVal;

*(vu16 *)Bank1_SRAM3_ADDR = 1;  //写外部SRAM
wReadVal = *(vu16 *)Bank1_SRAM3_ADDR;  //读外部SRAM

2、不同数据位宽的访问操作

因为现在这个SRAM模块是16位宽的,所以使用的时候用了“uint16_t”这样的指针对应地去访问,那么是否能进行单字节或者四字节甚至任意字节数据位宽的访问操作呢?

针对这个问题,《STM32中文参考手册》里有明确的说明,下面我摘抄一段:

19.3 AHB接口
AHB接口为内部CPU和其它总线控制设备访问外部静态存储器提供了通道。
AHB操作被转换到外部设备的操作。当选择的外部存储器的数据通道是16或8位时,在AHB上的
32位数据会被分割成连续的16或8位的操作。
AHB时钟(HCLK)是FSMC的参考时钟。
19.3.1 支持的存储器和操作
一般的操作规则
请求AHB操作的数据宽度可以是8位、 16位或32位,而外部设备则是固定的数据宽度,此时需要
保障实现数据传输的一致性。
因此, FSMC执行下述操作规则:
● AHB操作的数据宽度与存储器数据宽度相同:无数据传输一致性的问题。
● AHB操作的数据宽度大于存储器的数据宽度:此时FSMC将AHB操作分割成几个连续的较小
数据宽度的存储器操作,以适应外部设备的数据宽度。
● AHB操作的数据宽度小于存储器的数据宽度:
依据外部设备的类型,异步的数据传输有可能不一致。
─ 与具有字节选择功能的存储器(SRAM、 ROM、 PSRAM等)进行异步传输时, FSMC执行
读写操作并通过它的字节通道BL[1:0]访问正确的数据。
─ 与不具有字节选择功能的存储器(NOR和16位NAND等)进行异步传输时,即需要对16位宽
的闪存存储器进行字节访问;显然不能对存储器进行字节模式访问(只允许16位的数据传
输),因此:
a. 不允许进行写操作
b. 可以进行读操作(控制器读出完整的16位存储器数据,只使用需要的字节)。


看了以上的描述,因为IS62WV51216是有LB和UB引脚的,可以控制字节的有效性,所以编程操作的时候我们是可以进行任意字节位宽的数据操作的。如果换作其他不支持字节通道访问的芯片的话,那就需要对齐芯片的数据位宽进行数据操作了。在网上查资料时看到有人问“在操作不同的数据位宽时,FSMC_NBL1,FSMC_NBL0是受什么控制输出高低电平给UB,LB的?”,这个应该是属于硬件自动实现的,是FSMC的硬件机制。

3、FSMC引脚如何与SRAM芯片的物理引脚对应

19.4.1 NOR和PSRAM地址映像
HADDR[27:26]位用于选择四个存储块之一:
表86 NOR/PSRAM存储块选择
HADDR[27:26](1) 选择的存储块
00 存储块1 NOR/PSRAM 1
01 存储块1 NOR/PSRAM 2
10 存储块1 NOR/PSRAM 3
11 存储块1 NOR/PSRAM 4
(1) HADDR是需要转换到外部存储器的内部AHB地址线。
HADDR[25:0]包含外部存储器地址。 HADDR是字节地址,而存储器访问不都是按字节访问,因
此接到存储器的地址线依存储器的数据宽度有所不同,如下表:
表87 外部存储器地址
数据宽度(1) 连到存储器的地址线 最大访问存储器空间(位)
8位 HADDR[25:0]与FSMC_A[25:0]对应相连 64M字节 x 8 = 512 M位
16位 HADDR[25:1]与FSMC_A[24:0]对应相连, HADDR[0]未接 64M字节/2 x 16 = 512 M位
(1) 对于16位宽度的外部存储器, FSMC将在内部使用HADDR[25:1]产生外部存储器的地址FSMC_A[24:0]。不
论外部存储器的宽度是多少(16位或8位), FSMC_A[0]始终应该连到外部存储器的地址线A[0]。
NOR闪存和PSRAM的非对齐访问支持
每个NOR闪存或PSRAM存储器块都可以配置成支持非对齐的数据访问。
在存储器一侧,依据访问的方式是异步或同步,需要考虑两种情况:
● 异步模式:这种情况下,只要每次访问都有准确的地址,完全支持非对齐的数据访问。
● 同步模式:这种情况下, FSMC只发出一次地址信号,然后成组的数据传输通过时钟CLK顺
序进行。
某些NOR存储器支持线性的非对齐成组访问,固定数目的数据字可以从连续的以N为模的地
址读取(典型的N为8或16,可以通过NOR闪存的配置寄存器设置)。此种情况下,可以把存
储器的非对齐访问模式设置为与AHB相同的模式。
如果存储器的非对齐访问模式不能设置为与AHB相同的模式,应该通过FSMC配置寄存器的相
应位禁止非对齐访问,并把非对齐的访问请求分开成两个连续的访问操作。

这句话很重要“ 对于16位宽度的外部存储器, FSMC将在内部使用HADDR[25:1]产生外部存储器的地址FSMC_A[24:0]。不论外部存储器的宽度是多少(16位或8位), FSMC_A[0]始终应该连到外部存储器的地址线A[0]”。所以FSMC的地址线和实际SRAM地址线相连的时候不需要错位相连。

 

四、使全局变量定义在外部SRAM中的方法

1、修改system_stm32f10x.c

在system_stm32f10x.c系统文件中,有个叫SystemInit_ExtMemCtl的函数,就是专门为扩展RAM而设计的函数,该函数是在main()函数之前被执行的,它主要完成FSMC总线的配置。我们需要在这个函数里面调用外部SRAM的初始化函数。主要步骤如下:

(1)在system_stm32f10x.c中添加宏定义DATA_IN_ExtSRAM,启用SystemInit_ExtMemCtl函数。

(2)声明初始化函数:extern void SRAM_Config(void);

(3)在SystemInit_ExtMemCtl函数最后调用SRAM_Config();

#define DATA_IN_ExtSRAM
#ifdef DATA_IN_ExtSRAM
/**
  * @brief  Setup the external memory controller. 
  *         Called in startup_stm32f10x_xx.s/.c before jump to main.
  * 	      This function configures the external SRAM mounted on STM3210E-EVAL
  *         board (STM32 High density devices). This SRAM will be used as program
  *         data memory (including heap and stack).
  * @param  None
  * @retval None
  */ 
extern void SRAM_Config(void);
void SystemInit_ExtMemCtl(void) 
{
/*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is 
  required, then adjust the Register Addresses */

  /* Enable FSMC clock */
  RCC->AHBENR = 0x00000114;
  
  /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */  
  RCC->APB2ENR = 0x000001E0;
  
/* ---------------  SRAM Data lines, NOE and NWE configuration ---------------*/
/*----------------  SRAM Address lines configuration -------------------------*/
/*----------------  NOE and NWE configuration --------------------------------*/  
/*----------------  NE3 configuration ----------------------------------------*/
/*----------------  NBL0, NBL1 configuration ---------------------------------*/
  
  GPIOD->CRL = 0x44BB44BB;  
  GPIOD->CRH = 0xBBBBBBBB;

  GPIOE->CRL = 0xB44444BB;  
  GPIOE->CRH = 0xBBBBBBBB;

  GPIOF->CRL = 0x44BBBBBB;  
  GPIOF->CRH = 0xBBBB4444;

  GPIOG->CRL = 0x44BBBBBB;  
  GPIOG->CRH = 0x44444B44;
   
/*----------------  FSMC Configuration ---------------------------------------*/  
/*----------------  Enable FSMC Bank1_SRAM Bank ------------------------------*/
  
  FSMC_Bank1->BTCR[4] = 0x00001011;
  FSMC_Bank1->BTCR[5] = 0x00000200;
	
	SRAM_Config();
}
#endif /* DATA_IN_ExtSRAM */

 添加完之后就可以像片内RAM一样自由的使用外部的SRAM了。

 

 2、配置KEIL选项

我在main.c里定义了两个数组如下:

char bTest1[1024];
char bTest2[1024 * 8];

编译一下工程打开map文件查看数组存放的地址如下图,这里要提醒一下,这两个数组需要在程序中调用一下,要不然map文件中是找不到这两个数组的,也就是编译器优化掉了这两个数组:

    bTest1                                   0x200010b0   Data        1024  main.o(.bss)
    bTest2                                   0x200014b0   Data        8192  main.o(.bss)

因为片内RAM地址是从0x20000000开始的,所以这两个数组都是放在片内RAM的。接下来选择Option for Target -> Target选项卡,在红框中的RAM1位置填写好Start和Size的值,分别为0x68000000(片外SRAM的起始)和0x100000(1M字节的SRAM容量)。然后点击“OK”就配置好可以使用片外的SRAM了。

 右键main.c文件在菜单中选择Option for File选项。

 在Properties选项卡中的Zero Initialized Data中选择我们刚刚设置的RAM1,就可以将main.c文件中的所有全局变量都定义在外部SRAM中了。

 编译工程后这两个数组位置发生了变化,如下图:

    bTest1                                   0x68000000   Data        1024  main.o(.bss)
    bTest2                                   0x68000400   Data        8192  main.o(.bss)

 注意点:(1)这两个数组不要在外部SRAM初始化之前调用,否则会出现问题。

                (2)局部变量不支持指定地址的定义。

 

 3、在代码中指定

在代码中指定虽然有点麻烦,但是比较灵活,就是在变量后加上“__attribute__((at(具体的地址)))”,如下:

char cnt __attribute__((at(0x20008000)));
char bTest1[1024] __attribute__((at(0x20008003)));
char bTest2[1024 * 8] __attribute__((at(0x68000000)));

 内存地址如下:

    cnt                                      0x20008000   Data           1  main.o(.ARM.__AT_0x20008000)
    bTest1                                   0x20008003   Data        1024  main.o(.ARM.__AT_0x20008003)
    bTest2                                   0x68000000   Data        8192  main.o(.ARM.__AT_0x68000000)

注意点

(1)在外部SRAM初始化之前不要去调用定义在外部SRAM地址处的变量。

(2)针对不同的ARM编译器,定义语句不同:

a、针对AC5(ARMCC Compiler version 5.x)

uint8_t cnt __attribute__((at(0x20008000)));

b、 针对AC6(ARM Compiler 6 (又名ARMCLANG))

uint8_t cnt __attribute__((section(".ARM.__at_0x20008000")));

 (3)指定函数的存放地址

对于变量,在其后边加修饰;而对于函数,在声明处加修饰,注意,是在声明处,不是在函数定义处!!!变量指定的地址只能位于RAM区,常量和代码只能位于Flash区。

如果还想了解更多,可以学习“分散加载文件配置”的相关知识。

 

五、参考文章及资料

1、参考文章

《如何将变量存储在指定内存地址(基于Keil MDK-ARM)》https://blog.csdn.net/ybhuangfugui/article/details/94419544

《超简单!在Keil中指定某个函数或变量存放的地址》 https://blog.csdn.net/oLiShuTong/article/details/78816408

使用SDRAM扩展内存的方法基本上是一样的,但是F1系列的FSMC是不支持SDRAM的,F4系列是支持的,下面是使用SDRAM扩展内存的一些参考文章,讲的很详细: 

《STM32F429 >> 22. FMC_扩展外部SDRAM(一)》 https://blog.csdn.net/weixin_40973138/article/details/87902173

《STM32F429 >> 22. FMC_扩展外部SDRAM(二)》 https://blog.csdn.net/weixin_40973138/article/details/87905431

 

2、资料链接

《IS62WV51216.pdf》

《STM32中文参考手册_V10.pdf》

 链接:https://pan.baidu.com/s/1GN6LWIGkOmUC88t4oLL21Q  提取码:4j8o

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32使用SRAM扩展内存 的相关文章

  • 如何在 Cortex-M3 (STM32) 上从 RAM 执行函数?

    我正在尝试从 Cortex M3 处理器 STM32 上的 RAM 执行函数 该函数会擦除并重写内部闪存 所以我肯定需要在 RAM 中 但我该怎么做呢 我尝试过的是 使用 memcpy 将函数复制到 RAM 中的字节数组 检查它是否正确对齐
  • 在没有 IDE 的情况下如何使用 CMSIS?

    我正在使用 STM32F103C8T6 并想使用 CMSIS 这本质上只是寄存器定义 没有代码 让我的生活更轻松 同时仍保持在较低水平 问题是我不知道如何安装该库以便在命令行上使用 Makefile 使用 所有文档似乎都与特定于供应商的 I
  • 在 MCU 内部 FLASH 中从一个固件跳转到另一个固件

    我目前正在开发针对 STM32F030C8 的引导加载程序固件应用程序 我在分散文件中指定引导加载程序应用程序将占用主内存位置 0x08000000 到 0x08002FFF 扇区 0 到扇区 2 我还编写了一个主固件应用程序 存储在0x0
  • CMSIS 库是否应该包含在版本控制中? [复制]

    这个问题在这里已经有答案了 通常 我曾经在版本控制中包含芯片供应商 ST 提供的设备特定标头和源以及 CMSIS Core 标头 数量不多 也没有更新的习惯 我使用STM32微控制器 但我不使用立方体框架 or the 标准外设库 最近 我
  • 当数据大小较小时,内存到内存 DMA 传输是否需要权衡?

    我正在学习 STM32 F4 微控制器 我正在尝试找出使用 DMA 的限制 根据我的理解和研究 我知道如果数据量较小 即设备使用DMA生成或消耗少量数据 则开销会增加 因为DMA传输需要DMA控制器执行操作 从而不必要地增加系统成本 我做了
  • 140-基于stm32单片机智能晾衣杆控制系统Proteus仿真+源程序

    资料编号 140 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 ds1302时钟 光敏传感器 蜂鸣器 LED灯 制作一个基于stm32单片机智能晾衣杆控制系统Proteus仿真 2 通过光敏传感器
  • 133-基于stm32单片机停车场车位管理系统Proteus仿真+源程序

    资料编号 133 一 功能介绍 1 采用stm32单片机 4位数码管 独立按键 制作一个基于stm32单片机停车场车位管理系统Proteus仿真 2 通过按键进行模拟车辆进出 并且通过程序计算出当前的剩余车位数量 3 将剩余的车位数量显示到
  • STM32 GPIO工作原理详解

    STM32 GPIO介绍 1 STM32引脚说明 GPIO是通用输入 输出端口的简称 是STM32可控制的引脚 GPIO的引脚与外部硬件设备连接 可实现与外部通讯 控制外部硬件或者采集外部硬件数据的功能 以STM32F103ZET6芯片为例
  • 硬件基础-电容

    电容 本质 电容两端电压不能激变 所以可以起到稳定电压作用 充放电 电容量的大小 想使电容容量大 使用介电常数高的介质 增大极板间的面积 减小极板间的距离 品牌 国外 村田 muRata 松下 PANASONIC 三星 SAMSUNG 太诱
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • STM32的HAL中实现单按、长按和双按功能

    我正在尝试实现单击 双击和长按功能来执行不同的功能 到目前为止 我已经理解了单击和长按的逻辑 但我不知道如何检测双击 至于代码 我使用计数器实现了单击和长按 但代码仅停留在第一个 if 条件上 bool single press false
  • STM32F207 I2C 测试失败

    我正在使用 STM32F207 微控制器在 STM3220G EVAL 板上学习嵌入式开发 我尝试通过连接同一芯片上的两个 I2C2 和 I2C3 模块并发送 接收字符来测试 I2C 接口 这是我当前编写的代码 使用 mdk arm 5 i
  • STM32F4XX的12位ADC采集数值超过4096&右对齐模式设置失败

    文章目录 一 前言 二 问题1 数值超过4096 三 问题1的排错过程 四 问题2 右对齐模式设置失败 五 问题2的解决方法 5 1 将ADC ExternalTrigConv设置为0 5 2 使用ADC StructInit 函数 一 前
  • for循环延时时间计算

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 之前做led点亮的实验 好像是被delay函数影响了 因为delay参数设置的不对
  • 嵌入式开发--STM32G4系列片上FLASH的读写

    这个玩意吧 说起来很简单 就是几行代码的事 但楞是折腾了我大半天时间才搞定 原因后面说 先看代码吧 读操作 读操作很简单 以32位方式读取的时候是这样的 data IO uint32 t 0x0800F000 需要注意的是 当以32位方式读
  • systick定时器

    systick定时器 文章目录 前言 一 前期疑惑 二 解答 1 关于systick是阻塞的吗 2 非阻塞 三 软件编写 总结 前言 这边记录systick相关知识点 一 前期疑惑 在学习systick志气啊 其实对于systick还是一脸
  • STM32内部时钟

    我对 STM32F7 设备 意法半导体的 Cortex M7 微控制器 上的时钟系统感到困惑 参考手册没有充分阐明这些时钟之间的差异 SYSCLK HCLK FCLK 参考手册中阅读章节 gt RCC 为 Cortex 系统定时器 SysT
  • 使用 STM32 USB 设备库将闪存作为大容量存储设备

    我的板上有这个闪存IC 它连接到我的STM32F04 ARM处理器 处理器的USB端口可供用户使用 我希望我的闪存在通过 USB 连接到 PC 时被检测为存储设备 作为第一步 我在程序中将 USB 类定义为 MSC 效果很好 因为当我将主板
  • STM32 传输结束时,循环 DMA 外设到存储器的行为如何?

    我想问一下 在以下情况下 STM32 中的 DMA SPI rx 会如何表现 我有一个指定的 例如 96 字节数组 名为 A 用于存储从 SPI 接收到的数据 我打开循环 SPI DMA 它对每个字节进行操作 配置为 96 字节 是否有可能

随机推荐

  • 【转载】odoo技术开发白皮书 第一部分 第九章 权限

    转载 http book odoomommy com chapter1 README8 html 第九章 权限 Odoo的权限管理 从粗到细可以大概分为四个等级 对象级 视图级 字段级 记录级 什么意思呢 总结起来大概如下面的描述 对象级
  • 大家的毕业设计怎么做的?跟我一样吗?无极低码说你:只管建库建表,剩下的交给我

    首先呢 介绍一下无敌低代码平台 无极低代码平台是作者自己搭建的一个框架 刚开始由3行代码写服务升级而来 3行代码写服务当然也是作者自己写的 目的就是为了减少基础的开发工作 让不会后端开发的人员能够通过简单的步骤实现服务接口的编写 后面觉得3
  • 对比 Exception 和 Error,运行时异常与一般异常有什么区别?

    相同点 Exception 和 Error 都是继承了 Throwable 类 在 Java 中只有 Throwable 类型的实例才可以被抛出 throw 或者捕获 catch 它是异常处理机制的基本组成类型 Exception 和 Er
  • vue5种方式实现页面“刷新“

    vue中五种方式实现页面 刷新 1 使用window location reload 强制刷新 都会使页面有短暂的空白 体验效果不是特别好 home vue
  • 提高生活、学习、工作效率的方法——时间管理Vs个人管理

    首先 我想对于大家来说 时间管理这个词应该并不陌生 不过 在开会之前 又有几个知道呢 反正我当时并不知道 这就需要反思了 不过这里 先不做反思 先说说时间管理 初次接触到这个词 我想的是 为什么要管理 怎样进行时间管理 该怎么管理 随后 米
  • 12. 集群调度

    文章目录 简介 调度过程 自定义调度器 调度亲和性 Node亲和性 preferredDuringSchedulingIgnoredDuringExecution requiredDuringSchedulingIgnoredDuringE
  • 针对于MLE和MLP的代码例子实现

    背景 首先该例子来源于CSDN 详解最大似然估计 MLE 最大后验概率估计 MAP 以及贝叶斯公式的理解 nebulaf91的博客 这里的代码作为对上述内容的补充和实现 代码 import numpy as np import matplo
  • SSD接口种类

    转自微信公众号 存储随笔 随着SSD价格的不断下降以及SSD性能的不断提升 越来越多的朋友开始考虑给自己的电脑升级SSD固态硬盘 但是市面上现在SSD的根据不同的大小与尺寸 有多种多样的接口的SSD 本篇文章就当下主流的一些SSD接口进行简
  • OpenStack核心组件-horizon web 界面管理

    1 horizon 介绍 Horizon Horizon 为 Openstack 提供一个 WEB 前端的管理界面 UI 服务 通过 Horizone 所提供的 DashBoard 服务 管理员可以使用通过 WEB UI 对 Opensta
  • Oracle 批量提交,批量绑定 OCIBindByName 和OCIBindObject 的使用

    穷遍所有OCI文档找不出一个能绑定多行数据的说明和示例 自己尝试快两周解决了Oracle Spatial 批量绑定将Oracle的写入效率提升到了5000行左右 以下是一点心得 Oracle OCI 基本操作 本文不多说 假设你会用基本的O
  • [面试题]java程序内存泄漏怎么排查

    java程序内存泄漏怎么排查 首先了解几个命令 怎么判断当前程序有没有出现内存溢出 模拟代码 模拟步骤 判断依据 出现内存溢出怎么办 最原始的方法 使用JProfiler解析hprof文件 在线dump文件分析网站https console
  • PCB相关知识-封装+元件属性+印制电路板PCB

    文章目录 封装Footprint 元件属性Properties 印制电路板PCB 封装Footprint 每个元器件都对应一个封装 封装相当于元器件在现实中的载体 原理图导入到PCB中的除了网络信息 还有封装信息 我们在PCB中移动摆放的就
  • vscode 好用的插件推荐

    vscode 好用的插件推荐 文章目录 vscode 好用的插件推荐 1 Tabnine 安装 使用 2 Git Graph 安装 使用 3 Comment Translate 安装 使用 1 Tabnine Tabnine 需要大量的代码
  • Vue3 Vite4 ElementPlus TS模板(含Vue-Router4+Pinia4)

    引言 手动安装配置Vue3 ElementPlus模板比较繁琐 网上寻找一些模板不太符合自己预期 因此花点精力搭建一个符合自己需求的架子 采用最新的组件 版本如下 vite 4 3 9 vite plugin mock 2 9 8 vue
  • Openwrt 自编译后安装官方ipk时产生kernel MD5不兼容的问题处理

    目录 环境 原因 解决方法 最后 环境 芯片 V3S 软件 基于Openwrt 19 07 3的自编译版本 问题 在安装需要校验kernel版本的ipk时 无法安装 报错 satisfy dependencies for Cannot sa
  • Linux·深入理解 ext4 等 Linux 文件系统

    了解 ext4 的历史 包括其与 ext3 和之前的其它文件系统之间的区别 目前的大部分 Linux 文件系统都默认采用 ext4 文件系统 正如以前的 Linux 发行版默认使用 ext3 ext2 以及更久前的 ext 对于不熟悉 Li
  • 网络安全课程设计Java实现DES加密算法(可视化界面)代码+设计文档

    一 DES加密 解密算法 DES是一种对称加密算法 DES算法明文分组长度为64 bit 秘钥长度也为64 bit 但是实际密钥长度只有56位 其中第8 16 24 32 40 48 56 64位是奇偶校验位 用于检查密钥在产生 分配及存储
  • 安装 Nginx后无法正常显示欢迎界面的问题--解决方案

    问题 在终端中输入 curl 127 0 0 1 后 代码中出现404 解决方案 1 卸载nginx 需要预先安装 aptitude aptitude remove nginx 2 重装nginx apt get install nginx
  • 由浅入深理解区块链技术

    一 区块链技术概述 区块链技术的核心思想与密码朋克组织的渊源很深 这个组织由一批致力于个人隐私保护的密码学爱好者组成 他们认为在互联网环境下想要保护个人隐私 应该使用基于技术的而非其他组织背书的加密方法 不能够全部依靠大型机构提供的加密工具
  • STM32使用SRAM扩展内存

    目录 一 SRAM介绍 二 STM32F103系列的FSMC模块 三 初始化配置及数据访问 四 使全局变量定义在外部SRAM中的方法 五 参考文章及资料 一 SRAM介绍 SRAM Static Random Access Memory 即