FSMC—扩展外部SRAM

一、SRAM控制原理

        STM32控制器芯片内部有一定大小的SRAMFLASH作为内存和程序存储空间,但当程序较大,内存和程序空间不足时,就需要在STM32芯片的外部扩展存储器了。STM32F103ZE系列芯片可以扩展外部SRAM用作内存。 

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

1.1 型号为IS62WV51216SRAM芯片外观

1.2  SRAM芯片的内部功能框架

 1.3 SRAM信号线

信号线

类型

说明

A0-A18

I

地址输入

I/O0-I/O7

I/O

数据输入输出信号,低字节

I/O8-I/O15

I/O

数据输入输出信号,高字节

CS2 CS1#

I

片选信号,CS2高电平有效,CS1#低电平有

效,部分芯片只有其中一个引脚

OE#

I

输出使能信号,低电平有效

WE#

I

写入使能,低电平有效

UB#

I

数据掩码信号Upper Byte,高位字节允许访问,低电平有效,

LB#

I

数据掩码信号Lower Byte,低位字节允许访问,低电平有效

        SRAM的控制比较简单,只要控制信号线使能了访问,从地址线输入要访问的地址,即可从I/O数据线写入或读出数据。

1.4 SRAM的存储矩阵

         SRAM内部包含的存储阵列,可以把它理解成一张表格,数据就填在这张表格上。和表格查找一样,指定一个行地址和列地址,就可以精确地找到目标单元格,这是SRAM芯片寻址的基本原理。这样的每个单元格被称为存储单元,而这样的表则被称为存储矩阵。

1.5 地址译码器、列I/OI/O数据电路

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

        本实例中的SRAM比较小,没有列地址线,它的数据宽度为16位,即一个行地址对应2字节空间,框图中左侧的A0-A18是行址信号,18根地址线一共可以表示218=28x1024=512K行存储单元,所以它一共能访问512Kx16bits大小的空间。访问时,使用UB#LB#线控制数据宽度。

1.6 控制电路

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

1.7 SRAM的读写流程

SRAM进行数据时,它各个信号线的时序流程如下:

无时钟线,异步通信,通过时间参数来协调通信,要求地址线通过A0-A18来告诉SRAM要读取哪一个地址的单元格。

tRC:地址线的保持时间

tDOE:读使能过了一段时间,给了读使能OE信号后多长时间,SRAM可以输出数据,且这个数据线会保持一段时间使STM32能够有时间去读取数据,给出OE信号后,数据输出的时间

tOHA:从使能信号开始以后给出数据到读取周期过程结束后,还会保持tOHA的事故华北

所以在tAA之后进行采样就可以读取到有效的数据

tAA:从给出地址之后到数据出现,也就是返回数数据的过程的时间

 SRAM进行数据时,它各个信号线的时序流程如下:读写时序的流程很类似,过程如下:

(1)  主机使用地址信号线发出要访问的存储器目标地址;

(2)  控制片选信号CS1#CS2#使能存储器芯片;

(3)  若是要进行读操作,则控制读使能信号OE#表示要读数据,若进行写操作则控制写使能信号WE#表示要写数据;

(4)  使用掩码信号LB#UB#指示要访问目标地址的高、低字节部分;

(5)  若是读取过程,存储器会通过数据线向主机输出目标数据,若是写入过程,主要使用数据线向存储器传输目标数据。

SRAM的读写时序参数

时间参数

IS62WV51216BLL-55ns型号要求的最短时间

说明

tRC

55ns

读操作周期

tAA

0ns

地址访问时间

tWC

55ns

写操作周期

tSA

0ns

地址建立时间

tSD

25ns

数据建立至写结束的时间

tHD

0ns

数据写结束后的保持时间

在读写时序中,有几个比较重要的时间参数,在使用STM32 控制的时候需要参考,它们的介绍见表

二、STM32FSMC特性及架构

        STM32F1系列芯片使用FSMC外设来管理扩展的存储器FSMCFlexible Static Memory Controller的缩写,译为灵活的静态存储控制器。它可以用于驱动包括SRAMNOR FLASH以及NAND FLSAH类型的存储器,不能驱动如SDRAM这种动态的存储器,而在STM32F429系列的控制器中,它具有FMC外设,支持控制SDRAM存储器。

FSMC框图剖析

  • 通讯引脚
  • 存储器控制器
  • 时钟控制逻辑

2.1 通讯引脚 

        由于控制不同类型存储器的时候会有一些不同的引脚,看起来有非常多,其中地址线FSMC_A和数据线FSMC_D是所有控制器都共用的

FSMC引脚名称

对应SRAM引脚名

说明

FSMC_NBL[1:0]

LB#UB#

数据掩码信号

FSMC_A[18:0]

A[18:0]

行地址线

FSMC_D[15:0]

I/O[15:0]

数据线

FSMC_NWE

WE#

写入使能

FSMC_NOE

OE#

输出使能(读使能)

FSMC_NE[1:4]

CE#

片选信号

2.2 SRAM信号线

        其中比较特殊的FSMC_NE是用于控制SRAM芯片的控制信号线,STM32具有FSMC_NE1/2/3/4号引脚,不同的引脚对应STM32内部不同的地址区域。

        例如,当STM32访问0x68000000-0x6BFFFFFF地址空间时,FSMC_NE3引脚会自动设置为低电平,由于它连接到SRAMCE#引脚,所以SRAM的片选被使能,而访问0x60000000-0x63FFFFFF地址时,FSMC_NE1会输出低电平。当使用不同的FSMC_NE引脚连接外部存储器时,STM32访问SRAM的地址不一样,从而达到控制多块SRAM芯片的目的。

