当前位置: 首页 > news >正文

STM32F4_外部SRAM

目录

前言

1. SRAM控制原理

1.1 SRAM功能框图

1.2 SRAM读写时序

2. FSMC简介

2.1 FSMC架构

2.2 FSMC地址映射

2.3 FSMC控制SRAM时序

3. FSMC结构体

4. 库函数配置FSMC

5. 实验程序

5.1 main.c

5.2 SRAM.c

5.3 SRAM.h


前言

        STM32F4自带了192K字节的SRAM;对于一般的应用来说,192K字节已经够用了,但是对于那些对内存要求比较高的,192K字节是远远不够用的;为此,STM32F4板载了一个1M字节的SRAM芯片:IS62WV51216,以满足大内存的需求。

        IS62WV51216是ISSI(Integrated Silicon Solution Inc)公司生产的一颗16位宽512K(512*16,即1M字节(下面会做精确讲解计算,为什么是512*16,又为什么是1M字节))容量的CMOS静态内存(SRAM)芯片。

1. SRAM控制原理

        STM32控制器芯片内部有一定大小的SRAM及FLASH作为内存和程序存储空间,但是当程序比较大时,内存和程序空间不足时,就需要STM32芯片的外部扩展存储器了。 

        实际生活中,不管是我们使用手机还是电脑,我们常常说的运行内存(8+128、12+256中的8G和12G)实际上是执行内存,而我们下载APP或者游戏所消耗的内存是存储内存;这是截然不同的。

        给STM32芯片扩展内存与给PC电脑扩展内存的原理是一样的,只不过我们平时给电脑扩展内存一般以内存条的形式扩展,内存条实质上是由多个内存颗粒(即SDRAM芯片)组成的通用标准模块,而STM32扩展时,直接与SRAM芯片连接即可

扩展内存的本质是:利用STM32的FSMC灵活静态存储器去驱动IS62WV51216芯片,进而达到扩展内存的目的;(STM32芯片追其根本还是起控制作用,真正其作用的是IS62WV51216芯片)

1.1 SRAM功能框图

SRAM芯片内部功能框图:

A0-A18是地址线,会连接到内部地址译码器,然后会发送给存储器矩阵(SRAM、FLASH和EEPROM在内部都是通过矩阵的形式进行存储的,一方面有利于指针的读写,另一方面也有利于擦除)

其中存储器矩阵是512K*16,单位是Bit,1个字节对应于8位;512*16=8192Bit;8192/8=1024字节,所以外部扩展Flash的大小是1M;

  • A0-A18:输入引脚;地址输入  (设置指针寻址获取存储器矩阵中对应的数据)
  • I/O0-I/O7:输入输出引脚;数据输入输出信号,低字节
  • I/O8-I/O15:输入输出引脚;数据输入输出信号,高字节
  • CS2和CS1#:输入引脚;片选信号,CS2高电平有效,CS1#低电平有效,部分芯片只要其中一个引脚
  • OE#:输入引脚;输出使能信号,低电平有效
  • WE#:输入引脚;写入使能,低电平有效
  • UB#:输入引脚;数据掩码信号Upper Byte,高位字节允许访问,低电平有效
  • LB#:输入引脚;数据掩码信号Lower Byte,低位字节允许访问,低电平有效

拓展:

        数据掩码信号将真正的客户数据转换成其他人都不能使用的完全伪造的数据,但是那些数据仍可以被用于应用程序测试。

        简单来说就是:一种读写保护机制,因为写入芯片的程序对使用者来说都非常重要,为防止被他人窃取,所以引入数据掩码信号。

地址译码器的作用:

        地址译码器是把 N 根地址线转换成 2^{N} 根信号线。每根信号线对应一行或者一列存储单元,通过地址线找到具体的存储单元,实现寻址。

        美中不足的是:STM32F4的开发板中拓展的SRAM还比较小,只有1M,是没有列地址线的;它的数据宽度(因为存储器矩阵类似于我们使用的Excel,矩阵是由行和列组成的,那么每一行的长度称为数据宽度)是16位(一行能放2个字节,每个字节占8位);(其中:因为数据宽度是16位的,所以一行可以存放2个字节,每次写入一个字节,那么就需要分别写入这16位的高8位和低8位,那么就需要借助I/O0-I/O7、I/O8-I/O15数据线分别写入这16位的高字节和低字节)

        A0-A18是地址信号线,18根地址线一共可以表示2^{18}=2^{18}*1024=512K存储单元,所以总共可以访问 512K*16Bit 大小的空间。访问时,使用UB#或LB#线控制数据宽度

UB#和LB#的作用:

        因为存储器矩阵是通过地址线寻址进而得到对应的数据的;那么如果我们想要访问第二行的高8位,并且不想改变第二行的低8位,此时就需要借助于UB#和LB#,UB#是高位字节允许访问,低电平有效;LB#是低位字节允许访问,低电平有效;设置LB#等于1,那么低位字节就不允许访问,此时就无法访问第二行的低8位;在此基础上设置UB#=0,高位字节允许访问,此时就可以改变第二行高8位的数据。

控制电路:

        控制电路主要包括片选信号CS读写使能OE、WE以及宽度控制信号UB#和LB#。利用CS2和CS1#片选信号,可以把多个SRAM芯片组成一个大容量的内存条。OE#和WE#控制读写使能,防止误操作。

1.2 SRAM读写时序

SRAM数据时序:

读时序的过程是

        首先通过A0-A18地址线发送一个地址,这个地址代表我们想要访问的SRAM对应地址上的数据,因为SRAM是通过寻址的方式找到对应数据的;紧接着读使能OE置低电平,因为读使能引脚OE低电平有效;接下来片选信号线CS1置低电平,片选信号线CS2置高电平,因为CS1低电平有效,CS2高电平有效;然后设置掩码信号LB#和UB#,如果我们想要访问一行16位,那么LB和UB均设置为低电平即可;如果只是想访问16位中高8位和低8位其中之1,那么按照需要对应设置掩码信号即可;最后通过数据线 I/O 将对应地址上的数据发送给 STM32 即可;这样就可以实现在SRAM上读取数据。

 图中橙色区域黄色区域的含义是:

        因为SRAM读取数据是异步通讯,也就是没有时钟总线,也可以说是双方没有规定好时间,那么我将要读取的地址发送以后,就需要给出一定的反应时间(因为没有时钟,不是同步通信),也就是图中程序区域的t_{AA}长度,整个程序区域长度t_{RC}表示整个读数据的时间,黄色区域表示在发送地址一定时间后,SRAM才会将对应地址上的数据返回给STM32(也就是说对应时间t_{AA}过去以后,我才会在黄色区域时间内把对应数据返回回去)

SRAM数据时序:

写时序的过程是:

        首先在整个黄色区域,也就是写时序周期t_{WC}内发送一个地址,该地址表示STM32想要往SRAM的哪个地址上写;确定写的地方以后,紧接着拉低片选信号线CS1,置高片选信号线CS2;接下来写使能WE置低,表示开始写数据到SRAM中;然后根据自己想要写的数据宽度是16位还是16位中的高8位还是低8位设置掩码信号;最后通过数据线将所要写入的数据写到对应的地址上;

t_{SD}t_{HD}的作用:

        因为是异步通信,没有时钟总线,所以我们默认在整个写时序的过程中,在把写地址发送给SRAM以后,等待一段时间(这段时间是黄色区域的前半部分),然后默认再等待t_{SD}+t_{HD}时间,就认为数据一定是写入了发送的地址上。

2. FSMC简介

        首先我们需要明确STM32单片机只是起到了控制作用,也就是说MCU控制外设去实现单片机内部集成的某些功能。这里学习的FSMC就是其中一个外设,通过STM32控制FSMC就可以管理扩展的存储器SRAM

        FSMC:Flexible Static Memory Controller的缩写,译为灵活的静态存储器。FSMC可以用来驱动SRAM、NOR FLASH以及NAND FLASH类型的存储器,但是不可以驱动动态存储器SDRAM(动态存储器位于STM32F429中)。

2.1 FSMC架构

:通讯引脚

通讯引脚和原理图上的SRAM模块的引脚是一一对应的:

  • FSMC_NBL[1:0]:对应SRAM引脚为LB#和UB#;表示数据掩码信号
  • FSMC_A[18:0]:对应SRAM引脚为地址线A[18:0];表示行地址线
  • FSMC_D[15:0]:对应SRAM引脚为数据线I/0[15:0];表示数据线
  • FSMC_NWE:对应SRAM引脚为WE#;表示写入使能
  • FSMC_NOE:对应SRAM引脚为OE#;表示输出使能(读使能)
  • FSMC_NE[1:4]:对应SRAM引脚为CE#;表示片选信号

:存储器控制器

原理图中对应的所有引脚都是连接到对应的存储控制器中的。

NOR/PSRAM/SRAM设备使用相同的控制器NAND/PC卡设备使用相同的控制器,不同的控制器有专用的寄存器用于配置其工作模式;

其中控制SRAM的由有FSMC_BCR1/2/3/4控制寄存器、FSMC_BTR1/2/3/4片选时序寄存器以及FSMC_BWTR1/2/3/4写时序寄存器;每种寄存器都有4个,对应于4个不同的存储区域;

FSMC_BCR控制寄存器可配置要控制的存储器类型、数据线宽度以及信号有效极性能参数。

FSMC_BTR时序寄存器用于配置SRAM访问时的各种时间延迟,如数据保持时间、地址保持时间等。

FSMC_BWTR写时序寄存器与FSMC_BTR控制的参数类似,专门用于控制写时序的时间参数。

:时钟控制逻辑

FSMC外设挂载在AHB总线上,时钟信号来自于HCLK(默认168MHz),存储器控制器的同步时钟输出就是由它分频得到的。

2.2 FSMC地址映射

FSMC连接好外部的存储器(SRAM拓展芯片IS62WV51216)并初始化后,就可以直接通过访问地址来读写数据。

FSMC访问存储的方式不同于IIC EEPROM、SPI Flash,IIC和SPI都需要控制总线给存储器发送地址,然后获取数据;在程序里,地址和数据是需要定义不同的变量来存储的(我们的IIC、SPI程序中通常写字节函数都会定义第一个参数Address、第二个参数Data,表示往地址Address上写入数据Data),并且访问时还需要使用代码控制发送读写命令。

FSMC外接存储器时,其存储单元是映射到STM32的内部寻址空间的;在程序里,定义一个指向这些地址的指针,就可以通过指针直接修改这些存储单元的内容。并且,FSMC外设会自动完成数据访问过程,读写命令之类的操作不需要程序控制。

2.3 FSMC控制SRAM时序

FSMC外设支持输出多种不同的时序以便于控制不同的存储器,它具有ABCD四种模式:

其中ADDSET表示地址设置阶段的持续时间

  •         0000:地址设置阶段的持续时间=0*HCLK时钟周期(168MHz)
  •         0001:地址设置阶段的持续时间=1*HCLK时钟周期(168MHz)
  •         ……
  •         1111:地址设置阶段的持续时间=1615*HCLK时钟周期(168MHz)(复位后的默认值)

DATAST表示数据阶段的持续时间:

  •         00000000:Reserved
  •         00000001:DATAST阶段的持续时间=1*HCLK时钟周期
  •         00000010:DATAST阶段的持续时间=2*HCLK时钟周期
  •         ……
  •         11111111:DATAST阶段的持续时间=255*HCLK时钟周期(复位后的默认值)

以上的两个时间均通过FSMC片选时序寄存器的相应位进行设置;

3. FSMC结构体

