This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

msp430F5438 spi与铁电存储器FM25H20

F5438的spi与FM25H20通信,现在读取FM25H20的状态寄存器返回的也是0xff,给FM25H20的任一地址写数据,然后再读该地址的数据,返回的也是0xFF,不论什么操作,FM25返回的都是0xff。不知道出了什么问题。。。

#include "msp430x54x.h" #include <stdlib.h> #include <stdio.h> #include <string.h>

#define WREN_CMD 0x06    //允许写操作 

#define WRDI_CMD 0x04    //禁止写

 #define RDSR_CMD 0x05    //读状态寄存器

 #define WRSR_CMD 0x01    //写状态寄存器

#define READ_CMD 0x03    //读存储器数据

#define WRITE_CMD 0x02   //写存储器数据

#define SLEEP_CMD 0xB9  //进入睡眠模式

#define DUMY_CMD  0      //产生读时序

 

unsigned char FmTxData=0x55;

unsigned char FmRxData;

unsigned char temp;

 unsigned char temp1;

unsigned char rxdata;

void  WrMemData(long int addr, unsigned char c);

unsigned char RdMemData(long int addr);

 unsigned char RdMemStatReg();

 

 

void Init_SPI1(void)

{      P3SEL |=0x80;                       //P3.7功能选择为SPI1,--SIMO    

P3SEL &=0xBF;                       //p3.6端口模式    

P5SEL |=0x30;                       //P5.4/5功能选择为SPI1,---SOMI,CLK        

P3DIR  |= 0x40;                    //P3.6输出,控制FM片选信号    

P4DIR  |= 0x03;               //p4.0/1输出,控制wp和hold        

P3DIR |=0x80;   // SIMO output    

P5DIR &=0xEF;    // SOMI input    

P5DIR |=0x20;     //CLK output                

P3OUT  |= 0x40;     //CS is high    

P4OUT  |= 0x03;     // wp and hold are high                

UCB1CTL1 |= UCSWRST;             // 复位SPI1状态机        

UCB1CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB ; // 3-pin, 8位, SPI master, Clock polarity high, MSB    

UCB1CTL1 |= UCSSEL_2  ;                        // 选择SCK参考源为SMCLK    

UCB1BR0   = 0x02  ;                            // SCK = SMCLK/2    

UCB1BR1   = 0 ;   

 //UCA0MCTL = 0;        

UCB1CTL1 &=~UCSWRST ;               // SPI1状态机使能

}

 

unsigned char TransceiveSPI1 (unsigned char txdata)   {       while (!(UCB1IFG & UCTXIFG));             // wait until last SPI-Transmission is finished       UCB1TXBUF = txdata;                         // send 8 clocks "txdata" and SPI-clocks       while (!(UCB1IFG & UCRXIFG));           // wait until one byte is received       rxdata = UCB1RXBUF;         return rxdata;   }

 

/*char RxTxSPI1(unsigned char c)   //发送接收程序 { //////   while (!(UCB1IFG&UCTXIFG));           // USCI_B1 TX buffer ready? //   SPI1Rxflg=0;    UCB1TXBUF=c;    while(!SPI1Rxflg);    SPI1Rxflg=0;    return UCB1RXBUF; }    TxSPI1(char c)   //发送程序 {    UCB1TXBUF=c; } char RxSPI1()    //接收程序 {     char temp;     temp= UCB1RXBUF;     return temp; }  */

void MemEnable()       //发送器件写操作命令 {   P3OUT &=~BIT6;   TransceiveSPI1(WREN_CMD);   P3OUT |=BIT6; }

void MemDisable()      //发送器件写器件禁止 {   P3OUT &=~BIT6;   TransceiveSPI1(WRDI_CMD);  // if(TxFlg==1)   P3OUT |=BIT6;

}

void WrMemStatReg(unsigned char c)//写状态寄存器 {   MemEnable();   P3OUT &=~BIT6;  // TxFlg=0;   TransceiveSPI1(WRSR_CMD);

  TransceiveSPI1(c);    P3OUT |=BIT6; }

