正点原子F429开发板使用STM32CubeMX驱动板载SDRAM 发现最近随便转载的很多啊,未经授权禁止转载!抄袭!!否则转载者死全家!!另外这是我的笔记,不是教程,难免会有错误,不具有很高的参考性,望周知。
由于我需要使用到SDRAM作为显存来使用,使用内部的SRAM空间作为显存显然不是明智的,因为屏幕的像素点很多,这样将会占用大量的内存,导致无法运行其他的东西。
STM32CubeMX配置工程 废话不多说,首先打开STM32CubeMX,找到FMC选项,对其进行设置。这里的参数不是随便设置的,需要根据SDRAM芯片的参数进行设置。
这部分是时序相关的参数,根据SDRAM芯片手册并计算进行确定。
为了测试SDRAM是否正常工作,这里打开USART1,使用串口对SDRAM的读写进行测试。
这里只用到了串口发送部分,因此不需要进行其他设置。
使用Keil修改代码 增加SDRAM命令函数 参考正点原子例程代码,在fmc.c文件中添加如下代码,具体参数计算已在注释中说明。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #define Bank5_SDRAM_ADDR ((uint32_t)(0XC0000000)) #define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) #define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) #define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004) #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) #define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) #define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) #define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) uint8_t SDRAM_Send_Cmd (SDRAM_HandleTypeDef *SDRAM_Handler, uint8_t bankx,uint8_t cmd,uint8_t refresh,uint16_t regval) { uint32_t target_bank=0 ; FMC_SDRAM_CommandTypeDef Command; if (bankx==0 ) target_bank=FMC_SDRAM_CMD_TARGET_BANK1; else if (bankx==1 ) target_bank=FMC_SDRAM_CMD_TARGET_BANK2; Command.CommandMode=cmd; Command.CommandTarget=target_bank; Command.AutoRefreshNumber=refresh; Command.ModeRegisterDefinition=regval; if (HAL_SDRAM_SendCommand(SDRAM_Handler,&Command,0X1000 )==HAL_OK) { return 0 ; } else return 1 ; }void SDRAM_Initialization_Sequence (SDRAM_HandleTypeDef *SDRAM_Handler) { uint32_t temp=0 ; SDRAM_Send_Cmd(SDRAM_Handler, 0 ,FMC_SDRAM_CMD_CLK_ENABLE,1 ,0 ); HAL_Delay(1 ); SDRAM_Send_Cmd(SDRAM_Handler, 0 ,FMC_SDRAM_CMD_PALL,1 ,0 ); SDRAM_Send_Cmd(SDRAM_Handler, 0 ,FMC_SDRAM_CMD_AUTOREFRESH_MODE,8 ,0 ); temp=(uint32_t )SDRAM_MODEREG_BURST_LENGTH_1 | SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | SDRAM_MODEREG_CAS_LATENCY_3 | SDRAM_MODEREG_OPERATING_MODE_STANDARD | SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; SDRAM_Send_Cmd(SDRAM_Handler, 0 ,FMC_SDRAM_CMD_LOAD_MODE,1 ,temp); HAL_SDRAM_ProgramRefreshRate(SDRAM_Handler,683 ); }
接着,在MX_FMC_Init函数中,添加如下代码,在FMC外设初始化完成后,发送SDRAM初始化序列,对SDRAM进行初始化。
1 2 3 SDRAM_Initialization_Sequence(&hsdram1);
进行SDRAM读写测试 在main.c文件中,添加对串口Handle的外部声明:
1 2 3 extern UART_HandleTypeDef huart1;
在main函数的while循环中,添加测试代码:
1 2 3 4 5 6 7 8 9 10 11 while (1 ) {sprintf ((__IO uint8_t *) (0XC0000000 ), "SDRAM test success!\r\n" ); HAL_UART_Transmit(&huart1, (__IO uint8_t *) (0XC0000000 ), 21 , 0xff ); }
如果SDRAM功能正常,打开串口调试助手,能够看到不断有字符串输出,表明SDRAM已经能够正常使用了。
测试SDRAM的空间大小 正点原子提供了一个简单测试SDRAM空间大小的函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void fsmc_sdram_test () { uint32_t i=0 ; uint32_t temp=0 ; uint32_t sval=0 ; for (i=0 ;i<32 *1024 *1024 ;i+=16 *1024 ) { *(__IO uint32_t *)(0xc0000000 +i)=temp; temp++; } for (i=0 ;i<32 *1024 *1024 ;i+=16 *1024 ) { temp=*(__IO uint32_t *)(0xc0000000 +i); if (i==0 )sval=temp; else if (temp<=sval)break ; printf ("SDRAM Capacity:%dKB\r\n" ,(uint16_t )(temp-sval+1 )*16 ); } }
该函数利用不断向SDRAM内写入递增的值,并依次读取写入过的值,判断后面的数据是否比前一次读取的大,并通过printf函数输出当前测试的SDRAM的大小。使用printf函数注意需要在工程选项中勾选USE MicroLIB
并增大堆栈空间。测试结果如图。