//FSMC时序结构体//一个HCLK周期为1/168微秒typedef struct
{uint32_t FSMC_AddressSetupTime; //地址建立时间,0-0xF个HCLK周期//通过时序寄存器进行设置//0000:地址建立持续时间=0*HCLK时钟周期//1111:地址建立持续时间=15*HCLK时钟周期uint32_t FSMC_AddressHoldTime;  //地址保持时间,0-0xF个HCLK周期//通过时序寄存器设置//0000:保留//0001:保持时间=1*HCLK时钟周期//1111:保持时间=15*HCLK时钟周期uint32_t FSMC_DataSetupTime;   //数据建立时间,0-0xF个HCLK周期//通过时序寄存器设置//0000 0000:保留//0000 0001:持续时间=1*HCLK时钟周期//1111 1111:持续时间=255*HCLK时钟周期uint32_t FSMC_BusTurnAroundDuration; //总线转换周期,0-0xF个HCLK周期//通过时序寄存器BTR/BWTR配置//0000:增加0个HCLK时钟周期//1111:增加15个HCLK时钟周期uint32_t FSMC_CLKDivision;      //时钟分频因子,1-0xF//时序寄存器BTR位[23:20]设置//0000:Reserved//0001:CLK周期=2*HCLK周期//0010:CLK周期=3*HCLK周期//1111:CLK周期=16*HCLK周期uint32_t FSMC_DataLatency;      //数据延迟时间//时序寄存器BTR/BWTR位[18:15]设置数据延迟时间//0000 0000:Reserved//0000 0001:延迟时间=1*HCLK(168MHz)//0000 0010:延迟时间=2*HCLK(168MHz)以此类推//1111 1111:延迟时间=255*HCLK(168MHz)uint32_t FSMC_AccessMode;       //设置访问模式//时序寄存器BTR/BWTR位[29:28]设置访问模式//00:访问模式A//01:访问模式B//10:访问模式C//11:访问模式D
}FSMC_NORSRAMTimingInitTypeDef;
//FSMC初始化结构体//除了最后两个成员是时序寄存器配置以外,其余的成员都是FSMC_BCR控制寄存器配置的typedef struct
{uint32_t FSMC_Bank;  //设置要控制的Bank区域  选择FSMC映射的存储区域,SRAM不需要通过寻址,STM32内部是有其映射地址的,只需要通过指针即可访问内部存储区域//FSMC_Bank1_NORSRAM1  0x6000 0000~0x63FF FFFF//FSMC_Bank1_NORSRAM2  0x6400 0000~0x67FF FFFF//FSMC_Bank1_NORSRAM3  0x6800 0000~0x6BFF FFFF//FSMC_Bank1_NORSRAM4  0x6C00 0000~0x6FFF FFFF//原理图上对应的引脚标明:FSMC_NE3  所以在此选择FSMC_Bank1_NORSRAM3  对应的地址uint32_t FSMC_DataAddressMux; //设置地址总线和数据总线是否复用//FSMC_DataAddressMux_Enable/Disable //在控制NOR FLASH时,可以地址总线和数据总线分时复用,减少STM32信号线的数量uint32_t FSMC_MemoryType;     //设置存储器的类型//它支持控制的存储器类型为SRAM、PSRAM、NOR//FSMC_MemoryType_SRAM/PSRAM/NORuint32_t FSMC_MemoryDataWidth; //设置存储器的数据宽度  可以选择设置为8或者16位//FSMC_MemoryDataWidth_8b/16buint32_t FSMC_BurstAccessMode; //设置是否支持突发访问模式//FSMC_BurstAccessMode_Enable/Disable//突发访问模式是指发送一个地址后连续访问多个数据//非突发模式下每访问一个数据都需要输入一个地址//控制同步类型的存储器时才能使用突发模式(SRAM是异步类型的存储器)uint32_t FSMC_AsynchronousWait; //设置是否使能在同步传输时的等待信号//FSMC_AsynchronousWait_Enable/Disable//在控制同步类型的NOR或PSRAM时,存储器可以使用FSMC_NWAIT引脚通知STM32需要等待uint32_t FSMC_WaitSignalPolarity; //设置等待信号的极性  要求等待时,使用高电平还是低电平//FSMC_WaitSignalPolarity_High/Low;uint32_t FSMC_WrapMode;     //设置是否支持对齐的突发模式//是否支持把非对齐的AHB突发模式分割成2次线性操作//FSMC_WrapMode_Enable/Disableuint32_t FSMC_WaitSignalActive;  //配置等待信号是在等待前有效还是等待期间有效    //决定存储器是在等待状态之前的一个数据周期有效还是在等待状态期间有效//FSMC_WaitSignalActive_BeforeWaitState/DuringWaitStateuint32_t FSMC_WriteOperation;   //设置是否写使能//FSMC_WriteOperation_Enable/Disableuint32_t FSMC_WaitSignal;       //设置是否使能等待状态插入//设置当存储器突发传输模式时,是否允许通过NWAIT信号插入等待状态//FSMC_WaitSignal_Enable/Disableuint32_t FSMC_ExtendedMode;     //设置是否使能扩展模式//FSMC_ExtendedMode_Enable/Disableuint32_t FSMC_WriteBurst;       //设置是否使能写突发操作//FSMC_WriteBurst_Enable/Disable//当不使用扩展模式时,本参数用于配置读写时序,否则用于配置读时序FSMC_NORSRAMTimingInitTypeDef* FSMC_ReadWriteTimingStruct;//当使用扩展模式时,本参数用于配置写时序//FSMC_NORSRAMTimingInitTypeDef* FSMC_WriteTimingStruct;}FSMC_NORSRAMInitTypeDef;

4. 库函数配置FSMC

1. 使能FSMC时钟,配置FSMC相关的IO及其时钟使能

要使用FSMC,首先要开启其时钟。然后需要把FSMC_D0~D15,FSMC_A0~A18相关的IO口全部配置为复用功能,使能各个IO组的时钟

RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);    //使能 FSMC 时钟

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;     //复用输出

