打印

FSMC挂IS62WV51216,连续写两个不同地址时出错

[复制链接]
5589|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
daiqh|  楼主 | 2012-5-30 21:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
STM32F103ZET6通过FSMC挂IS62WV51216BLL SRAM。
数据宽度为FSMC_MemoryDataWidth_16b。初始化代码如下:
/*******************************************************************************
* Function Name  : FSMC_SRAM_Init
*******************************************************************************/
void FSMC_SRAM_Init(void)
{
           FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
           FSMC_NORSRAMTimingInitTypeDef  p;
        GPIO_InitTypeDef GPIO_InitStructure;


          /* Enable FSMC, GPIOD, GPIOE, GPIOF, GPIOG and AFIO clocks */
          RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
                              RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG | RCC_APB2Periph_AFIO , ENABLE);

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

          /*-- ----------------------------------- GPIO Configuration -------------------------------------------------*/
          /* SRAM Data lines configuration*/
        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_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);

                /* SRAM Address lines configuration */
        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);

          /* NOE and NWE configuration */
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 |GPIO_Pin_5;
          GPIO_Init(GPIOD, &GPIO_InitStructure);

  
          /* NE3 configuration */
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
          GPIO_Init(GPIOG, &GPIO_InitStructure);
  
          /* NBL0, NBL1 configuration */
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
          GPIO_Init(GPIOE, &GPIO_InitStructure);
  
        /*-- FSMC Configuration ------------------------------------------------------*/
        p.FSMC_AddressSetupTime = 0;                        /*ADDSET  地址建立时间*/
        p.FSMC_AddressHoldTime = 0;                        /*ADDHOLD 地址保持时间*/
        p.FSMC_DataSetupTime = 1;                        /*DATAST 数据建立时间*/
        p.FSMC_BusTurnAroundDuration = 0;                /*BUSTURN 总线返转时间*/
        p.FSMC_CLKDivision = 0;                        /*CLKDIV 时钟分频*/
        p.FSMC_DataLatency = 0;                        /*DATLAT 数据保持时间*/
        p.FSMC_AccessMode = FSMC_AccessMode_A;                       /*ACCMOD FSMC 访问模式*/
        
        /*选择设置的BANK及片选信号*/
        FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;

        /*设置是否数据地址总线分时复用(禁用)*/
        FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;

        /*设置存储器类型*/
        FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
        
        /*设置数据宽度*/
        FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;

        /*设置是否使用突发访问模式(连续读写模式)*/
        FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;

        /*设定是否使用异步等待信号*/
        FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
        
        /*设置WAIT信号的有效电平*/
        FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;

        /*设置是否使用环回模式*/
        FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;

        /*设置WAIT信号有效时机*/
        FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;

        /*设定是否使能写操作*/
        FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;

        /*设定是否使用WAIT信号*/
        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_NORSRAMInit(&FSMC_NORSRAMInitStructure);
        
        /*打开SRAM控制权 */
        FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);
}
--------------------------------------------------------------------------------------------------------------------------------------
现在用以下代码对两不同地址空间进行写操作再串口读出:
#define Bank1_SRAM3_ADDR    ((uint32_t)0x68000000)

#define temp1 (*(vu8 *)(Bank1_SRAM3_ADDR+0x1000))//定义temp1变量
#define temp2 (*(vu8 *)(Bank1_SRAM3_ADDR+0x2000))//定义temp2变量

temp1=0x12;                              //对偏移地址1000写入0x12
USART1_Transmit(temp1 );           //串口读出0x1000地址
temp2=0x34;;                             //对偏移地址2000写入0x34
USART1_Transmit(temp2);            //串口读出0x2000地址
这样串口输出是正确的,为0x12,0x34。但如果以上几条程序换一下位置,如下

temp1=0x12;                              //对偏移地址1000写入0x12
temp2=0x34;;                            //对偏移地址2000写入0x34
USART1_Transmit(temp1);          //串口读出0x1000地址
USART1_Transmit(temp2);          //串口读出0x2000地址
程序是先对两地址进行写操作,再分别输出。但输出两个不同地址里的值都是0x34,
两个地址的偏移量都不一样的,但为什么0x34会写到temp1里面去呢,求高人指点



