打印
[ZLG-ARM]

关于SST25VF080B的SPI通讯问题

[复制链接]
6824|28
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yld|  楼主 | 2012-2-24 21:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大家好!有做过SST25VF系列的SPI通讯吗?我用模拟总线和SPI硬件都试验了,读ID返回的数据还是和手册上的不符合,读ID(0) 应该要返回0xfb 读ID(1)应该返回0x8e    而且继续读下去,两者数据会交替出现。我的问题是:不管模拟还是硬件SPI总线,SST25VF080B绝对是有反应的,具体来讲,就是读ID(命令码是:0x90或者0xab都一样的),地址是0时,返回0xfb(貌似已经对了,和手册符合);地址是1,返回0x8c,这个不对,这个应该是SST25VF020B的地址。更加不对的是:继续读下去,交替出现的数据是非常有规律的:以地址0为例,一直读下去,出现的数据循环为:0xBF,[0X19,0XF8,0XCF,0XC6,0X7E,0X33,0XF1,0X9F,0X8C,0XFC,0X67,0XE3,0X3F,
[0X19,0XF8,0XCF,0XC6,0X7E,.......................................................0X3F]
就是这样的数据,从数据来分析,整个数据链似乎慢慢在移位,这个和SPI的数据移位似乎有关联?
我查找了好多资料,从SST官方的C51驱动,到众多网友的提供的宝贵的资料,用LPC2131,LPC2478,模拟,硬件SPI,全部试过了,还是不行。
SST25VF080B有一个特点,就是上升沿打进数据,下降沿输出数据,故在打完最后一位后,若CLK置0,则首位数据已经输出了,这点也已经注意到了。
恳请熟悉这款flash的网友帮忙,看我哪里疏忽了?我咨询了芯片销售商,他说保证是原装进口的,我无语了。哪怕有SST25VF080B的开发板,我买一块也可以啊!真是焦虑!SOS!

相关帖子

沙发
yld|  楼主 | 2012-2-24 21:47 | 只看该作者
另外,擦除操作也做过,只要擦出了,读出的数据必定=0xff,但是写进数据就不对了,大多数情况下写入的和读出的数据都不一致的,但是可以肯定,数据时写入了,因为读出的数据应经不为0xff了。状态寄存器也是可以清零的,上电复位后,读状态寄存器是0x18.------这是我可以提供的线索。请大侠们指教了。

使用特权

评论回复
板凳
aozima| | 2012-2-25 00:34 | 只看该作者
先读ID,ID不对说明时序没正确。然后就不必然后了。
SST25XX支持SPI模式0和模式3,一般用模式0(绝大部分器件使用模式0).

使用特权

评论回复
地板
yld|  楼主 | 2012-2-25 08:03 | 只看该作者
恩,非常感谢!那么晚了,还有兄弟没休息,顶我的贴!我再去查一下时序!

使用特权

评论回复
5
playlinus| | 2012-2-25 10:51 | 只看该作者
从以上SST25VF080B的DATASHEET读ID的时序看,写入90指令后,紧接着是地址 00 00 ADD1,接着SST25VF080B返回的就是Manufacturer`s ID 和 Device ID , DX32中关于读ID的那段程序如下.

u16 SST25ReadID(void)
{
    u8 id[3];
    u8 addr[3]={0,0,0};
   
    SSTCmd4bs(0x90,addr,id,3);
    return((id[0]<<8)+id[1]);
}

void SSTCmd4bs(u8 cmd,u8* addr,u8* data,u32 no)
{
    SST_SELECT();
    SPIByte(cmd);    //首命令
    SPIByte(*addr++);
    SPIByte(*addr++);
    SPIByte(*addr);
    for(;no>0;no--)
    {
        *data++=SPIByte(0xff);
    }
    SST_DESELECT();
}

可以看到, DX32程序中送完 0x90 指令后紧接着是addr[3]的3个元素 0 0 0 , SST25VF080B manufacturer`s ID地址为00000H, 而Device ID为 00001H , 我们写入地址是0 , 是否这里就用到了SST25VF080B所谓的AAI (auto address incresment)功能, 读出Manufacturer`s ID后地址自动增加到 00001H ,从而返回SSTVF080B的Device ID  ?

请赐教,以上理解是否正确,谢谢.

使用特权

评论回复
6
playlinus| | 2012-2-25 10:51 | 只看该作者
我也正为此事烦恼

使用特权

评论回复
7
yld|  楼主 | 2012-2-25 11:07 | 只看该作者
我时序都检查过了,还是一样不行。6楼的兄弟,你调试得到什么结果了?我读ID(0),返回0xfb;读ID(1)返回0x8c.但是不会交替出现,而是想1楼说的那样的。还请做过的兄弟不吝赐教啊!

使用特权

评论回复
8
yld|  楼主 | 2012-2-25 11:09 | 只看该作者
本帖最后由 yld 于 2012-2-25 11:39 编辑

读ID(0)返回0xbf,貌似对了;但是读ID(1),返回0x8c,就不对了.
手册上讲读ID(0)是会交替出现:0xbf,0x8e,0xbf,0x8e,.......直到SSE置高。
实际交替出现的数据是不对的。

使用特权

评论回复
9
yld|  楼主 | 2012-2-25 11:11 | 只看该作者
本帖最后由 yld 于 2012-2-25 11:12 编辑

模式0和模式3都试过了,一样的结果的。当然,模式0和模式3的编程,是有区别的。这个也注意到了。

使用特权

评论回复
10
yh810912| | 2012-2-25 11:14 | 只看该作者

使用特权

评论回复
11
ocon| | 2012-2-25 11:19 | 只看该作者
可以确定是时序不正确,请重点确认你的SPI空闲状态电平是否符合SST25VF020B的需求。

使用特权

评论回复
12
yld|  楼主 | 2012-2-25 11:43 | 只看该作者
本帖最后由 yld 于 2012-2-25 11:48 编辑

我把调试过的最简单的读ID的程序贴上来,还望得到大家的帮助!我开开发板用的是ZLG的 LPC2131开发板
程序如下:
/****************************************Copyright (c)****************************************************
**                               Guangzou ZLG-MCU Development Co.,LTD.
**                                      graduate school
**                                 http://www.zlgmcu.com
**
*******************************************************/

#include          "config.h"

#define      SPI_CS                  (1 << 29)

#define     CE_Low()                (IO0CLR |=  SPI_CS)

#define     CE_High()                (IO0SET |=  SPI_CS)                        

#define SPI_CK_L     IO0CLR |= (1<<4)/* set clock to low initial state for SPI operation mode 0 */

#define SPI_CK_H     IO0SET |= (1<<4)/* set clock to low initial state for SPI operation mode 0 */

#define SPI_DI_L      IO0CLR |= (1<<6)

#define SPI_DI_H      IO0SET |= (1<<6)

#define ReadIO         (IO0PIN&(1<<5))
   

void init(void);
void Send_Byte(unsigned char out);
unsigned char Get_Byte(void);

unsigned char Read_ID(uint8 ID_addr);

void  Delay(uint32  dly)
{  
    uint32  i = 0;
    for (; dly > 0; dly--) {
        for (i = 0; i < 5000; i++);
    }
}


void init(void)
{
        PINSEL0  =        0;               
        PINSEL1  =        0;        
        IO0DIR         |=  SPI_CS;               
        IO0DIR  &=  (~(1<<5));
        IO0DIR  |=  ((1<<4)|(1<<6)|(1<<29));
        SPI_CK_L;//MOD=0
    CE_High();               
}

void Send_Byte(unsigned char out)//SPI MOD=0
{
        unsigned char i = 0;
    SPI_CK_L;                                /* toggle clock low */
        for (i = 0; i < 8; i++)
        {
                if ((out & 0x80) == 0x80)        /* check if MSB is high */
                        SPI_DI_H;
                else
                        SPI_DI_L;                                /* if not, set to low */
            Delay(10);               
                SPI_CK_H;                                /* toggle clock high */
                out = (out << 1);                /* shift 1 place for next bit */
                Delay(10);        
                SPI_CK_L;                                /* toggle clock low */
        }
}


unsigned char Get_Byte(void)//SPI MOD=0
{
        unsigned char i = 0, in = 0;
        uint32 temp = 0;
        SPI_CK_L;
        for (i = 0; i < 8; i++)
        {
            in   =  (in << 1);
                temp =  ReadIO;
                if(temp)
                  {
                    in  =  (in|0x01);
              }                    
                SPI_CK_H;
                Delay(10);
                SPI_CK_L;
                Delay(10);
        }
        Delay(20);        
        return in;
}
/*
unsigned char Get_Byte(void)//SPI MOD=0
{//这种读的方式--得到的结果和上面一样
//表明SST25VF080B确实是在CLK的下降沿输出数据-->
//-->然后保持-->
//-->直到下一个CLK的下降沿来临才更新输出-->
//-->所以上升沿之前读 和 上升沿之后读 是没有区别的
        unsigned char i = 0, in = 0;
        uint32 temp = 0;
        SPI_CK_L;
        for (i = 0; i < 8; i++)
        {
            in   =  (in << 1);
                SPI_CK_H;
                Delay(10);
                temp =  ReadIO;
                if(temp)
                  {
                    in  =  (in|0x01);
              }                        
                SPI_CK_L;
                Delay(10);
        }
        Delay(20);        
        return in;
}
*/

unsigned char Read_ID(uint8 ID_addr)
{
        unsigned char byte;
        CE_Low();                        /* enable device */
        Send_Byte(0x90);            /* send read ID command (90h or ABh) */
    Send_Byte(0x00);                /* send address */
        Send_Byte(0x00);            /* send address */
        Send_Byte(ID_addr);        /* send address - either 00H or 01H */
        byte = Get_Byte();
        CE_High();                       /* disable device */
        return byte;
}


int main(void)
{
uint8  byte;

init();

byte = Read_ID(1);//Read_ID(0)返回0xbf;Read_ID(1)返回0x8c

if(byte==0xbf)//防止byte被编译器优化
   {
     Delay(1);
   }
while(1);
return 0;
}

使用特权

评论回复
13
yld|  楼主 | 2012-2-25 11:53 | 只看该作者
非常感谢11楼OCON兄弟的提醒,我再查一下,我觉得也可能是时序,但是还没有查到。

使用特权

评论回复
14
yld|  楼主 | 2012-2-25 12:19 | 只看该作者
我用模拟SPI总线的方法,就是为了更好的调试和理解的。

使用特权

评论回复
15
aozima| | 2012-2-25 13:04 | 只看该作者
搭个逻辑分析仪吧。

使用特权

评论回复
16
yld|  楼主 | 2012-2-25 13:11 | 只看该作者
呵呵,这个不会,也没有,泰克300MHZ 数字存储示波器到有一台,可以双踪!

使用特权

评论回复
17
aozima| | 2012-2-25 13:24 | 只看该作者

SPI_CK_H;
Delay(10);
//应该在这里读。
SPI_CK_L;
Delay(10);

使用特权

评论回复
18
lzm_lzm1| | 2012-2-25 13:27 | 只看该作者
2# yld fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

使用特权

评论回复
19
yld|  楼主 | 2012-2-25 13:33 | 只看该作者
TO:aozima兄!  你的方法我在程序里面是有的,就是被我注释掉的那个程序,这两种方法我都试过的,效果一样,我还特地作了说明,谢谢!

使用特权

评论回复
20
aozima| | 2012-2-25 14:25 | 只看该作者
SPI收发是一起的, 接收时,数据输出也不可以随意,一般为1.

一般IO模拟SPI,收发都是同一个函数。
接收时,发送dummy(0xFF)

使用特权

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

本版积分规则

yld

6

主题

36

帖子

0

粉丝