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.

MSP430F2272 with external EEPROM the 2nd

Other Parts Discussed in Thread: MSP430F2272

Hi there. It's me again. :) 

Again I have some issues with the MSP430F2272 and the ATMEL AT24C512B EEPROM. 

The Issue is when trying to read from the eeprom it stops after the second byte. It should read 12 bytes.

On the picture I'm calling "fnReadSystemValues();" and you can see the first 2 bytes of "fnStoreSystemValues();

  

Attached you can find the code. 

Is there a way to determine if the NACK has been created by the stop condition or by the EEPROM? 

Thx for the support. working on this for several hours now and running totaly out of ideas.

/*
 * I2C.c
 *
 *  Created on: 02.08.2012
 *      Author: l-doerner
 */

#include "I2C.h"

UINT16	Address					=	0;
UINT16	Length						=	0;

UINT8	*pTransmit					=	0;
UINT8	*pReceive					=	0;
UINT8	*pAddress					=	0;

UINT8	Target							=	WRITE_HISTORY;

UINT8	Addressing_Flag			=	0;

void fnInitI2C			(void)
{
	UCB0CTL1 = UCSWRST;
	/* I2C | master | single master | synchronous mode | slave address 7bit | own address 7bit */
	UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;

	/* enable SW reset | use SMCLK | normal ACK | no START | no STOP | reciver */
	UCB0CTL1 = UCSSEL_2 + UCSWRST;

	/* 12MHz/120 = 100KHz */
	UCB0BR0 = 0x78;
	UCB0BR1 = 0x00;
	//UCB0BR0 = 0x12;                             // set prescaler
	//  UCB0BR1 = 0;
	UCB0I2CSA = EEPROM;
	UCB0CTL1 &= ~UCSWRST;
	UCB0I2CIE = UCNACKIE;			/* Not-acknowledge interrupt enable*/
}

void fnStoreHistory 	(void)
{
//	fnInitI2C();
	Target							=		WRITE_HISTORY;
	Address						=		System.Actual_Page	*	128 + System.Page_Position;
	pAddress						=		(UINT8 *)& Address;
	pTransmit					=		(UINT8	*)	&history.Cylce;
	Length							=		sizeof(history);
	Addressing_Flag			=		1;
	IE2 			 					= 		UCB0TXIE;			/* USCI_B0 transmit interrupt enable */
	UCB0CTL1 					|= 	UCTR + UCTXSTT;		/* start condition I2C transmit */
	while (UCB0STAT & UCBBUSY);
}

void fnStoreSystemValues	(void )
{
//	fnInitI2C();
	Target						=		WRITE_SYSTEM;
	Address					=		0x0000;
	pAddress					=		(UINT8 *) &Address;
	pTransmit				=		(UINT8	*)	&System.Cycle_Count;
	Length						=		sizeof(System);
	Addressing_Flag		=		1;
	IE2 			 				= 		UCB0TXIE;			/* USCI_B0 transmit interrupt enable */
	UCB0CTL1 				|= 	UCTR + UCTXSTT;		/* start condition I2C transmit */
	while (UCB0STAT & UCBBUSY);
}

void fnReadHistory	(UINT16 Start_Address, UINT16 Length)
{
//	fnInitI2C();
	Target						=		READ_HISTORY;
	Address						=		Start_Address;
	pAddress					=		(UINT8 *) &Address;
	Length						=		Length;
	Addressing_Flag		=		1;
	IE2 			 					= 		UCB0TXIE;			/* USCI_B0 transmit interrupt enable */
	UCB0CTL1 				|= 	UCTR + UCTXSTT;		/* start condition I2C transmit */
	while (UCB0STAT & UCBBUSY);
}

void fnReadSystemValues 	(void)
{
//	fnInitI2C();
	Target							=		READ_SYSTEM;
	Address						=		0x0000;
	pAddress						=		(UINT8 *) &Address;
	pReceive						=		(UINT8	*)&	System.Cycle_Count;
	Length							=		sizeof(System);
	Addressing_Flag			=		1;
	IE2 			 					= 		UCB0TXIE;				/* USCI_B0 transmit interrupt enable */
	UCB0CTL1 					|= 	UCTR + UCTXSTT;		/* start condition I2C transmit */
	while (UCB0STAT & UCBBUSY);
}

void fnCheckSystemValues (void)
{
	fnReadSystemValues();

	if (System.Cycle_Count	==	0xFFFF)
	{
		System.Cycle_Count				=	0;
		System.Actual_Page				=	HISTORY_START_PAGE;
		System.Page_Position				=	0;
		System.Completed_Cycles		=	0;
		System.cal_value					=	0;
		fnStoreSystemValues();
	}
}

inline void	fnCheck_Page_Overflow(void)
{
	System.Page_Position++;

	if(System.Page_Position		==	128)
	{
		System.Page_Position		=		0;
		if (System.Actual_Page		== 	511)
		{
			System.Actual_Page		=		HISTORY_START_PAGE;
		}
		else
		{
			System.Actual_Page++;
		}
		Addressing_Flag		=		1;
		Address						=		System.Actual_Page	*	128 + System.Page_Position;
		pAddress					=		(UINT8 *) &Address;
	}
}


void fnResetHistoryValues  (void)
{
	history.Cylce						=	0;
	history.ProfileNumber			=	0;
	history.Start_Voltage			=	0;
	history.End_Voltage			=	0;
	history.Ah_charged				=	0;
	history.Refresh_Counter		=	0;
	history.Faults						=	0;
	history.Completed_Cycles	=	0;
}




