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.

MSP430读写SPI接口EEPROM的例程



您好,

请问是否有MSP430读写SPI接口EEPROM的参考例程?

谢谢。

  • //文件名:MC430F14_DEMO_4.c  

    //版本: 1.0  

    //描述:MC430F14开发板的主程序,MSP430模拟SPI接口与AT93C46读写实例。  

    //     向AT93C46写入一个数据,然后读出一个数据进行验证。  

    //编程环境:IAR WE430 3.40A  

    //编写: www.microcontrol.cn  DC  

    //时期: 2006.9.20.  

    #include <msp430x14x.h>  

    #include "MC430F14_DEMO_4.h"  

    void init(void);  

    //-----------------------------------------------------  

    void init(void)  

    { unsigned int i;  

     P5DIR |= 0x01 ;             //5.0(93C46_CS)为输出  

     P5DIR |= 0x02 ;             //5.1(93C46_DI)为输出  

     P5DIR |= 0x08 ;             //5.3(93C46_SCLK)为输出  

     P1DIR |= BIT1;              //P1.0(LED)指示数据正确性  

     P1OUT |= BIT1;              //先关闭LED  

     BCSCTL1 &= ~XT2OFF;         //启动XT2,  

     do  

      {IFG1 &= ~OFIFG;           //清OSCFault标志  

        for(i=0xFF;i>0;i--);    //延时等待  

      }  

      while((IFG1 & OFIFG) != 0); //查OSCFault,为0时转换完成  

     BCSCTL2 |= SELM_3+SELM1;            //MCLK 8分频,MCLK为XT2  

    }  

    void main(void)  

    {unsigned char ErrorFlag;            //错误标志位  

      unsigned int i;  

     WDTCTL = WDTPW + WDTHOLD;             // 停止WDT  

     init();  

     i=0;  

     ErrorFlag = Write_One(0x00,0x0f);  

     i = Read_One(0x00);  

     if (i==0x0f)  

       P1OUT ^= BIT1;  

     LPM0;  

    }  

    //文件名:MC430F14_DEMO_4.h  

    //版本: 1.0  

    //描述:程序声明  

    //编程环境:IAR WE430 3.40A  

    //编写: www.microcontrol.cn  DC  

    //时期: 2006.9.20.  

    //***********************************************************************  

    //*Name         :READ()  

    //*Discription  :93C46的字读取程序  

    //*输入:要读取的字地址(8bit:7位,16bit:6位)  

    //*输出:读取的字数值  

    //*从指定单元读出数据命令  

    //**********************************************************************  

    unsigned int Read_One(unsigned char Address);  

    //**********************************************************************  

    //*Name         :WRITE()  

    //*Discription  :93C46的字写入程序  

    //*输入: address 要写入的字地址(6位)  

    //* op_data 要写入的数据(16位)  

    //*输出: 读取的字数值  

    //*写入指定单元命令  

    //**********************************************************************  

    unsigned int Write_One(unsigned char Address,unsigned int Op_Data);  

    //文件名:MSP430_93C46.c  

    //版本: 1.0  

    //描述:MC430F14开发板的主程序,MSP430模拟SPI接口与AT93C46操作主程。  

    //以下AT93C46操作程序中是参考Benny Chen先生的例程。  

    //编程环境:IAR WE430 3.40A  

    //编写: www.microcontrol.cn    Benny Chen & DC  

    //时期: 2006.9.20.  

    #define CS_93C46_LOW P5OUT &= ~0x01      // CS = 0  

    #define CS_93C46_HIGH P5OUT |= 0x01      // CS = 1            

    #define SK_93C46_LOW P5OUT &= ~0x08      // SK = 0  

    #define SK_93C46_HIGH P5OUT |= 0x08      // SK = 1  

    #define DO_93C46_LOW ~(P5IN & 0x04)      // DO = 0  从93C46输出0  

    #define DO_93C46_HIGH P5IN & 0x04      // DO = 1  从93C46输出1  

    #define DI_93C46_LOW P5OUT &= ~0x02      // DI = 0  

    #define DI_93C46_HIGH P5OUT |= 0x02      // DI = 1  

    #define CMD_DisWrite 0x00      //禁止写命令  

    #define CMD_WriteAll 0x20        // x020:8bit     0x10:16bit,  写全部命令  

    #define CMD_EraseAll 0x40        // x040:8bit     0x20:16bit,  擦全部命令  

    #define CMD_EnWrite 0x60        //0x60:8bit      0X30:16BIT   允许写命令  

    #define CMD_Write 0x80          //8bit:0X80(0 1A6A5A4 A3A2A1A0)   16bit:0X40(01A5A4 A3A2A1A0)  

    #define CMD_Read 0x100          //8bit:0X100(10A6A5A4 A3A2A1A0)   16bit:0X80(10A5A4 A3A2A1A0)  

    #define CMD_Erase 0x180          //8bit:0X180(1 1A6A5A4 A3A2A1A0)  16bit:0XC0(11A5A4 A3A2A1A0)  

    #define START_Bit 0x200          //8bit:0x200      16bit:0x100  

    /*************************************************************/  

    /*Name         : Delay() */  

    /*Discription  : 延时子程序/  

    /*************************************************************/  

    void Delay(unsigned int num)  

    {  

    while(--num);  

    }  

    /*************************************************************/  

    /*Name         : START_93C46() */  

    /*Discription  : 启动93C46 */  

    /*************************************************************/  

    void START_93C46()  

    {  

    CS_93C46_HIGH;            /*开启93C46*/  

    CS_93C46_LOW;  

    DI_93C46_LOW;  

    SK_93C46_LOW;  

    CS_93C46_HIGH;                  //CS片选高电平有效  

    Delay(1000);  

    }  

    /****************************************************************/  

    /*Name         :END_93C46() */  

    /*Discription  :用于93C46的结束  

    /****************************************************************/  

    void END_93C46()  

    {  

    CS_93C46_LOW;                  //CS片选高电平无效  

    DI_93C46_HIGH;  

    SK_93C46_HIGH;  

    }  

    /*************************************************************/  

    /*Name         :SEND_DATA_93C46() */  

    /*Discription  :在93C46启动下,送入指定位数的数据 */  

    /*输入: op_data 要输入的数据 */  

    /* num 输入的位数 */  

    /* 最高位先送出 */  

    /*************************************************************/  

    void SEND_DATA_93C46(unsigned int Op_Data,unsigned char Num)  

    {  

    unsigned char i;  

    Op_Data = Op_Data << (16 - Num); /*左移去掉无用位*/  

    for(i = Num; i > 0; i --)  

     {  

      if ((Op_Data & 0X8000) ==0 )              

           DI_93C46_LOW;                  //MCU输出1位0  

      else  

          DI_93C46_HIGH;                  //MCU输出1位1  

      SK_93C46_HIGH;                  //产生一个时钟        

      SK_93C46_LOW;  

      Op_Data <<= 1;                  //指向下一位  

     }  

    }  

    /*********************************************************/  

    /*Name         : EWEN_93C46() */  

    /*Discription  :93C46的编程启动.操作码(100 11XXXXX) */  

    /* 擦写指定单元命令 */  

    /*********************************************************/  

    void EWEN_93C46()  

    {  

    START_93C46();  

    SEND_DATA_93C46(START_Bit + CMD_EnWrite, 0X0A);  

    END_93C46();  

    }  

    /***********************************************************************/  

    /*Name         : EWDS_93C46() */  

    /*Discription  : 93C46的编程关闭.操作码(8bit:100 00XXXXX    16bit:100 00XXXX) */  

    /*擦写禁止命令 */  

    /**********************************************************************/  

    void EWDS_93C46()  

    {  

    START_93C46();  

    SEND_DATA_93C46(START_Bit + CMD_DisWrite, 0X0A);  

    END_93C46();  

    }  

    /***********************************************************************/  

    /*Name         :READ() */  

    /*Discription  :93C46的字读取程序 */  

    /*输入:要读取的字地址(8bit:7位,16bit:6位) */  

    /*输出:读取的字数值 */  

    /*从指定单元读出数据命令 */  

    /**********************************************************************/  

    unsigned int Read_One(unsigned char Address)  

    {  

    unsigned int i;  

    unsigned int Result;  

    START_93C46();                        //启动93C46  

    SEND_DATA_93C46(START_Bit + CMD_Read + Address, 0X0A);  

    Result = 0;                        //存放返回数据的缓冲先清零  

    for(i =8; i >0; i--)                  //循环读出8个数据  

     {  

      Result = Result << 1;                  //先读最高位  

      SK_93C46_HIGH;  

      SK_93C46_LOW;  

      if (DO_93C46_HIGH)  

        Result = Result | 0X01;  

     }  

    END_93C46();                        //结束93C46  

    return Result;                        //返回读出的数据  

    }  

    /**********************************************************************/  

    /*Name         :WRITE() */  

    /*Discription  :93C46的字写入程序 */  

    /*输入: address 要写入的字地址(6位) */  

    /* op_data 要写入的数据(16位) */  

    /*输出: 读取的字数值 */  

    /*写入指定单元命令 */  

    /**********************************************************************/  

    unsigned int Write_One(unsigned char Address,unsigned int Op_Data)  

    {  

    unsigned char ErrorFlag;                  //错误标志位  

    unsigned int mCount;  

    EWEN_93C46();                        //启动93C46  

    START_93C46();                        //擦写指定单元命令  

    SEND_DATA_93C46(START_Bit + CMD_Write + Address, 0x0A);  //写入指定单元命令  

    SEND_DATA_93C46(Op_Data,0X08);                  //接着写入指定单元命令的数据  

    CS_93C46_LOW;  

    CS_93C46_HIGH;  

    ErrorFlag = 0;                        //清错误标志位  

    mCount = 50000;                        //延时时间  

    while (DO_93C46_LOW)                        //擦写忙闲标志  

     {  

      if (! --mCount)  

       {  

        ErrorFlag = 1;                        //延时过,还在忙则表示有错识  

        break;  

       }  

      }  

    END_93C46();                        //结束93C46  

    EWDS_93C46();                        //擦写禁止命令  

    return ErrorFlag;                        //返回表示擦除状态的特征  

    }  

  • 除了上面的参考代码,也得看您的EEPROM的时序、寄存器的情况,以及选用的MSP430的型号来调试

  • 其实给你参考代码意义不大,你还是需要自己去根据EEPROM写一个SPI的程序,不如查看TI的一些SPI的code example能够帮助到你理解。下面是一个EEPROM的例程。

    #include <MSP430Fx.h>  

    #include "dispport.h"  

    #include "spi_eeprom.h"  

    unsigned char EE_JustWritten=0; // Set to TRUE to force WaitRdy check before read.  

    void EE_Select(void) { P5OUT&=~EE_CS; }  

    void EE_DeSelect(void) { P5OUT|=EE_CS; }  

    unsigned char EE_RW(unsigned char txbyte) {  

    // Writes one byte to bitbang SPI, msb first, while receiving a byte  

    // EEprom is assumed to be faster than the processor in bitbang mode  

     unsigned char rxbyte=0;  

     char i;    

     for (i=0;i=7;i++) {  

       if (txbyte & 0x80) P5OUT|=EE_SI; else P5OUT&=~EE_SI; // set data  

       P5OUT|=EE_CK;   // Clock data in  

       rxbyte<=1;     // Rotate a nice hole for the data  

       if (P5IN & EE_SO) rxbyte++;  

       P5OUT&=~EE_CK;  // And get a bit out  

       txbyte<=1;  

     }    

     return rxbyte;  

    }    

    void EE_WREN(void) { EE_Select(); EE_RW(0x06); EE_DeSelect(); } // WREN command    

    void EE_WRDI(void) { EE_Select(); EE_RW(0x04); EE_DeSelect(); } // WRDI command    

    unsigned char EE_RDSR(void) { // Read SR  

    // SR is xxxx BP1 BP0 WEN -RDY  

    unsigned int res;    

     EE_Select(); EE_RW(0x05); res=EE_RW(0); EE_DeSelect();    

     return res;  

    }  

    void EE_WRSR(unsigned char status) { // Read SR  

     EE_Select(); EE_RW(0x01); EE_RW(status); EE_DeSelect();    

    }  

    void EE_WaitRdy(void) {  

     while (EE_RDSR() & 1) {}; // Loop until -RDY drops to 0  

     EE_JustWritten=0;    

    }  

    unsigned char EE_WR(unsigned int adr, unsigned char data) {  

    // Write a byte to the EEPROM. Returns status register on completion.  

     if (EE_JustWritten) EE_WaitRdy(); // See if we were finished with the last one    

     EE_WREN(); // Enable Write    

     EE_Select();  EE_RW(0x02); // Write command  

     EE_RW(adr >> 8); EE_RW(adr & 0xFF); // send address  

     EE_RW(data);  

     EE_DeSelect();  

     EE_JustWritten=1;    

     return EE_RDSR();  

    }  

    unsigned char EE_RD(unsigned int adr) {  

    // Read a byte from the EEPROM  

    unsigned int res;    

     if (EE_JustWritten) EE_WaitRdy();    

     EE_Select();  EE_RW(0x03); // Read command  

     EE_RW(adr >> 8); EE_RW(adr & 0xFF); // send address  

     res=EE_RW(0);  

     EE_DeSelect();    

     return res;    

    }  

    unsigned char EE_Write(unsigned int adr, unsigned char *data, unsigned char datalen) {  

    // Writes up to 64 bytes to the EEPROM. Returns status register on completion.  

     unsigned char i;    

     if (EE_JustWritten) EE_WaitRdy(); // See if we were finished with the last one    

     EE_WREN(); // Enable Write    

     EE_Select();  EE_RW(0x02); // Write command  

     EE_RW(adr >> 8); EE_RW(adr & 0xFF); // send address  

     for (i=0;i<datalen;i++) EE_RW(*data++);  

     EE_DeSelect();  

     EE_JustWritten=1;    

     return EE_RDSR();  

    }  

    void EE_Read(unsigned int adr, unsigned char *data, unsigned int datalen) {  

    // Reads any number of bytes from the EEPROM  

    unsigned int i;    

     if (EE_JustWritten) EE_WaitRdy();    

     EE_Select();  EE_RW(0x03); // Read command  

     EE_RW(adr >> 8); EE_RW(adr & 0xFF); // send address  

     for (i=0;i<datalen;i++) *data++=EE_RW(0);  

     EE_DeSelect();    

    }  

  • 非常感谢大家的帮助,谢谢