中山 网站建设开发,营销团队名字,可以做微信公众号封面的网站,东莞建网站哪家好目录
一、实例的功能
二、工程配置
1、KEYLED
2、时钟、DEBUG、USART6、NVIC、GPIO、CodeGenerator
3、FSMC
#xff08;1#xff09; 模式设置
#xff08;2#xff09; Bank 1子区3参数设置
1) NOR/PSRAM control组#xff0c;子区控制参数
2) NOR/PSRAM timi…目录
一、实例的功能
二、工程配置
1、KEYLED
2、时钟、DEBUG、USART6、NVIC、GPIO、CodeGenerator
3、FSMC
1 模式设置
2 Bank 1子区3参数设置
1) NOR/PSRAM control组子区控制参数
2) NOR/PSRAM timing组读写操作时序参数
3) DMA
三、软件设计
1、KEYLED
2、fsmc.h、fsmc.c
3、main.h
4、main.c
四、下载运行 本文介绍STM32F407单片机以轮询方式读写外部SRAM IS61LV25616AL的方法。继续使用旺宝红龙开发板STM32F407ZGT6 KIT V1.0。 关于 IS61LV25616AL可以详见参考文章1。 参考文章1细说STM32F407单片机FSMC连接外部SRAM的方法及HAL驱动-CSDN博客 https://wenchm.blog.csdn.net/article/details/144930868 参考文章2细说STM32F407单片机轮询方式读写SPI FLASH W25Q16BV_stm32f407 spiflash驱动程序-CSDN博客 https://wenchm.blog.csdn.net/article/details/144587209
一、实例的功能 连接外部SRAM的FSMC接口设置以及轮询方式读写外部SRAM的方法并用HAL函数读写数据和直接用指针读写数据。本示例需要引用参考文章2的KEYLED的4个按键和对应的LED。 本示例还用到RNG在组件面板Security分组里有RNG模块启用RNG即可。RNG需要用到48MHz时钟。
[S2]KeyUp Write by HAL functions LED1 ON
[S3]KeyDown Read by HAL functions LED2 ON
[S4]KeyLeft Write by pointer LED3 ON
[S5]KeyRight Read by pointer LED4 ON
二、工程配置
1、KEYLED 本例的项目中要使用KEYLED其中的keyled.c和keyled.h的使用方法与参考文章1相同。
2、时钟、DEBUG、USART6、NVIC、GPIO、CodeGenerator 外部时钟25MHz设置到HCLK168MHzPCLK142MHzPCLK284MHz其它都设置成168MHz。 DEBUG选择serial wireUSART6、NVIC、CodeGenerator的设置同参考文章1。
3、FSMC 开发板上使用Bank 1子区3连接外部SRAM,所以对NOR Flash/PSRAM/SRAM/ROM/LCD 3进行配置。
1 模式设置
Chip Select设置为NE3也就是使用FSMC_NE3作为SRAM芯片的片选信号。Memory type设置为SRAM。Address设置为19bits因为用到了FSMC_A0至FSMC_A18共19根地址线。Data设置为16bits因为使用了16位数据线。Wait设置为Disable。Wait是PSRAM芯片发给FSMC的等待输入信号本示例电路中IS62WV51216芯片没有这个输出信号。Byte enable需要勾选表示允许字节访问。允许字节访问时将通过芯片的UB和LB信号控制访问高位字节和低位字节。 这样设置后在引脚视图上将自动标出使用的各FSMC引脚。其中FSMC_D0至FSMC_D15是LCD和SRAM共用的16位数据线FSMC_NOE和FSMC_NWE是共用的控制信号线。 FSMC_NE3用于SRAM片选。FSMC_NBL1和FSMC_NBL0是SRAM的高低字节选择信号。 FSMC_A0至FSMC_A18共19根地址线的GPIO引脚分配如下图自动分配的GPIO引脚与实际电路的引脚是一致的所以无须更改。 /** FSMC GPIO ConfigurationPF0 ------ FSMC_A0PF1 ------ FSMC_A1PF2 ------ FSMC_A2PF3 ------ FSMC_A3PF4 ------ FSMC_A4PF5 ------ FSMC_A5PF12 ------ FSMC_A6PF13 ------ FSMC_A7PF14 ------ FSMC_A8PF15 ------ FSMC_A9PG0 ------ FSMC_A10PG1 ------ FSMC_A11PE7 ------ FSMC_D4PE8 ------ FSMC_D5PE9 ------ FSMC_D6PE10 ------ FSMC_D7PE11 ------ FSMC_D8PE12 ------ FSMC_D9PE13 ------ FSMC_D10PE14 ------ FSMC_D11PE15 ------ FSMC_D12PD8 ------ FSMC_D13PD9 ------ FSMC_D14PD10 ------ FSMC_D15PD11 ------ FSMC_A16PD12 ------ FSMC_A17PD13 ------ FSMC_A18PD14 ------ FSMC_D0PD15 ------ FSMC_D1PG2 ------ FSMC_A12PG3 ------ FSMC_A13PG4 ------ FSMC_A14PG5 ------ FSMC_A15PD0 ------ FSMC_D2PD1 ------ FSMC_D3PD4 ------ FSMC_NOEPD5 ------ FSMC_NWEPG10 ------ FSMC_NE3PE0 ------ FSMC_NBL0PE1 ------ FSMC_NBL1*//* GPIO_InitStruct */
2 Bank 1子区3参数设置 在模式设置中启用Bank 1子区3之后在参数设置部分会出现NOR/PSRAM3参数设置页面在这个页面设置SRAM的控制和时序参数。
1) NOR/PSRAM control组子区控制参数
Memory type只能选择SRAM因为在模式配置部分已设置为SRAM。Bank只能选择为Bank 1 NOR/PSRAM3,是与模式设置部分对应的。Write operation设置为Enabled,表示允许写操作。Extended mode设置为Disabled。FSMC自动使用模式A对SRAM进行操作。SRAM的读操作和写操作的速度基本相同所以读写操作可以使用相同的时序参数无须使用扩展模式单独设置读时序和写时序。
2) NOR/PSRAM timing组读写操作时序参数
Address setup time in HCLK clock cycles即地址建立时间参数ADDSET设置范围为015设置为0即可。Data setup time in HCLK clock cycles即数据建立时间参数DATAST设置范围为1~255设置为8。Bus turn around time in HCLK clock cycles总线翻转时间设置范围为015设置为0即可。
3) DMA FSMC参数设置部分没有DMA设置页面但是SRAM的HAL驱动程序中有DMA方式进行数据读写的函数其DMA方式的设置与其他外设稍有不同的。
三、软件设计
1、KEYLED 本例的项目中要使用KEYLED其中的keyled.c和keyled.h的使用方法与参考文章1相同。
2、fsmc.h、fsmc.c IDE自动生成。
3、main.h
/* USER CODE BEGIN Private defines */
void SRAM_WriteByFunc();
void SRAM_ReadByFunc();
void SRAM_WriteByPointer();
void SRAM_ReadByPointer();
/* USER CODE END Private defines */
4、main.c
/* USER CODE BEGIN Includes */
#include keyled.h
#include stdio.h
/* USER CODE END Includes */
/* USER CODE BEGIN PD */
// SRAM的容量不同该处的定义就不同,更改SRAM就得修改此处的定义
#define SRAM_ADDR_BEGIN 0x68000000UL //Bank1子区3的SRAM起始地址
#define SRAM_ADDR_HALF 0x6801FFFFUL //SRAM容量256K*16bit中间地址128K字节
#define SRAM_ADDR_END 0x6803FFFFUL //SRAM容量256K*16bit结束地址512K字节
//#define SRAM_ADDR_HALF 0x68080000UL //SRAM容量512K*16bit中间地址512K字节
//#define SRAM_ADDR_END 0x680FFFFFUL //SRAM容量512K*16bit结束地址1024K字节
/* USER CODE END PD */
/* USER CODE BEGIN 2 */printf(Demo19_1_FSMC: External SRAM\r\n);printf(Read/Write SRAM by polling\r\n);//显示菜单printf([S2]KeyUp Write by HAL functions.\r\n);printf([S3]KeyDown Read by HAL functions.\r\n);printf([S4]KeyLeft Write by pointer.\r\n);printf([S5]KeyRight Read by pointer.\r\n);// MCU output low level LED light is onLED1_OFF();LED2_OFF();LED3_OFF();LED4_OFF();/* USER CODE END 2 */
/* USER CODE BEGIN 3 */KEYS curKeyScanPressedKey(KEY_WAIT_ALWAYS);switch(curKey){case KEY_UP:{SRAM_WriteByFunc(); //Write by HAL functionsLED1_ON();LED2_OFF();LED3_OFF();LED4_OFF();}break;case KEY_DOWN:{SRAM_ReadByFunc(); //Read by HAL functionsLED1_OFF();LED2_ON();LED3_OFF();LED4_OFF();}break;case KEY_LEFT:{SRAM_WriteByPointer(); //Write by pointerLED1_OFF();LED2_OFF();LED3_ON();LED4_OFF();break;}case KEY_RIGHT:{SRAM_ReadByPointer(); //Read by pointerLED1_OFF();LED2_OFF();LED3_OFF();LED4_ON();}default:{LED1_OFF();LED2_OFF();LED3_OFF();LED4_OFF();}}printf(** Reselect menu or reset **\r\n);HAL_Delay(500); //延时消除按键抖动}/* USER CODE END 3 */
/* USER CODE BEGIN 4 */
/* 用HAL函数写入数据 */
void SRAM_WriteByFunc()
{
//1. 写入字符串uint32_t *pAddr (uint32_t *)(SRAM_ADDR_BEGIN); //给指针赋值uint8_t strIn[] Test FSMC;uint16_t dataLen sizeof(strIn); //数据长度字节数包括最后的结束符\0if (HAL_SRAM_Write_8b(hsram3,pAddr,strIn,dataLen) HAL_OK){printf(Write string at %p %s\r\n,pAddr,strIn);}//2. 写入1个随机数uint32_t num 0;pAddr(uint32_t *)(SRAM_ADDR_BEGIN256); //指针重新赋值HAL_RNG_GenerateRandomNumber(hrng, num); //产生32位随机数if (HAL_SRAM_Write_32b(hsram3, pAddr, num, 1) HAL_OK){printf(Write 32b number at %p %lx\r\n,pAddr,num);//十六进制显示,显示前缀0x}
}/* 用HAL函数读取数据 */
void SRAM_ReadByFunc()
{
//1. 读取字符串uint32_t *pAddr (uint32_t *)(SRAM_ADDR_BEGIN); //给指针赋值uint8_t strOut[30];uint16_t dataLen 30;if (HAL_SRAM_Read_8b(hsram3,pAddr,strOut,dataLen) HAL_OK){printf(Read string at %p %s\r\n,pAddr,strOut);//显示自动以\0结束}//2. 读取1个uint32_t类型的数uint32_t num 0;pAddr(uint32_t *)(SRAM_ADDR_BEGIN256); //指针重新赋值指向1个新的地址if (HAL_SRAM_Read_32b(hsram3, pAddr, num, 1) HAL_OK){printf(Read 32b number at %p %lx\r\n,pAddr,num);}
}/* 直接通过指针写数据 */
void SRAM_WriteByPointer()
{printf(Write five uint16_t numbers.\r\n);printf(start from 0x6801 FFFF.\r\n);uint16_t num 100;uint16_t *pAddr_16b (uint16_t *)(SRAM_ADDR_HALF); //uint16_t 类型数据指针for(uint8_t i0;i5;i) //连续写入5个16位整数{num 3;*pAddr_16b num; //直接向指针所指的地址写入数据pAddr_16b ; //1次地址2, 因为是uint16_t类型printf(The data of Add %p %d\r\n,pAddr_16b,num);}
}/* 直接通过指针读取数据 */
void SRAM_ReadByPointer()
{printf(Read five uint16_t numbers.\r\n);printf(start from 0x6801 FFFF.\r\n);uint16_t num 0;uint16_t *pAddr_16b (uint16_t *)(SRAM_ADDR_HALF); //uint16_t 类型数据指针for(uint8_t i0; i5; i){num *pAddr_16b; //直接从指针所指的地址读数pAddr_16b ; //1次地址2, 因为是uint16_t类型printf(The data of Add %p %d\r\n,pAddr_16b,num);}
}//串口打印
int __io_putchar(int ch)
{HAL_UART_Transmit(huart6,(uint8_t*)ch,1,0xFFFF);return ch;
}
/* USER CODE END 4 */ 使用HAL函数读写外部SRAM的数据就是使用参考文章2中的函数读写SRAM的数据。给这些函数传递的SRAM目标地址必须是uint32_t类型指针如下所示
uint32_t *pAddr (uint32_t*)(SRAM_ADDR_BEGIN); //给指针赋值
pAddr (uint32_t*)(SRAM_ADDR_BEGIN256); //指针重新赋值指向新的地址 而在使用指针直接访问SRAM时指针类型需要与实际访问的数据类型一致例如访问的数据是uint16_t类型就应该定义如下的指针
uint16_t *pAddr_16b (uint16_t*)(SRAM_ADDR_HALE); //uint16_t类型数据指针
四、下载运行 测试过程中发现一个有趣的现象当num的值增加到超过1024以后num值会被置0余数仍然有效比如某一时刻num10233新的num2。然后从2开始自增下去直到再次超过1024。这可能是一个BUG也可能是哪一处设置的不对请感兴趣的网友把解决办法贴上来。 还发现一个BUG写进SRAM的数据再次读出来不一定一样。