正点原子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并增大堆栈空间。测试结果如图。