void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF);   //设置引脚映射

2. 设置FSMC BANK1 区域3的相关寄存器

void FSMC_NORSRAMInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct);   //调用结构体设置FSMC控制寄存器的工作模式、位宽和读写时序

3. 使能BANK1 区域3

FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);    // 使能 BANK1  区域3

5. 实验程序

实验现象:

        开机后,显示提示信息,然后按下KEY0按键,测试外部SRAM容量大小并显示在LCD上。

                                                       按下KEY1按键,显示预存在外部的SRAM数据。

5.1 main.c

#include "stm32f4xx.h"                 
#include "delay.h"
#include "usart.h"
#include "LED.h"
#include "lcd.h"
#include "Key.h"
#include "usmart.h"
#include "SRAM.h"//LCD状态设置函数
void led_set(u8 sta)//只要工程目录下有usmart调试函数,主函数就必须调用这两个函数
{LED1=sta;
}
//函数参数调用测试函数
void test_fun(void(*ledset)(u8),u8 sta)
{led_set(sta);
}
u32 TestSRAM[250000] __attribute__((at(0x68000000))); //测试用数组
//定义一个局部变量 该数组是用来测试的数组
//__attribute__((at(0x68000000)))这个是用来指定变量或结构位域的特殊属性,该关键字后的双括弧中的内容是属性说明
//at是关键字,该关键字用来设置变量的绝对地址,也就是说通过该关键字可以指定某个变量处于内存里面的某个给定的地址
//综合起来就是:设置变量处于0x68000000这个地址//外部内存测试,最大支持1M字节内存测试
void fsmc_sram_test(u16 x,u16 y)
{u32 i=0;u8 temp=0;u8 sval=0;  //在地址0读到的数据LCD_ShowString(x,y,239,y+16,16,"Ex Memory Test:   0KB"); //提示信息  239,y+16是指区域大小//每隔4K字节,写入一个数据,总共写入256个数据,正好是1M字节,用来测试SRAM内存for(i=0;i<1024*1024;i=i+4096) //1M=1024KB,1KB=1024字节,4096字节就是4KB   i=i+4096表示for每循环一次,就跳过4K字节{//i是在1024*1024的存储器矩阵中进行循环的FSMC_SRAM_WriteBuffer(&temp,i,1);//调用在指定地址上写入n个字节函数//&temp,取地址变量temp,表示拿到了temp变量的存储首地址;指针指向temp首地址,表示从这个地址开始写//i表示要写入的值,i在存储器矩阵中递增,SRAM写是不需要软件参与的,只要指针能指向这个i对应的地址,就能对该地址进行写操作//每次写入1个字节temp++;}//依次读出之前写入的数据,进行校验for(i=0;i<1024*1024;i=i+4096){FSMC_SRAM_ReadBuffer(&temp,i,1);if(i==0) //表示在地址0上读出的数据{sval=temp; //把地址0上读到的数据给到sval}else if(temp<=sval) //else if 此时i不再是0,也就表示之前已经写入数据了,因为i在存储器矩阵中是递增的,所以只要后面读取的值小于地址0上的值,就break结束{break; //后面读出的数据一定要比第一次读到的数据大}LCD_ShowxNum(x+15*8,y,(u16)(temp-sval+1)*4,4,16,0); //显示内容容量 //第三个参数表示要写入的数值      第四个参数表示长度//u16 表示unsigned int 表示强制类型转换为int型 //temp是最后一次读取到值;sval是位置0上读取的值,temp-sval+1表示在整个存储器矩阵读到了多少个数,每个4K写一次,那么读到的数也是每隔4K的//(temp-sval+1)*4 表示总的数据长度,也就是内存容量}
}
int main(void)
{u8 key;u8 i=0;u32 j=0;delay_init(168);uart_init(115200);LED_Init();LCD_Init();Key_Init();FSMC_SRAM_Init();POINT_COLOR=RED;LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");LCD_ShowString(30,70,200,16,16,"SRAM Test");LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(30,110,200,16,16,"2023/20/23");LCD_ShowString(30,130,200,16,16,"KEY0:Test Sram");LCD_ShowString(30,150,200,16,16,"KEY1:Test Data");POINT_COLOR=BLUE; //设置字体为蓝色for(j=0;j<250000;j++){TestSRAM[j]=j; //预存测试数据}
//  可以借助该程序在串口查看数据
//	while(1)
//	{
//		printf("\r\nSRAM中的数据是:\r\n");
//		for(j=0;j<250000;j++)
//		{
//			LED0=!LED0;
//			printf("%d ",TestSRAM[j]);
//		}
//	}while(1){key=KEY_Scan(0);if(key==1)  //KEY0按下{fsmc_sram_test(60,170); //测试SRAM容量}else if(key==2) //KEY1按下 打印预存测试数据{for(j=0;j<250000;j++){LCD_ShowxNum(60,190,TestSRAM[j],6,16,0); //显示测试数据}}else{delay_ms(10);}i++;if(i==20){i=0;LED0=!LED0;}}
}

5.2 SRAM.c