2.3 存储器控制器

        上面不同类型的引脚是连接到FSMC内部对应的存储控制器中的。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控制寄存器可配置要控制的存储器类型、数据线宽度以及信号有效极性能参数。
  • FMC_BTR时序寄存器用于配置SRAM访问时的各种时间延迟,如数据保持时间、地址保持时间等。
  • FMC_BWTR写时序寄存器与FMC_BTR寄存器控制的参数类似,它专门用于控制写时序的时间参数。

2.4 时钟控制逻辑

        FSMC外设挂载在AHB总线上,时钟信号来自于HCLK(默认72MHz),控制器的同步时钟输出就是由它分频得到。例如,NOR控制器的FSMC_CLK引脚输出的时钟,它可用于与同步类型的SRAM芯片进行同步通讯,它的时钟频率可通过FSMC_BTR寄存器的CLKDIV位配置,可以配置为HCLK1/21/3,也就是说,若它与同步类型的SRAM通讯时,同步时钟最高频率为36MHz。本示例中的SRAM为异步类型的存储器,不使用同步时钟信号,所以时钟分频配置不起作用。

2.5 FSMC的地址映射 

         FSMC连接好外部的存储器并初始化后,就可以直接通过访问地址来读写数据

        FSMC访问存储器的方式与I2C EEPROMSPI FLASH的不一样,后两种方式都需要控制I2CSPI总线给存储器发送地址,然后获取数据;在程序里,这个地址和数据都需要分开使用不同的变量存储,并且访问时还需要使用代码控制发送读写命令。

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

        图中左侧的是Cortex-M3内核的存储空间分配,右侧是STM32 FSMC外设的地址映射。可以看到FSMCNOR/PSRAM/SRAM/NAND FLASH以及PC卡的地址都在External RAM地址空间内。

        正是因为存在这样的地址映射,使得访问FSMC控制的存储器时,就跟访问STM32的片上外设寄存器一样(片上外设的地址映射即图中左侧的“Peripheral”区域)

        FSMC把整个External RAM存储区域分成了4Bank区域,并分配了地址范围及适用的存储器类型,如NORSRAM存储器只能使用Bank1的地址。

        在NORSRAM区域,每个Bank的内部又分成了4个小块,每个小块有相应的控制引脚用于连接片选信号,如FSMC_NE[4:1]信号线可用于选择BANK1内部的4小块地址区域,当STM32访问0x68000000-0x6BFFFFFF地址空间时,会访问到Bank1的第3小块区域,相应的FSMC_NE3信号线会输出控制信号。

2.6 FSMC控制SRAM的时序 

        FSMC外设支持输出多种不同的时序以便于控制不同的存储器,它具有ABCD四种模式,下面我们仅针对控制SRAM使用的模式A进行讲解

读时序 

当内核发出访问某个指向外部存储器地址时,FSMC外设会根据配置控制信号线产生时序访问存储器,上图中的是访问外部SRAMFSMC外设的读写时序。

 以读时序为例,该图表示一个存储器操作周期由地址建立周期(ADDSET)、数据建立周期(DATAST)以及2HCLK周期组成。在地址建立周期中,地址线发出要访问的地址,数据掩码信号线指示出要读取地址的高、低字节部分,片选信号使能存储器芯片;地址建立周期结束后读使能信号线发出读使能信号,接着存储器通过数据信号线把目标数据传输给FSMCFSMC把它交给内核。

  写时序类似,区别是它的一个存储器操作周期仅由地址建立周期(ADDSET)和数据建立周期(DATAST)组成,且在数据建立周期期间写使能信号线发出写信号,接着FSMC把数据通过数据线传输到存储器中。

写时序

当内核发出访问某个指向外部存储器地址时,FSMC外设会根据配置控制信号线产生时序访问存储器,上图中的是访问外部SRAM时FSMC外设的读写时序。

以读时序为例,该图表示一个存储器操作周期由地址建立周期(ADDSET)、数据建立
周期(DATAST)以及2 个HCLK周期组成。在地址建立周期,地址线发出要访问的地址,数据掩码信号线指示出要读取地址的高、低字节部分,片选信号使能存储器芯片;地址建
立周期结束后读使能信号线发出读使能信号,接着存储器通过数据信号线把目标数据传输
给FSMC,FSMC 把它交给内核。
写时序类似,区别是它的一个存储器操作周期仅由地址建立周期(ADDSET)和数据建
立周期(DATAST)组成,且在数据建立周期期间写使能信号线发出写信号,接着FSMC把数
据通过数据线传输到存储器中。

三、FSMC控制SRAM的相关结构体

控制FSMC使用SRAM存储器时主要是配置时序寄存器以及控制寄存器,利用ST标准库的SRAM时序结构体以及初始化结构体可以很方便地写入参数。 

  • 时序结构体:FSMC_NORSRAMTimingInitTypeDef
  • 初始化结构体:FSMC_NORSRAMInitTypeDef

3.1 FSMC时序结构体 

