Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] SPI EEPROM not always returning back what was transmitted. MSP432 25LC040

Status
Not open for further replies.

Fish6

Newbie
Joined
Apr 1, 2021
Messages
3
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
21
Hello,

I am new to SPI and I am currently having trouble reading back from the SPI EEPROM 25LC040. Sometimes the transmit byte will match the received byte, but not continuously. I borrowed a lot of this code from CCS Resource Explorer. Can someone please help? Am I correct to assume that the EEPROM device is 00 for phase and polarity?

C:
#include "msp.h"
#include <stdint.h>

volatile uint8_t RXData = 0;
volatile uint8_t TXData;

int main(void)
{
    volatile uint32_t i;

    WDT_A->CTL = WDT_A_CTL_PW |             // Stop watchdog timer
            WDT_A_CTL_HOLD;

    P1->OUT &= ~BIT0;
    P1->DIR |= BIT0;                        // Configure P1.0 LED as output

    P1->SEL0 |= BIT4 | BIT5 | BIT6 | BIT7;  // set 4-SPI pin as second function

    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_SWRST; // Put state machine in reset

    // For our slave device, data goes out on falling edge and latched on the rising edge
    // Data present on SI pinn are latched on rising edge of clock input,
    // While data on the SO pin is updated after the falling edge of the clock input.

    EUSCI_B0->CTLW0 = EUSCI_B_CTLW0_SWRST | // Remain in reset state
            EUSCI_B_CTLW0_MST |             // SPI master
            EUSCI_B_CTLW0_SYNC |            // Synchronous mode
            //EUSCI_B_CTLW0_CKPH |
            //EUSCI_B_CTLW0_CKPL |            // Clock polarity high
            EUSCI_B_CTLW0_MSB |             // MSB first
            EUSCI_B_CTLW0_MODE_1 |          // 4-pin mode
            EUSCI_B_CTLW0_STEM |            // STE mode select
            EUSCI_B_CTLW0_SSEL__ACLK;       // ACLK

    EUSCI_B0->BRW = 1;                   // /2,fBitClock = fBRCLK/(UCBRx+1).
    EUSCI_B0->CTLW0 &= ~EUSCI_B_CTLW0_SWRST;// **Initialize USCI state machine**
    TXData = 0x01;                          // Holds TX data

    // Enable eUSCIA3 interrupt in NVIC module
    NVIC->ISER[0] = 1 << ((EUSCIB0_IRQn) & 31);

    while(1)
    {
        EUSCI_B0->IFG |= EUSCI_B_IFG_TXIFG; // Clear TXIFG flag
        EUSCI_B0->IE |= EUSCI_B__TXIE;      // Enable TX interrupt

        for (i = 1000; i > 0; i--);          // Delay before next transmission
        TXData++;                            // Increment transmit data
    }
}

// SPI interrupt service routine
void EUSCIB0_IRQHandler(void)
{
    if (EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG)  // data from txbuffer has moved to tx shift register
    {
        // Transmit characters
        EUSCI_B0->TXBUF = TXData;   // writing to txbuffer activates spi clock

        // Disable tx interrupt
        EUSCI_B0->IE &= ~EUSCI_B__TXIE;

        // Wait till a character is received
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_RXIFG));


        // Move data to a temporary buffer
        RXData = EUSCI_B0->RXBUF;

        if(RXData != 0x00){     // for debugging
            __no_operation();
            __no_operation();
        }
        // Clear the receive interrupt flag
        EUSCI_B0->IFG &= ~EUSCI_B_IFG_RXIFG;
    }
}
 
Last edited:

Hi,

Am I correct to assume that the EEPROM device is 00 for phase and polarity?
No need to "assume". --> read the datasheet.

****
According datasheet you need to follow a "write sequence" and a "read sequence".
I can't find this, no WRITE ENABLE, no WRITE instruction, no address set.

Klaus
 

    Fish6

    Points: 2
    Helpful Answer Positive Rating
I'm not familiar with MSPxx5 family and don't have the time to go into detailed reading of the user manual, In my understanding, SPI mode 0 will be selected by CKHP=1 CKPL=0 and mode 3 by CKHP=0 CKPL=1. Your setting corresponds to mode 1 and doesn't work with SPI EEPROMs because it samples on falling CLK edge.

1617264346893.png

MSP SPI modes

1617264769754.png

EEPROM SPI modes

In my view, the code becomes unneccessarily complicated by using interrupts for the data transfer. Don't know if there's any reason for it in your application. I would at least start without it.
 

    Fish6

    Points: 2
    Helpful Answer Positive Rating
