一、FSMC

FSMC为灵活的静态内存控制,FSMC模块能够与同步或异步存储器和16位PC存储器卡接口,它的主要作用是:

  • 将AHB传输信号转换到适当的外部设备协议
  • 满足访问外部设备的时序要求

FSMC连接的外部存储器可以是:静态存储器、NAND闪存、PC卡。其中静态存储区包括:SRAM、NOR闪存和PSARM。

1、FSMC框图:

在这里插入图片描述

2、外部设备地址映像

从FSMC的角度看,可以把外部存储器划分为固定大小为256M字节的四个存储块,见下图。

  • 存储块1用于访问最多4个NOR闪存或PSRAM存储设备。这个存储区被划分为4个NOR/PSRAM区并有4个专用的片选。
  • 存储块2和3用于访问NAND闪存设备,每个存储块连接一个NAND闪存。
  • 存储块4用于访问PC卡设备
    在这里插入图片描述

3、NOR和PSRAM地址映像

  • HADDR[27:26]位用于选择四个存储块之一:
    在这里插入图片描述
  • HADDR是需要转换盗版外部存储器的内部AHB地址线
  • HADDR[27:0]包含内部存储块区分HADDR[27:26] 和 外部存储器地址HADDR[25:0]。其中HADDR是字节地址,而存储器访问不一定都是字节访问,这个还受到连接到外部存储器的数据宽度决定,如下表所示:
    在这里插入图片描述
    **注意:**对于16位宽度的外部存储器,在内部的HADDR[25:1]将产生外部存储器的地址FSMC_A[24:0]。且不论外部存储器的宽度是16位还是8位,FSMC_A[0]始终应该连到外部存储器的地址线A[0]。

本节只学习FSMC的存储块1关于SRAM的部分内容。

二、FSMC与SRAM传输

#include "stm32f10x.h"
#include <stdio.h>

// 定义SRAM的起始地址,使用FSMC Bank1
#define SRAM_BANK_ADDR    ((uint32_t)0x68000000)

// FSMC初始化函数
void FSMC_SRAM_Init(void)
{
    FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
    FSMC_NORSRAMTimingInitTypeDef  p;
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能FSMC和GPIO时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG, ENABLE);

    // 配置FSMC相关的GPIO引脚 - 数据线(D0 - D15)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = 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);

    // 配置FSMC相关的GPIO引脚 - 地址线(A0 - A18)
    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_Init(GPIOG, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 ;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
	

    // 配置FSMC相关的GPIO引脚 - 控制信号
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 ;// OE,WE
    GPIO_Init(GPIOD, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10;// NE3 片选
    GPIO_Init(GPIOG, &GPIO_InitStructure);

 

    // 配置FSMC时序,根据IS62WV51216BLL-55TLI数据手册调整
    p.FSMC_AddressSetupTime = 0x01;	 //地址建立时间(ADDSET)为2个HCLK 1/72M=27.6ns
    p.FSMC_DataSetupTime = 0x02;		 //数据保持时间(DATAST)为3个HCLK 3/72M=41.4ns
	p.FSMC_AccessMode = FSMC_AccessMode_A;	 //模式A 
		//不需要配置的成员变量
    p.FSMC_BusTurnAroundDuration = 0x00;
	p.FSMC_AddressHoldTime = 0x00;	 //地址保持时间(ADDHLD)模式A未用到	
    p.FSMC_CLKDivision = 0x00;
    p.FSMC_DataLatency = 0x00;
 

    // 配置FSMC NOR/SRAM初始化结构体
   FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;//  这里我们使用NE3 ,也就对应BTCR[4],[5]。
    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; 
    FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;// FSMC_MemoryType_SRAM;  //SRAM   
    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;//存储器数据宽度为16bit  
    FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;// 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_WriteOperation = FSMC_WriteOperation_Enable;	//存储器写使能 
    FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;  
    FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; // 读写使用相同的时序
    FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; 
 
    FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
    FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;

    // 初始化FSMC Bank3
    FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);

    // 使能FSMC Bank3
    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);
}

// 向SRAM写入一个半字(16位)数据
void SRAM_WriteHalfWord(uint32_t WriteAddr, uint16_t Data)
{
    *(uint16_t *)(SRAM_BANK_ADDR + WriteAddr) = Data;
}

// 从SRAM读取一个半字(16位)数据
uint16_t SRAM_ReadHalfWord(uint32_t ReadAddr)
{
	uint32_t  p =(SRAM_BANK_ADDR + ReadAddr);
	uint16_t data=*(uint16_t *)p;
	 printf("address=%x,data=%x \n",p,data );
    return data;
}

 
// 向SRAM写入数组数据
void SRAM_WriteBuffer(uint32_t WriteAddr, uint16_t *pBuffer, uint32_t NumHalfwordToWrite)
{
    for (uint32_t i = 0; i < NumHalfwordToWrite; i++)
    {
        SRAM_WriteHalfWord(WriteAddr, pBuffer[i]);
        WriteAddr += 2;
    }
}

// 从SRAM读取数组数据
void SRAM_ReadBuffer(uint32_t ReadAddr, uint16_t *pBuffer, uint32_t NumHalfwordToRead)
{
    for (uint32_t i = 0; i < NumHalfwordToRead; i++)
    {
        pBuffer[i] = SRAM_ReadHalfWord(ReadAddr);
		// printf("%x ", pBuffer[i] );
        ReadAddr += 2;
    }
}

void USART_Configure(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStruct);
    //USART配置
    USART_InitTypeDef USART_InitStruct;
    USART_InitStruct.USART_BaudRate=115200;   		
    USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Mode = USART_Mode_Tx;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_Init(USART1,&USART_InitStruct);

    USART_Cmd(USART1,ENABLE);
}

void USART_SendChar(uint16_t ch){
    while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET){
    }
    USART_SendData(USART1,ch);
}

int fputc(int ch, FILE* file)
{
    USART_SendChar((uint16_t)ch);
    return ch;
}

int main(void)
{
    uint16_t writeData = 0x0010;
    uint16_t readData;
    uint16_t bufferWrite[5] = {0x1111, 0x2222, 0x3333, 0x4444, 0x5555};
    uint16_t bufferRead[5];

    USART_Configure();
    printf("USART_Init succeed!\n");

    // 初始化FSMC和SRAM
    FSMC_SRAM_Init();
    printf("FSMC_SRAM_Init succeed!\n");

    // 写入一个 半字 数据并读取验证
    SRAM_WriteHalfWord(0, writeData);
    printf("Wrote data: 0x%04x to address 0x%08x\n", writeData, SRAM_BANK_ADDR);
    readData = SRAM_ReadHalfWord(0);
    printf("Read data: 0x%04x from address 0x%08x\n", readData, SRAM_BANK_ADDR);

    // 写入数组数据并读取验证
    SRAM_WriteBuffer(0, bufferWrite, 5);
    SRAM_ReadBuffer(0, bufferRead, 5);
    for (int i = 0; i < 5; i++)
    {
        if (bufferRead[i] != bufferWrite[i])
        {
// printf("write and read buffer failed at index %d\n", i);
        }
		 printf("%x ", bufferRead[i] );
    }

    while (1)
    {
        // 主循环可添加其他任务
    }
}

在这里插入图片描述

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