FSMCSRAM时序结构体成员定义的都是SRAM读写时序中的各项时间参数,这些成员的的参数都与FSMC_BRTFSMC_BWTR寄存器配置对应

  • FSMC_AddressSetupTime  本成员设置地址建立时间,它可以被设置为0-0xFHCLK周期数,按STM32标准库的默认配置,HCLK的时钟频率为72MHz,即一个HCLK周期为1/72微秒。
  • FSMC_AddressHoldTime 本成员设置地址保持时间,它可以被设置为0-0xFHCLK周期数。
  • FSMC_DataSetupTime 本成员设置数据建立时间,它可以被设置为0-0xFHCLK周期数。
  • FSMC_BusTurnAroundDuration 本成员设置总线转换周期,在NOR FLASH存储器中,地址线与数据线可以分时复用,总线转换周期就是指总线在这两种状态间切换需要的延时,防止冲突。控制其它存储器时这个参数无效,配置为0即可。
  • FSMC_CLKDivision 本成员用于设置时钟分频,它以HCLK时钟作为输入,经过FSMC_CLKDivision分频后输出到FSMC_CLK引脚作为通讯使用的同步时钟。控制其它异步通讯的存储器时这个参数无效,配置为0即可。
  • FSMC_DataLatency 本成员设置数据保持时间,它表示在读取第一个数据之前要等待的周期数,该周期指同步时钟的周期,本参数仅用于同步NOR FLASH类型的存储器,控制其它类型的存储器时,本参数无效。
  • FSMC_DataLatency 本成员设置数据保持时间,它表示在读取第一个数据之前要等待的周期数,该周期指同步时钟的周期,本参数仅用于同步NOR FLASH类型的存储器,控制其它类型的存储器时,本参数无效。
  • FSMC_AccessMode 本成员设置存储器访问模式,不同的模式下FSMC访问存储器地址时引脚输出的时序不一样,可选FSMC_AccessMode_A/B/C/D模式。一般来说控制SRAM时使用A模式。

  这个FSMC_NORSRAMTimingInitTypeDef 时序结构体配置的延时参数,将作为下一节的FSMC SRAM初始化结构体的一个成员。

3.2 FSMCSRAM初始化结构体

        FSMC初始化结构体,除最后两个成员是上一小节讲解的时序配置外,其它结构体成员的配置都对应到FSMC_BCR中的寄存器位。

可以输入的宏

对应的地址区域

FSMC_Bank1_NORSRAM1

0x60000000-0x63FFFFFF

FSMC_Bank1_NORSRAM2

0x64000000-0x67FFFFFF

FSMC_Bank1_NORSRAM3

0x68000000-0x6BFFFFFF

FSMC_Bank1_NORSRAM4

0x6C000000-0x6FFFFFFF

  • FSMC_Bank本成员用于选择FSMC映射的存储区域,它的可选参数以及相应的内核地址映射范围见上面的表格
  • FSMC_DataAddressMux本成员用于设置地址总线与数据总线是否复用(FSMC_DataAddressMux_Enable /Disable),在控制NOR FLASH时,可以地址总线与数据总线可以分时复用,以减少使用STM32信号线的数量。
  • FSMC_MemoryType本成员用于设置要控制的存储器类型,它支持控制的存储器类型为SRAMPSRAM以及NOR FLASH(FSMC_MemoryType_SRAM/PSRAM/NOR)
  • FSMC_MemoryDataWidth 本成员用于设置要控制的存储器的数据宽度,可选择设置成816(FSMC_MemoryDataWidth_8b /16b)
  • FSMC_BurstAccessMode 本成员用于设置是否使用突发访问模式(FSMC_BurstAccessMode_Enable/Disable),突发访问模式是指发送一个地址后连续访问多个数据,非突发模式下每访问一个数据都需要输入一个地址,仅在控制同步类型的存储器时才能使用突发模式。
  • • FSMC_AsynchronousWait 本成员用于设置是否使能在同步传输时使用的等待信号(FSMC_AsynchronousWait_Enable/Disable),在控制同步类型的NORPSRAM时,存储器可以使用FSMC_NWAIT引脚通知STM32需要等待。
  • FSMC_WaitSignalPolarity 本成员用于设置等待信号的有效极性,即要求等待时,使用高电平还是低电平(FSMC_WaitSignalPolarity_High/Low)
  • FSMC_WrapMode 本成员用于设置是否支持把非对齐的AHB突发操作分割成2次线性操作(FSMC_WrapMode_Enable/Disable),该配置仅在突发模式下有效。
  • FSMC_WaitSignalActive 本成员用于配置在突发传输模式时,决定存储器是在等待状态之前的一个数据周期有效还是在等待状态期间有效(FSMC_WaitSignalActive_BeforeWaitState/DuringWaitState)
  • FSMC_WriteOperation 这个成员用于设置是否写使能(FSMC_WriteOperation_ Enable /Disable),禁止写使能的话FSMC只能从存储器中读取数据,不能写入。
  • FSMC_WaitSignal 本成员用于设置当存储器牌突发传输模式时,是否允许通过NWAIT信号插入等待状态(FSMC_WaitSignal_Enable/Disable)
  • FSMC_ExtendedMode 本成员用于设置是否使用扩展模式(FSMC_ExtendedMode_Enable/Disable),在非扩展模式下,对存储器读写的时序都只使用FSMC_BCR寄存器中的配置,即下面的FSMC_ReadWriteTimingStruct结构体成员;在扩展模式下,对存储器的读写时序可以分开配置,读时序使用FSMC_BCR寄存器,写时序使用FSMC_BWTR寄存器的配置,即下面的FSMC_WriteTimingStruct结构体。
  • FSMC_ReadWriteTimingStruct 本成员是一个指针,赋值时使用上一小节中讲解的时序结构体FSMC_NORSRAMInitTypeDef设置,当不使用扩展模式时,读写时序都使用本成员的参数配置。
  • FSMC_WriteTimingStruct 同样地,本成员也是一个时序结构体的指针,只有当使用扩展模式时,本配置才有效,它是写操作使用的时序。