#include "stm32f4xx.h"              
#include "SRAM.h"//使用NOR/SRAM的 Bank1.sector3,地址位HADDR[27,26]=10
//00:sector1
//01:sector2
//10:sector3
//11:sector4
//对IS62WV51216来说,地址线范围为A0~A18#define Bank1_SRAM3_ADDRESS ((u32)(0x68000000))   //Bank1_SRAM3的起始地址为0x68000000//初始化外部SRAM
void FSMC_SRAM_Init(void)
{RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOG,ENABLE); //使能B D E F G时钟RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE); //使能FSMC时钟//PB15GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽输出GPIO_InitStructure.GPIO_Pin=GPIO_Pin_15; //PB15 推挽输出 控制背光GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);//PD0 PD1 PD4 PD5 PD8~15 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;GPIO_InitStructure.GPIO_OType=GPIO_OType_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_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;GPIO_Init(GPIOD,&GPIO_InitStructure);//PE0 PE1 PE7~15GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;  //引脚模式设置为复用,后续将引脚复用为FSMCGPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽输出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_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;GPIO_Init(GPIOE,&GPIO_InitStructure);//PF0~5 PF12~15GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽输出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_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;GPIO_Init(GPIOF,&GPIO_InitStructure);//PG0~5 PG10GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽输出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_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;GPIO_Init(GPIOG,&GPIO_InitStructure);//将所有复用功能的引脚设置为 复用FSMCGPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_FSMC); //PD0复用为FSMCGPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_FSMC); //PD1复用为FSMCGPIO_PinAFConfig(GPIOD,GPIO_PinSource4,GPIO_AF_FSMC); //PD4复用为FSMCGPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_FSMC); //PD5复用为FSMCGPIO_PinAFConfig(GPIOD,GPIO_PinSource8,GPIO_AF_FSMC); //PD8复用为FSMCGPIO_PinAFConfig(GPIOD,GPIO_PinSource9,GPIO_AF_FSMC); //PD9复用为FSMCGPIO_PinAFConfig(GPIOD,GPIO_PinSource10,GPIO_AF_FSMC); //PD10复用为FSMCGPIO_PinAFConfig(GPIOD,GPIO_PinSource11,GPIO_AF_FSMC); //PD11复用为FSMCGPIO_PinAFConfig(GPIOD,GPIO_PinSource12,GPIO_AF_FSMC); //PD12复用为FSMCGPIO_PinAFConfig(GPIOD,GPIO_PinSource13,GPIO_AF_FSMC); //PD13复用为FSMCGPIO_PinAFConfig(GPIOD,GPIO_PinSource14,GPIO_AF_FSMC); //PD14复用为FSMCGPIO_PinAFConfig(GPIOD,GPIO_PinSource15,GPIO_AF_FSMC); //PD15复用为FSMCGPIO_PinAFConfig(GPIOE,GPIO_PinSource0,GPIO_AF_FSMC); //PE0复用为FSMCGPIO_PinAFConfig(GPIOE,GPIO_PinSource1,GPIO_AF_FSMC); //PE1复用为FSMCGPIO_PinAFConfig(GPIOE,GPIO_PinSource7,GPIO_AF_FSMC); //PE7复用为FSMCGPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_FSMC); //PE8复用为FSMCGPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_FSMC); //PE9复用为FSMCGPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_FSMC); //PE10复用为FSMCGPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_FSMC); //PE11复用为FSMCGPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_FSMC); //PE12复用为FSMCGPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_FSMC); //PE13复用为FSMCGPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_FSMC); //PE14复用为FSMCGPIO_PinAFConfig(GPIOE,GPIO_PinSource15,GPIO_AF_FSMC); //PE15复用为FSMCGPIO_PinAFConfig(GPIOF,GPIO_PinSource0,GPIO_AF_FSMC); //PF0复用为FSMCGPIO_PinAFConfig(GPIOF,GPIO_PinSource1,GPIO_AF_FSMC); //PF1复用为FSMCGPIO_PinAFConfig(GPIOF,GPIO_PinSource2,GPIO_AF_FSMC); //PF2复用为FSMCGPIO_PinAFConfig(GPIOF,GPIO_PinSource3,GPIO_AF_FSMC); //PF3复用为FSMCGPIO_PinAFConfig(GPIOF,GPIO_PinSource4,GPIO_AF_FSMC); //PF4复用为FSMCGPIO_PinAFConfig(GPIOF,GPIO_PinSource5,GPIO_AF_FSMC); //PF5复用为FSMCGPIO_PinAFConfig(GPIOF,GPIO_PinSource12,GPIO_AF_FSMC); //PF12复用为FSMCGPIO_PinAFConfig(GPIOF,GPIO_PinSource13,GPIO_AF_FSMC); //PF13复用为FSMCGPIO_PinAFConfig(GPIOF,GPIO_PinSource14,GPIO_AF_FSMC); //PF14复用为FSMCGPIO_PinAFConfig(GPIOF,GPIO_PinSource15,GPIO_AF_FSMC); //PF15复用为FSMCGPIO_PinAFConfig(GPIOG,GPIO_PinSource0,GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOG,GPIO_PinSource1,GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOG,GPIO_PinSource2,GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOG,GPIO_PinSource3,GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOG,GPIO_PinSource4,GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOG,GPIO_PinSource5,GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOG,GPIO_PinSource10,GPIO_AF_FSMC);FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitStructure; //调用STM32库函数配置的结构体配置时序寄存器FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode=FSMC_AccessMode_A;  //设置访问模式为模式AFSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime=0x00;   //地址保持时间,模式A未用到FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime=0x00;  //地址建立时间(ADDSET)为1个HCLK 1/36M=27nsFSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration=0x00;   //总线转换周期 0000:增加0个HCLK时钟周期FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision=0x00;    //时钟分频因子 0000 0000:保留FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency=0x00;    //数据延迟时间 0000 0000:保留FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime=0x08;  //数据保持时间(DATAST)为9个HCLK 6*9=54ns//调用STM32库函数配置的结构体配置FSMC_BCR控制寄存器FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_NORSRAMInitStructure.FSMC_Bank=FSMC_Bank1_NORSRAM3;  //Bank1区域3FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode=FSMC_BurstAccessMode_Disable; //不支持突发访问模式FSMC_NORSRAMInitStructure.FSMC_DataAddressMux=FSMC_DataAddressMux_Disable; //地址总线和数据总线不复用FSMC_NORSRAMInitStructure.FSMC_ExtendedMode=FSMC_ExtendedMode_Disable;  //不使能扩展模式,读写使用相同的时序FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth=FSMC_MemoryDataWidth_16b; //存储器的数据宽度为16位FSMC_NORSRAMInitStructure.FSMC_MemoryType=FSMC_MemoryType_SRAM; //选择存储器种类为SRAMFSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct=&FSMC_NORSRAMTimingInitStructure; //不使用扩展模式时,配置读写时序FSMC_NORSRAMInitStructure.FSMC_WaitSignal=FSMC_WaitSignal_Disable;  //不使能等待状态插入FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive=FSMC_WaitSignalActive_BeforeWaitState; //配置等待信号在等待前有效FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity=FSMC_WaitSignalPolarity_Low;  //要求等待时,设置为低电平FSMC_NORSRAMInitStructure.FSMC_WrapMode=FSMC_WrapMode_Disable; //不支持对齐的突发模式FSMC_NORSRAMInitStructure.FSMC_WriteBurst=FSMC_WriteBurst_Disable; //不使能写突发操作FSMC_NORSRAMInitStructure.FSMC_WriteOperation=FSMC_WriteOperation_Enable; //存储器写使能FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct=&FSMC_NORSRAMTimingInitStructure; //扩展模式时,本参数用于配置写时序FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3,ENABLE); //使能Bank1 区域3
}
//在指定地址(WriteAddress+Bank1_SRAM3_ADDRESS)上开始,连续写入n个字节
//pBuffer:字节指针
//WriteAddress:要写入的地址
//n:要写入的字节数
void FSMC_SRAM_WriteBuffer(u8* pBuffer,u32 WriteAddress,u32 n) //在SRAM上写字节是不需要软件来操作的,因为地址是在STM32上映射的//所有只需要给出地址,通过指针就可以实现读写操作,读写操作通过硬件来完成,无需软件操作来参与
{for(;n!=0;n--) //通过for循环将n个字节写到SRAM,每循环一次,要写入的字节就少一个{*(vu8*)(Bank1_SRAM3_ADDRESS+WriteAddress)=*pBuffer; //该代码的含义是:Bank1_SRAM3_ADDRESS是Bank1区域3的起始地址+WriteAddress要写入的地址,表示首先要将指针指向我们要写入的地址上//(vu8*)(Bank1_SRAM3_ADDRESS+WriteAddress)表示强制类型转换成vu8的指针,然后解引用拿到该指针指向地址上的数据//将*pBuffer指针指向这个数据,硬件自动写入数据WriteAddress++;//要写入的地址加1pBuffer++;//指针指向下一个地址}//这里注意://假设WriteAddress要写入的地址是0,也就是说从SRAM起始地址开始写,起始地址是0x68000000;写入的地址是偶数,那么地址线最低位A0一定是0,因为SRAM是通过地址线发送要访问的地址的//此时LB#和UB#掩码信号中LB有效,所以LB=0,写入数据D0~D7有效;D8~D15无效,UB=1;//继续写地址1的时候,写入的地址就变成了0x68000001,此时LB=1,无效;UB=0,有效;因此数据写入高8位地址//UB和LB与要写入地址的最低位有关//如果要写入的数据是16位的,那么UB和LB都要有效,所以UB和LB都是0;//如果地址是奇数,那么1个16位的数据需要分两次去写,因为强制类型转换把要写入的地址转换成了8位//所以需要分别去写地址的高8位和低8位;//这样写两次相对于写一次,速度就会减半;
}
//在指定地址(ReadAddress+Bank1_SRAM3_ADDRESS)上开始,连续读出n个字节
//pBuffer:字节指针
//ReadAddress:要读出的起始地址
//n:要写入的字节数
void FSMC_SRAM_ReadBuffer(u8* pBuffer,u32 ReadAddress,u32 n)
{for(;n!=0;n--) //循环n次,从SRAM中读出n个字节 同理,读字节也是硬件来完成的,无需软件操作{*pBuffer++=*(vu8*)(Bank1_SRAM3_ADDRESS+ReadAddress); //解引用拿到指针指向地址上的数据,字节指针指向这个数据//通过硬件循环读取该数据,指针后置++ReadAddress++;//对应地址++}
}//测试函数
//在指定地址写入1个字节
//Address:地址
//Data:要写入的数据
void fsmc_sram_test_write(u32 Address,u8 Data)
{FSMC_SRAM_WriteBuffer(&Data,Address,1);  //第一个参数字节指针,指向要写入数据的首元素地址;第二个参数是要写入的地址;第三个参数是要写入的字节个数//写入一个字节
}
//读取一个字节
//Address:要读取的地址
//返回值:读取到的数据
u8 fsmc_sram_test_read(u32 Address)
{u8 Data;FSMC_SRAM_ReadBuffer(&Data,Address,1); //读取一个字节return Data;
}

