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.

MSP430G2553: SPI Interface for CAT25128 EEPROM

Part Number: MSP430G2553

Hello All,

Title : Interfacing EEPROM CAT25128 with MSP430g2553.

IDE : CCS

Issue : I am getting read and write with EEPROM 3 times out of 10 times.

Sometimes I read same data as written.

Sometimes i get previous data.

Sometimes on "Read status register" , i got 0xFF in UCA0RXBUF.(This happens many of the times, which should not happen)

Here i am attaching my files for code.

Please tell me if i am configuring anything wrong.

strange : Datasheet says EEPROM work on SPI mode 00 and 11, but i got output(of cource not every time) on mode 01.

////////////////////////////////////////////////////////main.c//////////////////////////////////////////////
int main()
{

	spi_init();
	//p = isReady();
	if(isReady())
	{
		enableWrite();
		q = getstatusregister();
	}
	while(1) {

		Delay();

		writeByte(0x0008,0x01);
		__delay_cycles(1000);                 // Wait for slave to initialize
		p=readByte(0x0008);
		Delay();

	}


}



////////////////////////////////////////////////SPI.c////////////////////////////////////////////

#include <msp430.h>
#include "spi.h"
//#include "eeprom.h"
#include "stdint.h"

void spi_init(void)
{
	WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
	P1OUT = 0x00;                             // P1 setup for LED & reset output
	BCSCTL1 = CALBC1_1MHZ; 				//Set DCO to 8Mhz
	DCOCTL = CALDCO_1MHZ; 				//Set DCO to 8Mhz

	P1DIR |= BIT0 + BIT5;                     //
	P1SEL = BIT1 + BIT2 + BIT4;
	P1SEL2 = BIT1 + BIT2 + BIT4;
	UCA0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC;  // 3-pin, 8-bit SPI master
	//  UCA0CTL0 |= 0xC0 ;  // 3-pin, 8-bit SPI master
	//UCA0CTL0 &= 0x3F ;  // 3-pin, 8-bit SPI master

	UCA0CTL1 |= UCSSEL_2;                     // SMCLK
	UCA0BR0 |= 0x02;                          // /2
	UCA0BR1 = 0;                              //
	UCA0MCTL = 0;                             // No modulation
	UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
	//UCA0CTL1 |= UCSWRST;                     // **Initialize USCI state machine**

	//  IE2 |= UCA0RXIE;                          // Enable USCI0 RX interrupt

	P1OUT &= ~BIT5;                           // Now with SPI signals initialized,
	P1OUT |= BIT5;                            // reset slave

}

void select_chip()
{
	  P1OUT &= ~BIT0;
}

void deselect_chip()
{
    P1OUT |= BIT0;                          // If correct, light LED
}

uint8_t send_byte_spi(uint8_t byte)
{
	  uint8_t Received_byte;
	  UCA0TXBUF = byte;                     // Transmit first character
	  //Delay();
	  //__delay_cycles(100);                 // Wait for slave to initialize
	  Received_byte = UCA0RXBUF;
	  return Received_byte;
}

void Delay()
{
	  __delay_cycles(10000);                 // Wait for slave to initialize
}


///////////////////////////////////////////////////////////EEPROM.c//////////////////////////////////

#include <msp430.h>
#include <stdbool.h>
#include "spi.h"
#include "eeprom.h"
#include "stdint.h"
	uint8_t ret1;
uint8_t HB,LB;

uint8_t getstatusregister()
{
	uint8_t ret;
	startCommand(EEPROM_CAT25_COMMAND_RDSR, 0);
	//loop added by 
	do {
		ret = send_byte_spi(EEPROM_CAT25_DUMMY_BYTE);
	}while(ret == 0xFF);
	//startCommand(EEPROM_CAT25_COMMAND_RDSR, 0);

	endCommand();
	return(ret);
}


void startCommand(uint8_t command, const uint16_t address)
{

 // _spi->beginTransaction(_spiSettings);
	select_chip();
  /*  if (command == EEPROM_CAT25_COMMAND_READ) {
      command = EEPROM_CAT25_COMMAND_READ_A8_HIGH;
    } else if (command == EEPROM_CAT25_COMMAND_WRITE) {
      command = EEPROM_CAT25_COMMAND_WRITE_A8_HIGH;
    }
*/
    //Delay(); 

 // _spi->transfer(command);
    ret1 = send_byte_spi(command);

	//  __delay_cycles(1000);                 // Wait for slave to initialize

  if (command == EEPROM_CAT25_COMMAND_READ || command == EEPROM_CAT25_COMMAND_WRITE) {
    sendAddressBytes(address);
  }
}


void sendAddressBytes(const uint16_t address)
{uint8_t pp;
/*  if (EEPROM_CAPACITY_CAT25128 > 0x10000) {
    //_spi->transfer((uint8_t)((address >> 16) & 0xFF));
     * HB =
	pp =  send_byte_spi((uint8_t)((address >> 16) & 0xFF));


  }*/

  if ((EEPROM_CAPACITY_CAT25128 > 0x100)) {
   // _spi->transfer((uint8_t)((address >> 8) & 0xFF));
	  HB=((uint8_t)((address >> 8) & 0xFF));
	pp=   send_byte_spi(HB);

  }

 // _spi->transfer((uint8_t)(address & 0xFF));
  LB=((uint8_t)(address & 0xFF));
  pp=	  send_byte_spi(LB);

}
/*void sendAddressBytes(const uint32_t address)
{
	  UCA0TXBUF = 0x00;                     // Transmit first character
	  UCA0TXBUF = 0x00;                     // Transmit first character

	}*/