四、FSMC—扩展外部SRAM

接下来对时序结构体FSMC_NORSRAMTimingInitTypeDef 赋值。在这个时序结构体配
置中,由于我们要控制的是SRAM,所以选择FSMC 为模式A,在该模式下配置FSMC 的
控制时序结构体中,实际上只有地址建立时间FSMC_AddressSetupTime(即ADDSET 的值)
以及数据建立时间FSMC_DataSetupTime(即DATAST 的值)成员的配置值是有效的,其
它SRAM没使用到的成员值全配置为0 即可。而且,这些成员值使用的单位为:1 个HCLK
的时钟周期,而HCLK 的时钟频率为72MHz,对应每个时钟周期为1/72 微秒。


FSMC 时序配置与SRAM 时序参数要求对比(读)

由上图的FSMC 时序和SRAM时序对比及SRAM时间参数要求可总结下表最右侧的计算表达式。

根据FSMC配置表达式的配置要求把时间单位1/72 微秒(即1000/72 纳秒)代入,可求得
ADDSET = 0,DATAST=1 时即可符合要求。如:

tRC=ADDSET+1+DATAST+1+2 =( 0+1+1+1+2 )*1000/72 = 69 ns > 55 ns
tDOE=DATAST+1 = (1+1)*1000/72 = 27.7 > 25 ns
不过,经实验总结出该配置在连续读取多个数据的时候会出现问题,更正确的配置为
ADDSET=0,DATAST=2,而这样的配置与写时序是一致的,下面再来列出写时序的计算
过程:

FSMC 时序配置与SRAM 时序参数要求对比(写) 

根据FSMC配置表达式的配置要求把时间单位1/72 微秒(即1000/72 纳秒)代入,可求得
ADDSET = 0,DATAST=2 时即可符合要求。如:
tWC = ADDSET+1+DATAST+1 =( 0+1+2+1 )*1000/72 = 55.555 ns > 55 ns
tPWB = DATAST+1 = (2+1) *1000/72 = 41.6666 > 40 ns
把计算得的参数赋值到时序结构体中的FSMC_AddressSetupTime(即ADDSET 的值)
及FSMC_DataSetupTime(即DATAST 的值)中,然后再把时序结构体作为指针赋值到下
面的FSMC 初始化结构体中,作为读写的时序参数,最后再调用FSMC_NORSRAMInit 函
数即可把参数写入到相应的寄存器中。

bsp_sram.c

  *******************************************************************************/#include "./sram/bsp_sram.h"/*** @brief  初始化控制SRAM的IO* @param  无* @retval 无*/