5.3 SRAM.h

#ifndef _SRAM__H_
#define _SRAM__H_
#include "sys.h"void FSMC_SRAM_Init(void);
void FSMC_SRAM_WriteBuffer(u8* pBuffer,u32 WriteAddress,u32 n);
void FSMC_SRAM_ReadBuffer(u8* pBuffer,u32 ReadAddress,u32 n);void fsmc_sram_test_write(u32 addr,u8 data);
u8 fsmc_sram_test_read(u32 addr);#endif

相关文章:

STM32F4_外部SRAM

目录 前言 1. SRAM控制原理 1.1 SRAM功能框图 1.2 SRAM读写时序 2. FSMC简介 2.1 FSMC架构 2.2 FSMC地址映射 2.3 FSMC控制SRAM时序 3. FSMC结构体 4. 库函数配置FSMC 5. 实验程序 5.1 main.c 5.2 SRAM.c 5.3 SRAM.h 前言 STM32F4自带了192K字节的SRAM&#xff1…...

Java的代理模式

java有三种代理模式 静态代理 jdk动态代理 cglib实现动态代理 代理模式的定义&#xff1a; 为其他对象提供一种代理以控制对这个对象的访问。在某些情况下&#xff0c;一个对象不适合或者不能直接引用另一个对象&#xff0c;而代理对象可以在客户端和目标对象之间起到中介的…...