#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR (void)
{
	static UINT8 Address_length		=	2;

	if (IFG2 & UCB0RXIFG)				// UCB0RXIFG is set when UCB0RXBUF has received a complete character
	{
		switch (Target) {
			case READ_HISTORY:
				if ( Length == 13)		// all Bytes read
				{
					UCB0CTL1 |= UCTXSTP;	// stop condition I2C
					IFG2 					&= 	~UCB0RXIFG;		// USCI_B0 clear transmit interrupt flag
			//		UARTBUFFER= UCB0RXBUF;						//UARTBUFFER todo
				}
				else
				{
				//	UARTBUFFER= UCB0RXBUF;
					Length--;
				}
				break;
			case READ_SYSTEM:
				if(Length == 1)
				{
					UCB0CTL1 		|= UCTXSTP;	// stop condition I2C
					*pReceive 		= UCB0TXBUF;
					IFG2 				&= 	~UCB0RXIFG;		// USCI_B0 clear transmit interrupt flag
				}
				else
				{
					Length	--;
					*pReceive = UCB0TXBUF;
					pReceive++;
					IFG2 					&= 	~UCB0TXIFG;		// USCI_B0 clear transmit interrupt flag

				}
				break;
			default:
				break;
		}
	}
	else
	if (IFG2 & UCB0TXIFG)
	{
		if (Addressing_Flag)
		{
			if(Address_length == 0)
			{
				Addressing_Flag		=	0;
				Address_length		=	2;

				switch (Target)
				{
					case WRITE_HISTORY:
						UCB0TXBUF		=	*pTransmit;
						pTransmit++;
						Length--;
						fnCheck_Page_Overflow();
						break;
					case WRITE_SYSTEM:
						UCB0TXBUF		=	*pTransmit;
						pTransmit++;
						Length--;
						break;
					case READ_HISTORY:
					case READ_SYSTEM:
						IFG2 					&= 	~UCB0TXIFG;		// USCI_B0 clear transmit interrupt flag
						IE2 						  = 	 UCB0RXIE;			// USCI_B0 receive interrupt enable
						UCB0CTL1			&=		~UCTR;			// disable transmit
						UCB0CTL1 			|= 	UCTXSTT;				// restart condition I2C receive
						break;
					default:
						break;
				}
			}
			else
			{
				UCB0TXBUF 		= 		*pAddress;
				IFG2 					&= 	~UCB0TXIFG;		// USCI_B0 clear transmit interrupt flag
				pAddress++;
				Address_length--;
			}
		}
		else
		{
			if ( Length == 1)
			{
				UCB0CTL1 |= UCTXSTP;	// stop condition I2C
				IFG2 &= ~UCB0TXIFG;		// USCI_B0 clear transmit interrupt flag
			}
			else
			{
				UCB0TXBUF = *pTransmit;
				pTransmit++;
				Length--;
				if(Target	==	WRITE_HISTORY)
				{
					fnCheck_Page_Overflow();
				}
			}
		}
	}
}

  • In your code, you enable NACK interrupt, but I don't see any ISR to handle it if it comes.

    I don't see main() too, so I don't know what you're calling when.

    Teh value of EEPROM is also unknown to me. From the screenshot, I can assume that it is 0x50.

    In the RX IFG, you do *pReceive= UCB0TXBUF. This must read RXBUF, of course.

    It is not necessary to clear RXIFG in the TX ISR and TX ISR in teh RX ISR. When UCTR is set, RXIFG is always clear and when it is clear, TXIFG will never be set.

    Unfortunately, you also didn't provide the System structure, so I don't knwo what the different uses resolve to.

    However, some things look somewhat strange:

    In fnRead(write)SystemValues, you set pReceive (pTransmit) to the address of System.CycleCount. But you set the length of the transfer to the length of System.
    Even if CycleCount is the first member of System in the struct declaration, it is not necessarily the first in memory. Why doN't you jsut give &System as start address if the transfer is the full length of System anyway?

    Yu end your transmission when Length ==1. Thsi way, you transfer one byte less than intended.
    If Length was 1 anyway, this would result in nothing read as it is the brak conditiona lready. Worse, since in WRITY_SYSTEM you send and do a Length--, an initial Length of 1 would result in 256 bytes written. You must check for Length==0 instead - and also check it before you send the first byte in the WRITE_SYSTEM case.

    Lars D said:
    Is there a way to determine if the NACK has been created by the stop condition or by the EEPROM?

    Yes. Teh EEPROM cannot send a NACK when you read form it. It may stop sending data (which results in 0xff read), but it cannot send a NACK. The only one who can send a NACK is the receiver of the data. In case of a mater read, the master. So for some reason, your master generates a stop after the second byte.

    One possible reason why it fails might be that you didn't declare Length (and all other values used in both, ISR and main) as volatile. It may be that the compiler doesn't write to lLength until the end of teh current function - which is long after the transfer is done. The compiler doesn't know that Length is 'magically' read by an ISR that is called out-of-order. And therefore Length may contain anything. Declaring a variable volatile tells the compiler to do an access to a variable exactly after the previous and before the next isntrucitons. This makes optimizations less effective but ensures that the data is written before the code continues and also ensures that data is read from memory if needed and not kept in a temporary register.

**Attention** This is a public forum