static void SRAM_GPIO_Config(void)
{GPIO_InitTypeDef  GPIO_InitStructure;/* 使能SRAM相关的GPIO时钟 *//*地址信号线*/RCC_APB2PeriphClockCmd(FSMC_A0_GPIO_CLK | FSMC_A1_GPIO_CLK | FSMC_A2_GPIO_CLK | FSMC_A3_GPIO_CLK | FSMC_A4_GPIO_CLK | FSMC_A5_GPIO_CLK |FSMC_A6_GPIO_CLK | FSMC_A7_GPIO_CLK | FSMC_A8_GPIO_CLK |FSMC_A9_GPIO_CLK | FSMC_A10_GPIO_CLK| FSMC_A11_GPIO_CLK| FSMC_A12_GPIO_CLK| FSMC_A13_GPIO_CLK|FSMC_A14_GPIO_CLK |FSMC_A15_GPIO_CLK|FSMC_A16_GPIO_CLK |FSMC_A17_GPIO_CLK |FSMC_A18_GPIO_CLK|/*数据信号线*/FSMC_D0_GPIO_CLK | FSMC_D1_GPIO_CLK | FSMC_D2_GPIO_CLK | FSMC_D3_GPIO_CLK | FSMC_D4_GPIO_CLK | FSMC_D5_GPIO_CLK |FSMC_D6_GPIO_CLK | FSMC_D7_GPIO_CLK | FSMC_D8_GPIO_CLK |FSMC_D9_GPIO_CLK | FSMC_D10_GPIO_CLK| FSMC_D11_GPIO_CLK|FSMC_D12_GPIO_CLK| FSMC_D13_GPIO_CLK| FSMC_D14_GPIO_CLK|FSMC_D15_GPIO_CLK|  /*控制信号线*/FSMC_CS_GPIO_CLK  | FSMC_WE_GPIO_CLK | FSMC_OE_GPIO_CLK |FSMC_UDQM_GPIO_CLK|FSMC_LDQM_GPIO_CLK, ENABLE);/*-- GPIO 配置 -----------------------------------------------------*//* 通用 GPIO 配置 */GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;       //配置为复用功能GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     /*A地址信号线 针对引脚配置*/GPIO_InitStructure.GPIO_Pin = FSMC_A0_GPIO_PIN; GPIO_Init(FSMC_A0_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A1_GPIO_PIN; GPIO_Init(FSMC_A1_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A2_GPIO_PIN; GPIO_Init(FSMC_A2_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A3_GPIO_PIN; GPIO_Init(FSMC_A3_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A4_GPIO_PIN; GPIO_Init(FSMC_A4_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A5_GPIO_PIN; GPIO_Init(FSMC_A5_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A6_GPIO_PIN; GPIO_Init(FSMC_A6_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A7_GPIO_PIN; GPIO_Init(FSMC_A7_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A8_GPIO_PIN; GPIO_Init(FSMC_A8_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A9_GPIO_PIN; GPIO_Init(FSMC_A9_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A10_GPIO_PIN; GPIO_Init(FSMC_A10_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A11_GPIO_PIN; GPIO_Init(FSMC_A11_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A12_GPIO_PIN; GPIO_Init(FSMC_A12_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A13_GPIO_PIN; GPIO_Init(FSMC_A13_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A14_GPIO_PIN; GPIO_Init(FSMC_A14_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A15_GPIO_PIN; GPIO_Init(FSMC_A15_GPIO_PORT, &GPIO_InitStructure);	GPIO_InitStructure.GPIO_Pin = FSMC_A16_GPIO_PIN; GPIO_Init(FSMC_A16_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A17_GPIO_PIN; GPIO_Init(FSMC_A17_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_A18_GPIO_PIN; GPIO_Init(FSMC_A18_GPIO_PORT, &GPIO_InitStructure);/*DQ数据信号线 针对引脚配置*/GPIO_InitStructure.GPIO_Pin = FSMC_D0_GPIO_PIN; GPIO_Init(FSMC_D0_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D1_GPIO_PIN; GPIO_Init(FSMC_D1_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D2_GPIO_PIN; GPIO_Init(FSMC_D2_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D3_GPIO_PIN; GPIO_Init(FSMC_D3_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D4_GPIO_PIN; GPIO_Init(FSMC_D4_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D5_GPIO_PIN; GPIO_Init(FSMC_D5_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D6_GPIO_PIN; GPIO_Init(FSMC_D6_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D7_GPIO_PIN; GPIO_Init(FSMC_D7_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D8_GPIO_PIN; GPIO_Init(FSMC_D8_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D9_GPIO_PIN; GPIO_Init(FSMC_D9_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D10_GPIO_PIN; GPIO_Init(FSMC_D10_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D11_GPIO_PIN; GPIO_Init(FSMC_D11_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D12_GPIO_PIN; GPIO_Init(FSMC_D12_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D13_GPIO_PIN; GPIO_Init(FSMC_D13_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D14_GPIO_PIN; GPIO_Init(FSMC_D14_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_D15_GPIO_PIN; GPIO_Init(FSMC_D15_GPIO_PORT, &GPIO_InitStructure);/*控制信号线*/GPIO_InitStructure.GPIO_Pin = FSMC_CS_GPIO_PIN; GPIO_Init(FSMC_CS_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_WE_GPIO_PIN; GPIO_Init(FSMC_WE_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_OE_GPIO_PIN; GPIO_Init(FSMC_OE_GPIO_PORT, &GPIO_InitStructure);    GPIO_InitStructure.GPIO_Pin = FSMC_UDQM_GPIO_PIN; GPIO_Init(FSMC_UDQM_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = FSMC_LDQM_GPIO_PIN; GPIO_Init(FSMC_LDQM_GPIO_PORT, &GPIO_InitStructure);	
}		
/*** @brief  初始化FSMC外设* @param  None. * @retval None.*/
void FSMC_SRAM_Init(void)
{	FSMC_NORSRAMTimingInitTypeDef   FSMC_ReadTimingStruct;FSMC_NORSRAMTimingInitTypeDef   FSMC_WriteTimingStruct;FSMC_NORSRAMInitTypeDef	FSMC_NORSRAMInitStructure;RCC_AHBPeriphClockCmd  ( RCC_AHBPeriph_FSMC , ENABLE ) ;//读时序FSMC_ReadTimingStruct.FSMC_AccessMode = FSMC_AccessMode_A ;FSMC_ReadTimingStruct.FSMC_AddressHoldTime = 0;				//SRAM没用到FSMC_ReadTimingStruct.FSMC_AddressSetupTime = 0;			//理论值FSMC_ReadTimingStruct.FSMC_BusTurnAroundDuration =  0;//SRAM没用到FSMC_ReadTimingStruct.FSMC_CLKDivision = 0;						//SRAM没用到FSMC_ReadTimingStruct.FSMC_DataLatency = 0;						//SRAM没用到FSMC_ReadTimingStruct.FSMC_DataSetupTime = 2;					//2是经验值 理论值是1//写时序FSMC_ReadTimingStruct.FSMC_AccessMode = FSMC_AccessMode_A ;FSMC_ReadTimingStruct.FSMC_AddressHoldTime = 0;				//SRAM没用到FSMC_ReadTimingStruct.FSMC_AddressSetupTime = 0;			//理论值FSMC_ReadTimingStruct.FSMC_BusTurnAroundDuration =  0;//SRAM没用到FSMC_ReadTimingStruct.FSMC_CLKDivision = 0;						//SRAM没用到FSMC_ReadTimingStruct.FSMC_DataLatency = 0;						//SRAM没用到FSMC_ReadTimingStruct.FSMC_DataSetupTime = 2;					//2是经验值 理论值是1FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable;FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;FSMC_NORSRAMInitStructure.FSMC_MemoryType =  FSMC_MemoryType_SRAM;FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable ;FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;	FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_ReadTimingStruct;FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignalPolarity_Low;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_WriteTimingStruct;//把配置写入到寄存器FSMC_NORSRAMInit  ( &FSMC_NORSRAMInitStructure ) ;//使能FSMCFSMC_NORSRAMCmd  ( FSMC_Bank1_NORSRAM3, ENABLE );						}void SARM_Init(void )
{SRAM_GPIO_Config();FSMC_SRAM_Init();}/*********************************************END OF FILE**********************/

bsp_sram.h

//使用NOR/SRAM的 Bank1.sector3,地址位HADDR[27,26]=10 
//对IS61LV25616/IS62WV25616,地址线范围为A0~A17 
//对IS61LV51216/IS62WV51216,地址线范围为A0~A18
#define Bank1_SRAM3_ADDR    ((uint32_t)(0x68000000))		#define IS62WV51216_SIZE 0x100000  //512*16/2bits = 0x100000  ,1M字节/*A地址信号线*/    
#define FSMC_A0_GPIO_PORT        GPIOF
#define FSMC_A0_GPIO_CLK         RCC_APB2Periph_GPIOF
#define FSMC_A0_GPIO_PIN         GPIO_Pin_0#define FSMC_A1_GPIO_PORT        GPIOF
#define FSMC_A1_GPIO_CLK         RCC_APB2Periph_GPIOF
#define FSMC_A1_GPIO_PIN         GPIO_Pin_1#define FSMC_A2_GPIO_PORT        GPIOF
#define FSMC_A2_GPIO_CLK         RCC_APB2Periph_GPIOF
#define FSMC_A2_GPIO_PIN         GPIO_Pin_2#define FSMC_A3_GPIO_PORT        GPIOF
#define FSMC_A3_GPIO_CLK         RCC_APB2Periph_GPIOF
#define FSMC_A3_GPIO_PIN         GPIO_Pin_3#define FSMC_A4_GPIO_PORT        GPIOF
#define FSMC_A4_GPIO_CLK         RCC_APB2Periph_GPIOF
#define FSMC_A4_GPIO_PIN         GPIO_Pin_4#define FSMC_A5_GPIO_PORT        GPIOF
#define FSMC_A5_GPIO_CLK         RCC_APB2Periph_GPIOF
#define FSMC_A5_GPIO_PIN         GPIO_Pin_5#define FSMC_A6_GPIO_PORT        GPIOF
#define FSMC_A6_GPIO_CLK         RCC_APB2Periph_GPIOF
#define FSMC_A6_GPIO_PIN         GPIO_Pin_12#define FSMC_A7_GPIO_PORT        GPIOF
#define FSMC_A7_GPIO_CLK         RCC_APB2Periph_GPIOF
#define FSMC_A7_GPIO_PIN         GPIO_Pin_13#define FSMC_A8_GPIO_PORT        GPIOF
#define FSMC_A8_GPIO_CLK         RCC_APB2Periph_GPIOF
#define FSMC_A8_GPIO_PIN         GPIO_Pin_14#define FSMC_A9_GPIO_PORT        GPIOF
#define FSMC_A9_GPIO_CLK         RCC_APB2Periph_GPIOF
#define FSMC_A9_GPIO_PIN         GPIO_Pin_15#define FSMC_A10_GPIO_PORT        GPIOG
#define FSMC_A10_GPIO_CLK         RCC_APB2Periph_GPIOG
#define FSMC_A10_GPIO_PIN         GPIO_Pin_0#define FSMC_A11_GPIO_PORT        GPIOG
#define FSMC_A11_GPIO_CLK         RCC_APB2Periph_GPIOG
#define FSMC_A11_GPIO_PIN         GPIO_Pin_1#define FSMC_A12_GPIO_PORT        GPIOG
#define FSMC_A12_GPIO_CLK         RCC_APB2Periph_GPIOG
#define FSMC_A12_GPIO_PIN         GPIO_Pin_2#define FSMC_A13_GPIO_PORT        GPIOG
#define FSMC_A13_GPIO_CLK         RCC_APB2Periph_GPIOG
#define FSMC_A13_GPIO_PIN         GPIO_Pin_3#define FSMC_A14_GPIO_PORT        GPIOG
#define FSMC_A14_GPIO_CLK         RCC_APB2Periph_GPIOG
#define FSMC_A14_GPIO_PIN         GPIO_Pin_4#define FSMC_A15_GPIO_PORT        GPIOG
#define FSMC_A15_GPIO_CLK         RCC_APB2Periph_GPIOG
#define FSMC_A15_GPIO_PIN         GPIO_Pin_5#define FSMC_A16_GPIO_PORT        GPIOD
#define FSMC_A16_GPIO_CLK         RCC_APB2Periph_GPIOD
#define FSMC_A16_GPIO_PIN         GPIO_Pin_11#define FSMC_A17_GPIO_PORT        GPIOD
#define FSMC_A17_GPIO_CLK         RCC_APB2Periph_GPIOD
#define FSMC_A17_GPIO_PIN         GPIO_Pin_12#define FSMC_A18_GPIO_PORT        GPIOD
#define FSMC_A18_GPIO_CLK         RCC_APB2Periph_GPIOD
#define FSMC_A18_GPIO_PIN         GPIO_Pin_13/*D 数据信号线*/
#define FSMC_D0_GPIO_PORT        GPIOD
#define FSMC_D0_GPIO_CLK         RCC_APB2Periph_GPIOD
#define FSMC_D0_GPIO_PIN         GPIO_Pin_14#define FSMC_D1_GPIO_PORT        GPIOD
#define FSMC_D1_GPIO_CLK         RCC_APB2Periph_GPIOD
#define FSMC_D1_GPIO_PIN         GPIO_Pin_15#define FSMC_D2_GPIO_PORT        GPIOD
#define FSMC_D2_GPIO_CLK         RCC_APB2Periph_GPIOD
#define FSMC_D2_GPIO_PIN         GPIO_Pin_0#define FSMC_D3_GPIO_PORT        GPIOD
#define FSMC_D3_GPIO_CLK         RCC_APB2Periph_GPIOD
#define FSMC_D3_GPIO_PIN         GPIO_Pin_1#define FSMC_D4_GPIO_PORT        GPIOE
#define FSMC_D4_GPIO_CLK         RCC_APB2Periph_GPIOE
#define FSMC_D4_GPIO_PIN         GPIO_Pin_7#define FSMC_D5_GPIO_PORT        GPIOE
#define FSMC_D5_GPIO_CLK         RCC_APB2Periph_GPIOE
#define FSMC_D5_GPIO_PIN         GPIO_Pin_8#define FSMC_D6_GPIO_PORT        GPIOE
#define FSMC_D6_GPIO_CLK         RCC_APB2Periph_GPIOE
#define FSMC_D6_GPIO_PIN         GPIO_Pin_9#define FSMC_D7_GPIO_PORT        GPIOE
#define FSMC_D7_GPIO_CLK         RCC_APB2Periph_GPIOE
#define FSMC_D7_GPIO_PIN         GPIO_Pin_10#define FSMC_D8_GPIO_PORT        GPIOE
#define FSMC_D8_GPIO_CLK         RCC_APB2Periph_GPIOE
#define FSMC_D8_GPIO_PIN         GPIO_Pin_11#define FSMC_D9_GPIO_PORT        GPIOE
#define FSMC_D9_GPIO_CLK         RCC_APB2Periph_GPIOE
#define FSMC_D9_GPIO_PIN         GPIO_Pin_12#define FSMC_D10_GPIO_PORT        GPIOE
#define FSMC_D10_GPIO_CLK         RCC_APB2Periph_GPIOE
#define FSMC_D10_GPIO_PIN         GPIO_Pin_13#define FSMC_D11_GPIO_PORT        GPIOE
#define FSMC_D11_GPIO_CLK         RCC_APB2Periph_GPIOE
#define FSMC_D11_GPIO_PIN         GPIO_Pin_14#define FSMC_D12_GPIO_PORT        GPIOE
#define FSMC_D12_GPIO_CLK         RCC_APB2Periph_GPIOE
#define FSMC_D12_GPIO_PIN         GPIO_Pin_15#define FSMC_D13_GPIO_PORT        GPIOD
#define FSMC_D13_GPIO_CLK         RCC_APB2Periph_GPIOD
#define FSMC_D13_GPIO_PIN         GPIO_Pin_8#define FSMC_D14_GPIO_PORT        GPIOD
#define FSMC_D14_GPIO_CLK         RCC_APB2Periph_GPIOD
#define FSMC_D14_GPIO_PIN         GPIO_Pin_9#define FSMC_D15_GPIO_PORT        GPIOD
#define FSMC_D15_GPIO_CLK         RCC_APB2Periph_GPIOD
#define FSMC_D15_GPIO_PIN         GPIO_Pin_10/*控制信号线*/  
/*CS片选*/
/*NE3 ,对应的基地址0x68000000*/
#define FSMC_CS_GPIO_PORT        GPIOG
#define FSMC_CS_GPIO_CLK         RCC_APB2Periph_GPIOG
#define FSMC_CS_GPIO_PIN         GPIO_Pin_10/*WE写使能*/
#define FSMC_WE_GPIO_PORT        GPIOD
#define FSMC_WE_GPIO_CLK         RCC_APB2Periph_GPIOD
#define FSMC_WE_GPIO_PIN         GPIO_Pin_5/*OE读使能*/
#define FSMC_OE_GPIO_PORT        GPIOD
#define FSMC_OE_GPIO_CLK         RCC_APB2Periph_GPIOD
#define FSMC_OE_GPIO_PIN         GPIO_Pin_4/*UB数据掩码*/
#define FSMC_UDQM_GPIO_PORT        GPIOE
#define FSMC_UDQM_GPIO_CLK         RCC_APB2Periph_GPIOE
#define FSMC_UDQM_GPIO_PIN         GPIO_Pin_1/*LB数据掩码*/
#define FSMC_LDQM_GPIO_PORT        GPIOE
#define FSMC_LDQM_GPIO_CLK         RCC_APB2Periph_GPIOE
#define FSMC_LDQM_GPIO_PIN         GPIO_Pin_0//SRAM初始化
void SARM_Init(void );#endif /* __SRAM_H */

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

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

相关文章

【计算机网络】TCP原理 | 可靠性机制分析(一)

个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】【Java系列】 本专栏旨在分享学习网络编程、计算机网络的一点学习心得,欢迎大家在评论区交流讨论💌 目…

sensor 点亮出图后,画面全黑是为什么?

同事在点一个思特威的 sensor sc035hgs,这个 sensor 主要负责数据采集,然后给到后面的 NN(神经网络)去做处理。 点亮出图后,画面很黑,如下图所示: 因为没拿到板子,只能盲猜&#xf…

面试官:说说HashMap和HashTable的区别

程序员的公众号:源1024,获取更多资料,无加密无套路! 最近整理了一波电子书籍资料,包含《Effective Java中文版 第2版》《深入JAVA虚拟机》,《重构改善既有代码设计》,《MySQL高性能-第3版》&…

算法日志的存在核心在于搭建自检系统

"相信每一个人执行与日志有关的任务都会遇到这样难题吧?长达几万行的日志,如果我们单纯用肉眼去一个个排查,那么恐怕所耗费的时间是以天为计量单位了。当然这是一种比较夸张的情况,根据我的项目经验,正常情况是十…

每日一博 - 多租户技术及其三种数据存储策略

文章目录 概述应用程序隔离数据隔离小结 概述 多租户技术(Multi-Tenant Technology)是软件即服务(SaaS)架构中的一项核心技术,允许单一软件应用或服务同时服务于多个客户(即“租户”)&#xff…

软件测试|Python函数参数之必传参数、默认参数、可变参数、关键字参数的详细使用

在Python中,函数参数是定义在函数头部的变量,用于接收传递给函数的数据。Python函数参数有四种类型:必传参数、默认参数、可变参数和关键字参数。每种类型都有不同的使用方式和适用场景。本文将详细介绍这四种函数参数的使用方法。 Python函…

ArkTS - 网络请求

一、Axios请求 应用通过HTTP发起一个数据请求,支持常见的GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT方法。 前端开发肯定都使用过一个叫axios的第三方库,它是是一个基于 promise 的网络请求库,可以用于浏览器和 node.js&…

关于曲率、曲率半径和曲率圆,看这几篇文章就够啦

关于曲率、曲率半径和曲率圆的内容,是考研数学数学一和数学二大纲中明确要求掌握的内容,但这部分内容在很多教材教辅以及练习题中较少涉及。在本文中,荒原之梦考研数学网就为大家整理了曲率、曲率半径和曲率圆方程相关的概念、基础知识以及练…

LauraGPT

git:https://github.com/alibaba-damo-academy/FunCodec 文章目录 model archAudioTokenizermodel init model arch text-embedding 用千问的模型参数初始化;AudioEncoder用asr-conformer的参数初始化;所有的参数都参与更新,除了C…

实时语义分割模型PP-LiteSeg论文解读

paper:PP-LiteSeg: A Superior Real-Time Semantic Segmentation Model official implementation:https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.8/paddleseg/models/pp_liteseg.py 本文的创新点 提出了一种灵活的轻量级解码器&#xf…

SpringBoot+Vue轻松实现考试管理系统

简介 本系统基于 Spring Boot 搭建的方便易用、高颜值的教学管理平台,提供多租户、权限管理、考试、练习、在线学习等功能。主要功能为在线考试、练习、刷题,在线学习。课程内容支持图文、视频,考试类型支持考试、练习、问卷。 源码下载 网…

Linux|服务器|简单记录备忘VMware虚拟机开启桌面失败报错:VMware: No 3D enabled (0, Success).的解决

一, VMware虚拟机 Linux操作系统,centos7版本,安装完桌面后,执行startx 命令后 ,报错:VMware: No 3D enabled (0, Success). 桌面没有启动成功 完整日志输出如下: [rootnode4 ~]# startx x…

上传自己的依赖到maven仓库 -- 保姆级复盘

上传自己的依赖到maven仓库 -- 保姆级复盘 1、准备工作1.1、安装Git1.2、将需要上传的代码先上传到Gitee中1.2.1、上传步骤1.2.2、如果出现以下错误(主要原因是gitee中README.md文件和本地不一致,或者不在本地代码目录中) 2、sonatype注册登录…

文件批量重命名:高效整理文件的技巧,随机汉字重命名文件

在数字化时代,每天都要处理大量的文件,无论是文档、图片还是音频、视频。随着时间的推移,文件库可能会变得混乱不堪,难以找到想要的文件,可见文件名有着重要的作用。现在一起来看云炫文件管理器高效的文件整理方法&…

网络调试 TCP,开发板用静态地址-入门7

用两台电脑(无线网络)做实验 1.1, 在电脑A上设置为Server如下: 选择TCP Server后,直接跳出用本机IP做为“本地主机地址” 1.2在 电脑B上设置为Client, 远程主机地址设置为Server的 IP 1.3, 在A, B两台电脑上能够互相发送数据 用…

构建自己的私人GPT

创作不易,请大家多鼓励支持。 在现实生活中,很多人的资料是不愿意公布在互联网上的,但是我们又要使用人工智能的能力帮我们处理文件、做决策、执行命令那怎么办呢?于是我们构建自己或公司的私人GPT变得非常重要。 一、本地部署…

每天一杯羊奶,让身体更健康

每天一杯羊奶,让身体更健康 羊奶作为一种天然的健康饮品,越来越受到人们的关注和喜爱。它不仅口感醇厚,营养丰富,而且具有独特的保健功效。今天,小编羊大师带大家详细介绍一下每天喝一杯羊奶对身体的好处。 羊奶中的…

Python基础知识总结3-面向对象进阶知识

面向对象三大特征介绍 继承子类扩展父类语法格式关于构造函数:类成员的继承和重写查看类的继承层次结构 object根类dir() 查看对象属性重写 __str__() 方法 多重继承MRO方法解析顺序super()获得父类定义多态特殊方法和运算符重载特殊属性 对象的浅拷贝和深拷贝组合_…

如何利用MiniTab的命令行来提高数据建模效率

使用MiniTab进行数据建模时,如果涉及到需要多次更改数据、多次查看模型,感兴趣的同学可以尝试一下,把命令行显示出来,通过命令行的形式来执行,避免在繁多的菜单中到处查找。 操作方式如下图: 点击菜单“查…

junit单元测试:使用@ParameterizedTest 和 @CsvSource注解简化单元测试方法

在平常的开发工作中,我们经常需要写单元测试。比如,我们有一个校验接口,可能会返回多种错误信息。我们可以针对这个接口,写多个单元测试方法,然后将其场景覆盖全。那么,怎么才能写一个测试方法,…