FilterAttributeOnClassMethod

目录 1 BadMethodFilterAttribute 2 FilterAttributeOnClassMethod 2.1 OnMethodExecuted 2.2 OnMethodExecutedAsync 2.3 OnMethodExecuting BadMethodFilterAttribute using System; using System.Threading.Tasks; namespace Flatwhite.Core.Tests.Attributes …...

springboot + (mysql/pgsql) + jpa 多数据源(不同类数据源)

配置文件&#xff1a; spring:datasource:primary:jdbc-url: jdbc:mysql://host:3306/数据库?useUnicodetrue&characterEncodingUTF-8&autoReconnecttrue&failOverReadOnlyfalse&serverTimezoneAsia/Shanghai&zeroDateTimeBehaviorconvertToNullusername…...

【Golang】Golang进阶系列教程--Go 语言 context 都能做什么?

文章目录 前言核心是 Context 接口&#xff1a;包含四个方法&#xff1a;遵循规则WithCancelWithDeadlineWithTimeoutWithValue 前言 很多 Go 项目的源码&#xff0c;在读的过程中会发现一个很常见的参数 ctx&#xff0c;而且基本都是作为函数的第一个参数。 为什么要这么写呢…...

画图干货!14种uml图类型及示例

1. 什么是 UML UML 是统一建模语言的缩写。UML 图是基于 UML&#xff08;统一建模语言&#xff09;的图表&#xff0c;目的是直观地表示系统及其主要参与者、角色、动作、工件或类&#xff0c;以便更好地理解、更改、维护或记录信息关于系统。简而言之&#xff0c;UML 是一种…...

计算机视觉实验:人脸识别系统设计

实验内容 设计计算机视觉目标识别系统&#xff0c;与实际应用有关&#xff08;建议&#xff1a;最终展示形式为带界面可运行的系统&#xff09;&#xff0c;以下内容选择其中一个做。 1. 人脸识别系统设计 (1) 人脸识别系统设计&#xff08;必做&#xff09;&#xff1a;根据…...

振弦采集仪完整链条的岩土工程隧道安全监测

振弦采集仪完整链条的岩土工程隧道安全监测 隧道工程是一种特殊的地下工程&#xff0c;其建设过程及运行期间&#xff0c;都受到各种内外力的作用&#xff0c;如水压、地震、地质变形、交通荷载等&#xff0c;这些因素都会对隧道的安全性产生影响。因此&#xff0c;对隧道的安…...

NLP实战9:Transformer实战-单词预测

目录 一、定义模型 二、加载数据集 三、初始化实例 四、训练模型 五、评估模型 &#x1f368; 本文为[&#x1f517;365天深度学习训练营]内部限免文章&#xff08;版权归 *K同学啊* 所有&#xff09; &#x1f356; 作者&#xff1a;[K同学啊] 模型结构图&#xff1a; &a…...

使用Vue.js和Rust构建高性能的物联网应用

物联网(IoT)应用是现代技术的重要组成部分&#xff0c;它们可以在各种场景中&#xff08;例如智能家居&#xff0c;工业自动化等&#xff09;提供无缝的自动化解决方案。在这篇文章中&#xff0c;我们将探讨如何使用Vue.js和Rust构建高性能的物联网应用。 1. 为什么选择Vue.js…...

idea调节文字大小、日志颜色、git改动信息

idea调节菜单栏文字大小&#xff1a; 调节代码文字大小&#xff1a; 按住ctrl滚动滑轮可以调节代码文字大小&#xff1a; 单击文件即可在主窗口上打开显示&#xff1a; idea在控制台对不同级别的日志打印不同颜色 &#xff1a; “grep console”插件 点击某一行的时候&#x…...

避免大龄程序员边缘化:如何在技术行业中保持竞争力

目录 导语持续学习和进修维护专业形象寻找适合自己的领域构建个人品牌和网络拥抱变化和创新实例结语&#xff1a; 导语 导语&#xff1a;随着科技的不断发展&#xff0c;技术行业的竞争日益激烈。对于那些年龄稍长的程序员来说&#xff0c;如何保持竞争力并避免边缘化成为了一…...

Jenkins工具系列 —— 启动 Jenkins 服务报错

错误显示 apt-get 安装 Jenkins 后&#xff0c;自动启动 Jenkins 服务报错。 排查原因 直接运行jenkins命令 发现具体报错log&#xff1a;Failed to start Jetty或Failed to bind to 0.0.0.0/0.0.0.0:8080或Address already in use 说明&#xff1a;这里提示的是8080端口号…...

华为数通HCIA-实验环境ensp简介

ensp 路由器&#xff1a;AR系列、NE系列&#xff1b; 模拟器中使用AR2220&#xff1b; 交换机&#xff1a;S系列、CE系列&#xff1b; 模拟器中使用S5700&#xff1b; 线缆&#xff1a;copper——以太网链路&#xff1b; serial——串行链路&#xff0c;在模拟器中用于模…...

SK5代理与IP代理:网络安全中的爬虫利器

一、什么是IP代理与SK5代理&#xff1f; IP代理&#xff1a; IP代理是一种允许用户通过代理服务器进行网络连接的技术。用户请求经由代理服务器中转&#xff0c;从而实现隐藏真实IP地址&#xff0c;保护用户隐私&#xff0c;并在一定程度上突破IP访问限制。常见的IP代理有HTTP…...

实战:Prometheus+Grafana监控Linux服务器及Springboot项目

文章目录 前言知识积累什么是Prometheus什么是Grafana怎样完成数据采集和监控 环境搭建docker与docker-compose安装docker-compose编写 监控配置grafana配置prometheus数据源grafana配置dashboardLinux Host Metrics监控Spring Boot 监控 写在最后 前言 相信大家都知道一个项目…...