unsigned char RdMemStatReg()//读寄存器 { //  unsigned char temp;   P3OUT &=~BIT6;   TransceiveSPI1(RDSR_CMD);   temp1=TransceiveSPI1(DUMY_CMD); //  =RxSPI1();   P3OUT |=BIT6;   return temp1; }

void  WrMemData(long int  addr, unsigned char c)//写一个字节数据到指定地址 {   P3OUT &=~BIT6;   TransceiveSPI1(WREN_CMD);

   // MemEnable();  // P3OUT &=0xBF;  // TxFlg=0;

  TransceiveSPI1(WRITE_CMD);   TransceiveSPI1((addr&0xff0000)>>16);   TransceiveSPI1((addr&0x00ff00)>>8);   TransceiveSPI1(addr&0x0000ff);     TransceiveSPI1(c);   P3OUT |=BIT6; }

unsigned char RdMemData(long int addr)//从指定地址读一个字节 { //  unsigned char temp;   P3OUT &=~BIT6;   TransceiveSPI1(READ_CMD);   TransceiveSPI1((addr&0xff0000)>>16);   TransceiveSPI1((addr&0x00ff00)>>8);   TransceiveSPI1(addr&0x0000ff);   temp=TransceiveSPI1(DUMY_CMD);    // TxSPI1(DUMY_CMD); //  temp=RxSPI1();

  P3OUT |=BIT6;   return temp; }

  • Jiejie Dai,

    你好!按照你的描述,你应该并没有成功控制FM25H20。建议您先让msp430SPI输出数据用示波器观察,根据FM25H20的数据手册上的时序要求,看看你编写的时序是否符合?

    确定了这一点之后,还需要遵循FM25H20的读写操作流程,下面是我在网上查到的。你检查一下你的主程序,是不是符合下面的操作流程?

    写操作
        FM25H20写操作先发送WREN指令,再发送WRITE指令。WRITE指令后接3个字节的地址,这24位地址中的高6位为任意码,低18位地址为要写入的首字节数据的有效地址,该地址后面为要写入的数据。若输人的数据大于1个,那么第一个数据后的数据存储地址由FM25H20内部依次增加给出。当地址达到3FFFFH时,地址计数器置为00000H,输入数据是以最高有效位(MSB)在前,最低有效位(LSB)在后的顺序传输的。
    读操作
        
    在S信号下降沿发送READ指令,在READ指令后紧接发送3个字节的地址。当发送完指令和地址后,可忽略数据线操作。数据总线等待8个时钟信号,依次读取数据。当地址达到3FFFFH时,地址计数器置为00000H,输入数据是以MSB在前,LSB在后的顺序传输的。

    上述两点都符合了,还是不可以的话,换个FM25H20试试。

    总之,一步一步排查问题,看看到底哪里出问题了。

    希望对你有帮助!

  • 通过示波器观测,MSP430 SIMO输出数据波形正确,CLK时钟信号正常,片选CS信号正常,WP和Hold引脚输出设置为高电平,

    我的思路是msp430输出一个数据到FM25H20的某一地址,例如0x0002ff,然后从该地址读取数据,如果发送的数据和读回的数据相等,

    则表示通信正常。现在的情况时msp430可以发送,SIMO数据正常,而FM25地址读取的数据一直为0xFF,用示波器观测,输出无信号。

    msp收发都未采用中断模式。

  • 通过示波器观测,MSP430 SIMO输出数据波形正确,CLK时钟信号正常,片选CS信号正常,WP和Hold引脚输出设置为高电平,

    我的思路是msp430输出一个数据到FM25H20的某一地址,例如0x0002ff,然后从该地址读取数据,如果发送的数据和读回的数据相等,

    则表示通信正常。现在的情况时msp430可以发送,SIMO数据正常,而FM25地址读取的数据一直为0xFF,用示波器观测,输出无信号。

    msp收发都未采用中断模式。

  • Jiejie Dai,

    你的验证思路是没有问题的。据你的描述,目前这只是完成了第一步,表明你的MSP430 SPI设置正确。接着查第二步,看看是否遵循FM25H20的读写操作流程。

    O(∩_∩)O~

  • 真的非常感谢您耐心的回答及帮我查阅的资料,心存感激和感恩。

    对FM25H20的读写操作,首先发送op-code,代码如下。片选CS信号由msp430控制,当对FM25进行操作是,片选信号拉低,发送op-code,然后发送地址,发送或接受数据,操作完成后,片选信号拉低。我现在不确定是什么地方出现纰漏或者还有我没考虑到的方面

    void MemEnable()       //发送器件写操作命令

     {   P3OUT &=~BIT6;  

     TransceiveSPI1(WREN_CMD);  

    P3OUT |=BIT6; }

    void MemDisable()      //发送器件写器件禁止

     {   P3OUT &=~BIT6;

      TransceiveSPI1(WRDI_CMD);  

      P3OUT |=BIT6;

    }

    void WrMemStatReg(unsigned char c)//写状态寄存器

     {   MemEnable();  

     P3OUT &=~BIT6;    

    TransceiveSPI1(WRSR_CMD);

      TransceiveSPI1(c);   

    P3OUT |=BIT6; }

    unsigned char RdMemStatReg()//读寄存器

     {

       P3OUT &=~BIT6;  

    TransceiveSPI1(RDSR_CMD);

      temp1=TransceiveSPI1(DUMY_CMD);

      P3OUT |=BIT6;  

     return temp1; }

    void  WrMemData(long int  addr, unsigned char c)//写一个字节数据到指定地址

     {   P3OUT &=~BIT6;

      TransceiveSPI1(WREN_CMD);

         TransceiveSPI1(WRITE_CMD);  

    TransceiveSPI1((addr&0xff0000)>>16);  

    TransceiveSPI1((addr&0x00ff00)>>8);  

     TransceiveSPI1(addr&0x0000ff);    

    TransceiveSPI1(c);  

     P3OUT |=BIT6; }

    unsigned char RdMemData(long int addr)//从指定地址读一个字节

     { 

     P3OUT &=~BIT6;  

     TransceiveSPI1(READ_CMD);  

     TransceiveSPI1((addr&0xff0000)>>16);  

     TransceiveSPI1((addr&0x00ff00)>>8);  

     TransceiveSPI1(addr&0x0000ff);

      temp=TransceiveSPI1(DUMY_CMD);

      P3OUT |=BIT6;  

     return temp; }

  • Jiejie Dai,

    在读数据时, 数据总线等待8个时钟信号,依次读取数据。而在你的读取字节函数中,如下所示,

    Jiejie Dai 说:
    temp=TransceiveSPI1(DUMY_CMD);

    你直接返回的是temp,并没有等待8个时钟信号。在这下面再加一句

     temp=TransceiveSPI1(DUMY_CMD);

    第一个用于等待,第二句用于读回数据。

    你试试看行不行?

    希望对你有帮助!O(∩_∩)O~

  • Lina Lian 说:

    Jiejie Dai,

    在读数据时, 数据总线等待8个时钟信号,依次读取数据。而在你的读取字节函数中,如下所示,

    temp=TransceiveSPI1(DUMY_CMD);

    你直接返回的是temp,并没有等待8个时钟信号。在这下面再加一句

     temp=TransceiveSPI1(DUMY_CMD);

    第一个用于等待,第二句用于读回数据。

    你试试看行不行?

    希望对你有帮助!O(∩_∩)O~

    [/quote]

    刚才试验了一下,FM还是无输出,不过这个发现对我很有帮助,当时看FM25 datasheet的时候一直在纠结这个问题。

    不知道我的收发函数有没有什么错误和main()函数是不是有问题:

    unsigned char TransceiveSPI1 (unsigned char txdata)

      {      

    while (!(UCB1IFG & UCTXIFG));             // wait until last SPI-Transmission is finished      

    UCB1TXBUF = txdata;                         // send 8 clocks "txdata" and SPI-clocks          

    while (!(UCB1IFG & UCRXIFG));           // wait until one byte is received      

    rxdata = UCB1RXBUF;            

     return rxdata;  

     }

    void main()

    {     Init_CLK()     ;  

    Init_Port()    ;      

     Init_SPI1();    

     __delay_cycles(10240000);      

      for(;;)  

     {  

        WrMemData(0x0002ff,FmTxData);     //FmTxData=0x55; 

     __delay_cycles(102400);    

     FmRxData=RdMemData(0x0002ff);     

     __delay_cycles(102400);    

     if(FmRxData==0x55)   

      {        P1OUT=0xff;  

       __delay_cycles(10240000);   

      P1OUT=0x00;    

     __delay_cycles(10240000);   

      }

      }

     }

     

     


     

     

  • Jiejie Dai,

    我下载了FM25H20的数据手册看了一下,对读取数据的控制,中文表述有误,你原来的理解应该是正确的。如下图所示,应该发完地址后,即可直接读数,datasheet中原文表述为:

    After the op-code and address are complete, the D line is ignored. The bus master issues 8 clocks, with one bit read out for each.

    故不需要等待8个时钟周期。

    我看了你的SPI的程序,有以下几个建议:

    1. 建议你把SPI读,写函数分开写,不要用一个TransceiveSPI1综合所有,对于FM25H20的操作而言,要不只需读,要不只需写,我没有看到需要同时读和写的。

    2.建议P1OUT的状态控制只控制有LED灯的那个端口,例如: P1OUT |= BIT0; P1OUT &= ~BIT0;

    3. 注意, 上电1ms后才可将S拉低。原文为:

    The FM25H20 is not accessible for a period of time
    (1 ms) after power up. Users must comply with the
    timing parameter tPU, which is the minimum time
    from VDD (min) to the first /S low.

    4. 严格用波器检查一下所有SPI操作是否符合数据手册11页对时序的要求。

    5.验证一下MSP430的SPI是否可成功发送和接收。

    希望对你有帮助!O(∩_∩)O~

  • Lina Lian 说:

    Jiejie Dai,

    我下载了FM25H20的数据手册看了一下,对读取数据的控制,中文表述有误,你原来的理解应该是正确的。如下图所示,应该发完地址后,即可直接读数,datasheet中原文表述为:

    After the op-code and address are complete, the D line is ignored. The bus master issues 8 clocks, with one bit read out for each.

    故不需要等待8个时钟周期。

    我看了你的SPI的程序,有以下几个建议:

    1. 建议你把SPI读,写函数分开写,不要用一个TransceiveSPI1综合所有,对于FM25H20的操作而言,要不只需读,要不只需写,我没有看到需要同时读和写的。

    2.建议P1OUT的状态控制只控制有LED灯的那个端口,例如: P1OUT |= BIT0; P1OUT &= ~BIT0;

    3. 注意, 上电1ms后才可将S拉低。原文为:

    The FM25H20 is not accessible for a period of time
    (1 ms) after power up. Users must comply with the
    timing parameter tPU, which is the minimum time
    from VDD (min) to the first /S low.

    4. 严格用波器检查一下所有SPI操作是否符合数据手册11页对时序的要求。

    5.验证一下MSP430的SPI是否可成功发送和接收。

    希望对你有帮助!O(∩_∩)O~

    非常感谢您的指点,已经测试成功,抽时间把代码上传,供大家参考指点一下

  • 您好,我现在也在做FM25H20的测试,读出来的数也是FF 

    希望您能指点下,给出您宝贵的经验。

    邮箱:freak.zhou@linkhope.co

    谢谢!

  • 怎么弄的 可以给我一份吗 我也在弄 QQ455987004

  • 请问一下,您原来读出来的数据是0xFF是怎么回事。不知道忘了没有,可以解答一下吗

  • 把读写速率降低,新的片子最好低速率下擦除一遍再用。

  • 谢谢你的解答,本来是准备回答自己的问题,好像这个论坛不能自问自答,就跑到你的下面来解答一下问题,借以帮助有需要的人

    我在设置SPI通信的时候,片选端口SS作为SPI的一部分片选,这一部分是有问题的。如果SS作为SPI的片选,在SPI发送一个字节之后SS会有一个变高。但是FM25H20的片选端口在接受连续数据时,片选端口一直处于低电平。因此在设置SPI模式时,SS应设置为普通输出端口,自己手动拉低或拉高。

    同时,再次感谢你的解答!