bool isReady(void)
{
  if ((getstatusregister() & EEPROM_CAT25_RDY_Msk) == EEPROM_CAT25_RDY_BUSY) {
    return(false);
  }
  return(true);
}

void endCommand(void)
{
  //  Delay(); 

	deselect_chip();
	//_spi->endTransaction();
}


void enableWrite(void)
{
  startCommand(EEPROM_CAT25_COMMAND_WREN, 0);
  endCommand();
}

void disableWrite(void)
{
  startCommand(EEPROM_CAT25_COMMAND_WRDI, 0);
  endCommand();
}

uint8_t readByte(const uint16_t address)
{
	uint8_t ret;
  if (address >= EEPROM_CAPACITY_CAT25128) {
    return(0);
  }

  while (!isReady()) {
   // yield();
	  ;
  }

  startCommand(EEPROM_CAT25_COMMAND_READ, address);
//  ret = send_byte_spi(EEPROM_CAT25_DUMMY_BYTE);
  Delay();
  do {
  		ret = send_byte_spi(EEPROM_CAT25_DUMMY_BYTE);
  	}while(ret == 0xFF || ret == 0x00);

 // startCommand(EEPROM_CAT25_COMMAND_READ, address);

  endCommand();

 return(ret);
}

uint8_t writeByte(const uint16_t address, const uint8_t byte)
{
  if (address >= EEPROM_CAPACITY_CAT25128) {
    return(0);
  }

  while (!isReady()) {
    //yield();
	  ;
  }

  enableWrite();
  startCommand(EEPROM_CAT25_COMMAND_WRITE, address);
  send_byte_spi(byte);
  endCommand();

  return(1);
}


/////////////////////////////////////////EEPROM.h///////////////////////////////////////////////////////
#include <msp430.h>
#include <stdbool.h>
#include "stdint.h"

#define EEPROM_CAT25_DUMMY_BYTE			0xFF

// Commands supported by all chips
#define EEPROM_CAT25_COMMAND_READ		0x03
#define EEPROM_CAT25_COMMAND_WRITE		0x02
#define EEPROM_CAT25_COMMAND_RDSR		0x05
#define EEPROM_CAT25_COMMAND_WRSR		0x01
#define EEPROM_CAT25_COMMAND_WREN		0x06
#define EEPROM_CAT25_COMMAND_WRDI		0x04


#define EEPROM_CAPACITY_CAT25128	0x4000

/* The CAT25040/CAT25020/CAT25010 use 8 address bits, while the
 * larger EEPROMs use 16 bits (or 24 bits for the 1MBit chips and above).
 * The CAT25040 however, needs 9 bits, so bit position 3 of the
 * READ or WRITE instrutions is used as the 9th bit of the address.
 */
//#define EEPROM_CAT25_COMMAND_READ_A8_HIGH	0x0B
#define EEPROM_CAT25_COMMAND_READ_A8_HIGH	0x13

//#define EEPROM_CAT25_COMMAND_WRITE_A8_HIGH	0x0A
#define EEPROM_CAT25_COMMAND_WRITE_A8_HIGH	0x12


#define EEPROM_CAT25_RDY_Pos			0
#define EEPROM_CAT25_RDY_Msk			(0x1ul << EEPROM_CAT25_RDY_Pos)
#define EEPROM_CAT25_RDY(value)			(EEPROM_CAT25_RDY_Msk & ((value) << EEPROM_CAT25_RDY_Pos))
#define EEPROM_CAT25_RDY_READY_Val		0x0ul
#define EEPROM_CAT25_RDY_BUSY_Val		0x1ul
#define EEPROM_CAT25_RDY_READY			(EEPROM_CAT25_RDY_READY_Val << EEPROM_CAT25_RDY_Pos)
#define EEPROM_CAT25_RDY_BUSY			(EEPROM_CAT25_RDY_BUSY_Val << EEPROM_CAT25_RDY_Pos)


uint8_t getstatusregister();
void startCommand(uint8_t command, const uint16_t address);
void sendAddressBytes(const uint16_t address);
void endCommand(void);
bool isReady(void);
void enableWrite(void);
void disableWrite(void);
uint8_t readByte(const uint16_t address);
uint8_t writeByte(const uint16_t address, const uint8_t byte);



  • Hi Palak,

    According to the CAT25128 datasheet the input data is latched on the rising edge of the SCK clock input. It's a little hard to understand but I interpret this as a UCCKPH = 1 in the MSP430 where data is captured on the first UCLK edge and changed on the following edge. Also, I believe it corresponds to an inactive clock polarity of low (UCCKPL = 0). It looks like you have this switched around in your code. Can you make these modifications and let me know if it helps?

    Also, please read through the SPI section of Solutions to Common eUSCI and USCI Serial Communication Issues on MSP430 MCUs for a detailed explanation of the most common SPI issues and their solutions. 

    Best regards, 
    Caleb Overbay

  • There shouldn't be any difference if the clock idles low or high. It is important that the data is latched at the rising edge of the clock signal, so if you have a clock idle state of low, then you have to configure the USCI to latch the data on the 1st and change it on the 2nd edge and if it idles high, then change data on the 1st and latch it on the 2nd edge.
  • Hi Palak,

    Have you been able to solve this issue? If so could you post your solution to the forum to help others who may experience the same issue?

    Best regards,
    Caleb Overbay

**Attention** This is a public forum