[用go实现解释器]笔记1-词法分析

本文是《用go实现解释器》的读书笔记 ​ https://malred-blog​malred.github.io/2023/06/03/ji-suan-ji-li-lun-ji-shu-ji/shi-ti/go-compile/yong-go-yu-yan-shi-xian-jie-shi-qi/go-compiler-1/#toc-heading-6http://个人博客该笔记地址 ​github.com/malred/malanghttp:/…...

在 spark-sql / spark-shell / hive / beeline 中粘贴 sql、程序脚本时的常见错误

一个很小的问题&#xff0c;简单记录一下。有时候我们会粘贴一段已经成功运行过的SQL或程序脚本&#xff0c;但是在spark-sql / spark-shell / hive / beeline 中执行时可能会报这样的错误&#xff1a; hive> CREATE EXTERNAL TABLE IF NOT EXISTS ORDERS(> Display all…...

关于视频汇聚融合EasyCVR平台多视频播放协议的概述

视频监控综合管理平台EasyCVR具备视频融合能力&#xff0c;平台基于云边端一体化架构&#xff0c;具有强大的数据接入、处理及分发能力&#xff0c;平台既具备传统安防视频监控的能力与服务&#xff0c;也支持AI智能检测技术的接入&#xff0c;可应用在多行业领域的智能化监管场…...

三星书画联展:三位艺术家开启国风艺术之旅

7月22日&#xff0c;由广州白云区文联、白云区工商联主办的“三星书画联展”&#xff0c;在源美术馆正式开展。本次书画展展出的艺术种类丰富&#xff0c;油画、国画、彩墨画、书法等作品异彩纷呈。广东省政协原副主席、农工党省委书画院名誉院长马光瑜&#xff0c;意大利艺术研…...

在腾讯云服务器OpenCLoudOS系统中安装nginx(有图详解)

1. 创建安装目录 2. 下载、安装、编译 进入安装目录&#xff1a; cd /app/soft/nginx/ 下载&#xff1a; wget https://nginx.org/download/nginx-1.21.6.tar.gz 解压&#xff1a; tar -zxvf nginx-1.21.6.tar.gz 安装插件&#xff1a; yum -y install pcre-devel 安装…...

大数据课程E5——Flume的Selector

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解Selector的概念和配置属性; ⚪ 掌握Selector的使用方法; 一、简介 1. 概述 1. Selector本身是Source的子组件,决定了将数据分发给哪个Channel。 2. Selector中提供了两种模式: …...

在线查看浏览器

随着网络的兴起&#xff0c;电影和电视剧已经成为我们生活中必不可少的乐趣。然而&#xff0c;像爱奇艺、优酷、腾讯、芒果等等这些平台&#xff0c;我们想要看好视频&#xff0c;需要开通VIP&#xff0c;虽然价格不是很高&#xff0c;但是我们能省则省啊&#xff0c;今天我就给…...

谷粒商城第七天-商品服务之分类管理下的分类的拖拽功能的实现

目录 一、总述 1.1 前端思路 1.2 后端思路 二、前端实现 2.1 判断是否能进行拖拽 2.2 收集受影响的节点&#xff0c;提交给服务器 三、后端实现 四、总结 一、总述 这个拖拽功能对于这种树形的列表&#xff0c;整体的搬迁是很方便的。但是其实现却并不是那么的简单。 …...

解决单节点es索引yellow

现象 单节点的es&#xff0c;自动创建索引后&#xff0c;默认副本个数为1&#xff0c;索引状态为yellow 临时解决 修改副本个数为0 永久解决 方法1、修改elasticsearch.yml文件&#xff0c;添加配置并重启es number_of_replicas&#xff1a;副本分片数&#xff0c;默认…...

Java虚拟机在类加载阶段都做了些什么,才使得我们可以运行Java程序

前言&#xff1a; 今天和大家探讨一道Java中经典的面试题&#xff0c;这道面试题经常出现在各个公司的面试中&#xff0c;结合周志明&#xff0c;老师的《深入理解Java虚拟机》书籍&#xff0c;本篇文章主要讲解Java类加载机制的知识。该专栏比较适合刚入坑Java的小白以及准备秋…...

华为认证 | 学HCIE,想培训需要注意啥?

HCIE&#xff08;华为认证网络专家&#xff09;是华为技术认证体系中的最高级别认证&#xff0c;对于网络工程师来说考试难度也比较高&#xff0c;一般来说&#xff0c;需要进行培训。 那么HCIE考试培训需要注意啥&#xff1f; 01 充分了解认证要求 在开始准备HCIE认证之前&a…...

这所211考数一英二,学硕降分33分,十分罕见!

一、学校及专业介绍 合肥工业大学&#xff08;Hefei University of Technology&#xff09;&#xff0c;简称“合工大”&#xff0c;校本部位于安徽省合肥市&#xff0c;是中华人民共和国教育部直属的全国重点大学&#xff0c;是国家“双一流”建设高校&#xff0c; 国家“211工…...

关于BQ27427的配置问题

EVM是TI家做的BQ27427的开发板&#xff0c;这款芯片还挺新的。 大概是这样&#xff0c;一块开发板要一千多块钱&#xff0c;使用的时候还出现了一些奇怪的问题。 配置使用的是买的盗版的EV2400&#xff0c;就是黑色的那个东西&#xff0c;使用的通信方式IIC。 TI手册上写的软件…...

试卷还原成空白卷怎么做?分享个简单的方法

在进行考试时&#xff0c;可能会填错答案或想要重新测试&#xff0c;此时需要正确擦除填写的试卷答案。下面介绍一些需要注意的事项以及正确的擦除方法。 使用橡皮擦或橡皮 正确的擦除方法是使用橡皮擦或橡皮对填写的答案进行擦除。首先&#xff0c;将橡皮擦或橡皮放置在试卷上…...