沙发
aozima| | 2012-5-30 21:51 | 只看该作者
附件用法:
    void mem_test(uint32_t address, uint32_t size )
    mem_test(0x6C00**, 0x200000)

mem_test.zip

732 Bytes

使用特权

评论回复
板凳
aozima| | 2012-5-30 21:53 | 只看该作者
此问题多为硬件问题:
你这个情况地址线短路,虚焊的可能性比较大。
其它常见问题还有:
数据线短路,虚焊。
16位时的高低字节选择短路,虚焊.

使用特权

评论回复
地板
daiqh|  楼主 | 2012-5-30 22:06 | 只看该作者
此问题多为硬件问题:
你这个情况地址线短路,虚焊的可能性比较大。
其它常见问题还有:
数据线短路,虚焊。
16位时的高低字节选择短路,虚焊.
aozima 发表于 2012-5-30 21:53

如果是短路,虚焊的话,那么写--读---写---读的模式也应该会出错啊,

使用特权

评论回复
5
daiqh|  楼主 | 2012-5-30 22:11 | 只看该作者
2# aozima
多谢,附件程序可以用来测试

使用特权

评论回复
6
aozima| | 2012-5-30 22:55 | 只看该作者
楼主应该仔细看一下我的那个测试程序。

如果程序是这样的话。

#define temp1 (*(u8 *)(Bank1_SRAM3_ADDR+0x1000))//定义temp1变量

temp1=0x12;                                        //对偏移地址1000写入0x12
USART1_Transmit(temp1 );        //串口读出0x1000地址
会被编译器优化成:
USART1_Transmit(0x12);
虽然你这里加了v,但还是请查看一下编译出来的指令是否没有偷懒。

然后就是,假设总线上并没有接SRAM,处于悬空状态(当CS线焊焊时也会是这种情况)。
当写-读的操作是连接执行的时候,写出的数据因数据线的电容还被存在数据线上面,
于是被读回来了,所以结果也是对的。
只有向不同的地址写入不同的数据再全读回来对比才能保证。

所以完整的测试应该是像我程序中的一样,可以测出CS,RD,WR,地址线,数据线,字节选择上面的短路,虚焊。
以及地址环回测试。

使用特权

评论回复
7
daiqh|  楼主 | 2012-5-30 23:38 | 只看该作者
6# aozima
嗯,正在测试硬件连接了.多谢你那么详细的指导哦

使用特权

评论回复
8
daiqh|  楼主 | 2012-5-31 15:42 | 只看该作者
6# aozima
果然是CS的问题,内存模块的CS标号居然没和对应的排针对应上。所以这样看来贴中所提到的第一种读出来的数,其实也是错的,aozima大哥分析得也够精辟的,呵。
现在用你所给的代码测试8位读写,
由于SRAM是51216且选择NOR/PSRAM 3,调用程序为mem_test(0x68000000,0x80000);
所以所影射到的地址范围是0x68000000--0x6807FFFF
仿真查看memory如下:

但再查看0x6807FFFF后面的地址居然也写入了数据,且一直写到0x6BFFFFFF为止。

这里就不明白了,为什么超出了范围还会写入数据?
------------------------------------------------------
另外,上面设置的size又觉得是0x100000才对,
因为FSMC中一个地址对应一个8位空间,而51216是一个地址对应该一个16位,所以0x80000要乘2.
不知这样认为对否,因不是很明白数据为8位时而内存为16位的存放形式。

使用特权

评论回复
9
aozima| | 2012-5-31 18:21 | 只看该作者
上面设置的size又觉得是0x100000才对

测试时size使用 0x100008就明白地址环回的作用了。

不是很明白数据为8位时而内存为16位的存放形式

看SRAM上面的”字节选择“

使用特权

评论回复
10
daiqh|  楼主 | 2012-6-4 20:42 | 只看该作者
9# aozima
再次多谢大神的提醒指点,问题都搞清楚了,呵

使用特权

评论回复
11
haitun050505| | 2013-9-17 10:11 | 只看该作者
来学习的

使用特权

评论回复
12
jzmpapa| | 2019-6-4 16:41 | 只看该作者
mem_test.zip下载能解压吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

95

帖子

2

粉丝