Thanks so much! I will try again using the datasheet instruction sequences and polling instead of interrupts.
--- Updated ---

Hi,


No need to "assume". --> read the datasheet.

****
According datasheet you need to follow a "write sequence" and a "read sequence".
I can't find this, no WRITE ENABLE, no WRITE instruction, no address set.

Klaus

Thanks!!
I looked up how to program SPI EEPROM using the sequences. Now I can write to the EEPROM and read the same byte even after powering off the device.

C:
// Implement SPI using polling method

#include "msp.h"
#include <stdint.h>

// EEPROM Instructions
#define READ    0x03
#define WRITE   0x02
#define WRDI    0x04
#define WREN    0x06
#define RDSR    0x05
#define WRSR    0x01

uint8_t SPI_transfer(uint8_t data);
void wait_busy(void);
void read_EEPROM(uint8_t address);
void write_EEPROM(uint8_t address);

uint8_t RDxBuffer = 0;

int main(void)
{
    volatile uint32_t i;

    WDT_A->CTL = WDT_A_CTL_PW |             // Stop watchdog timer
                 WDT_A_CTL_HOLD;

    P1->SEL0 |= BIT4 | BIT5 | BIT6 | BIT7;  // set 4-SPI pin as second function

    P8->DIR |= BIT7;    // CS Pin GPIO
    P8->OUT |= BIT7;

    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_SWRST; // Put state machine in reset

    EUSCI_B0->CTLW0 = EUSCI_B_CTLW0_SWRST | // Remain in reset state
                        EUSCI_B_CTLW0_MST | // SPI master
                       EUSCI_B_CTLW0_SYNC | // Synchronous mode
                        EUSCI_B_CTLW0_MSB | // MSB first
                     EUSCI_B_CTLW0_MODE_1 | // 4-pin mode
                       EUSCI_B_CTLW0_STEM | // STE mode select
                  EUSCI_B_CTLW0_SSEL__ACLK; // ACLK

    EUSCI_B0->BRW = 1;  //2,fBitClock = fBRCLK/(UCBRx+1).
    EUSCI_B0->CTLW0 &= ~EUSCI_B_CTLW0_SWRST;// **Initialize USCI state machine**


    while(1)
    {
        read_EEPROM(0);
        write_EEPROM(0);
    }
}

uint8_t SPI_transfer(uint8_t data){

    // begin transmission
    EUSCI_B0->TXBUF = data;

    // wait while eUSCI_B is busy
    while(EUSCI_B0->STATW & EUSCI_B_STATW_SPI_BUSY){}

    // read recieved value
    return EUSCI_B0->RXBUF;
}

void wait_busy(void){

    char status = 0;

    do{
        P8->OUT &= ~BIT7;    // CS select

        SPI_transfer(RDSR);
        status = SPI_transfer(0);

        P8->OUT |= BIT7;     // CS release
    } while(status == 1);

}

void read_EEPROM(uint8_t address){

    wait_busy();
    P8->OUT &= ~BIT7;   // CS select
    SPI_transfer(READ);
    SPI_transfer(address);
    RDxBuffer = SPI_transfer(0);
    P8->OUT |= BIT7;    // CS release
}

void write_EEPROM(uint8_t address){

    wait_busy();

    // Protect Release
    P8->OUT &= ~BIT7;   // CS select
    SPI_transfer(WRSR);
    SPI_transfer(0x02);
    P8->OUT |= BIT7;    // CS release

    // Write Enable
    P8->OUT &= ~BIT7;   // CS select
    SPI_transfer(WREN);
    P8->OUT |= BIT7;    // CS release

    // Write
    P8->OUT &= ~BIT7;   // CS select
    SPI_transfer(WRITE);
    SPI_transfer(address);
    SPI_transfer(0xCD);
    P8->OUT |= BIT7;    // CS release

}
 
Last edited:

Hi,

Your program looks much better now. And it works.
How helpful a datasheet is ;-)

One issue:
Don't know how fast your microcontroller is, but (in write_EEPROM) you release CS then set CS without delay.
Read the datasheets whether timing specification is met.

Klaus
 

Still wrong SPI mode, I believe.

Hello,

My code is setting the phase and polarity as 00. I am trying to follow the 25LC040 datasheet. From what I remember the master and slave is supposed to have same clock phase and polarity. And from the 25LC040 datasheet section 3.1 Principles of Operation I found this:

1617318023295.png


From 2.5 of datasheet:
1617320590758.png

Sampled on rising edge means 00 or 11 for phase-polarity. But I could not find any evidence for polarity except that all the figures in the datasheet seem to idle SCK low.

Please correct me if I am wrong, I'm still new to SPI and EEPROM.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top