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.

RF430CL330hH problem with INTO only firing once

Guru 18395 points
Other Parts Discussed in Thread: RF430CL330H, MSP430FR5969

Good afternoon,

I've adapted the code from a TI application note, concretely tidc487 for my MSP430FR5969 to work with RF430CL330H boosterpack. Some pins had to be changed for i2C to work but it works.

The question is I'm able to see my INTO interrupt firing once. I configure this interrupt to fires upon the tag read. I get close to the tag with my phone, I recover my "hello world" message and my LED blinks. I remove my phone from the area next to the tag. The next time I approach my phone, I can recover the same "hello world" message. However, my ISR does not fire.

I attach the code next. I've tried to keep it short.

file main.c

void main (void)
{
	volatile unsigned int test = 0;
	volatile unsigned int flags = 0;
	//unsigned char read_data[200];

	MSP430_Init();

	Low_Power_Delay_ms(20);

	while(!(Read_Register(STATUS_REG) & READY)){	//wait until READY bit has been set
		Low_Power_Delay_ms(1);
	}

	/****************************************************************************/
    /* Errata Fix : Unresponsive RF - recommended firmware                      */
    /****************************************************************************/
	{
//		//Please implement this fix as given in this block.  It is important that
//		//no line be removed or changed.
		unsigned int version;
		version = Read_Register(VERSION_REG);  // read the version register.  The fix changes based on what version of the
//											   // RF430 is being used.  Version C and D have the issue.  Next versions are
//											   // expected to have this issue corrected
//											   // Ver C = 0x0101, Ver D = 0x0201
		if (version == 0x0101 || version == 0x0201)
		{
			Write_Register(0xFFE0, 0x004E);
			Write_Register(0xFFFE, 0x0080);
			if (version == 0x0101)
			{  // Ver C
				Write_Register(0x2a98, 0x0650);
			}
			else
			{	// Ver D
				Write_Register(0x2a6e, 0x0650);
			}
			Write_Register(0x2814, 0);
			Write_Register(0xFFE0, 0);
		}
		//Upon exit of this block, the control register is set to 0x0
	}

	// check to see if the memory contents are valid, if not put in a our default NDEF message.
	if(FRAM_Message[0] != 0xD2)
	{
		memcpy(FRAM_Message, RF430_DEFAULT_DATA , 48);
	}


    while (1)
    {
    	Low_Power_Delay_ms(1);

    	Update_RF430();

		Low_Power_Delay_ms(20);

		while(!into_fired) {}
		into_fired = 0;


//		while(!(Read_Register(STATUS_REG) & READY)); //wait until READY bit has been set
    }
}

void Low_Power_Delay_ms(unsigned int ms){
	TA1CTL |= TACLR;

	TA1CCR0 = ms*10;                  // leave time for the RF430CL33H to get itself initialized, 200=20ms
	TA1CTL |= MC__UP;                 // ACLK, up mode
	__bis_SR_register(LPM3_bits + GIE);
	TA1CTL |= MC__STOP;
}

void MSP430_Init(){
	WDTCTL = WDTPW + WDTHOLD;		// Turn off Watch Dog
	
	PMMCTL0 = PMMPW;				// Open PMM Module
	PM5CTL0 &= ~LOCKLPM5;			// Clear locked IO Pins

	CSCTL0_H = 0xA5;
	CSCTL1 |= DCOFSEL0 + DCOFSEL1;          // Set max. DCO setting = 8MHz
	CSCTL2 = SELA_1 + SELS_3 + SELM_3;      // set ACLK = VLOCLK = 10kHz
	CSCTL3 = DIVA_0 + DIVS_0 + DIVM_0;      // set VLOCLK / 1

	//**** Drive unused pins low, for lowest power  ***//
	P1DIR = 0xFF;
	P2DIR = 0xFF;
	P3DIR = 0xFF;
	P4DIR = 0xFF;

	P1OUT = 0x00;
	P2OUT = 0x00;
	P3OUT = 0x00;
	P4OUT = 0x00;
	//*************************************************//

	Rf430_I2C_Init();

	// Configure pins for I2C
	PORT_I2C_SEL0 &= ~(SCL + SDA);
	PORT_I2C_SEL1 |= SCL + SDA;

	Rf430_I2C_Init();

	// DRIVE CS Low to indicate I2C Mode
	PORT_CS_SEL0 |= PORT_CS_PIN;
	PORT_CS_DIR |= PORT_CS_PIN;
	PORT_CS &= ~PORT_CS_PIN;

	//RST RF430 (in case board is still powered but the MSP430 reset for some reason - MSP430 RST button pushed for example)
	PORT_RST_SEL0 &= ~RST;
	PORT_RST_SEL1 &= ~RST;
	PORT_RST_OUT &= ~RST; 				//RF430CL330H device in reset
	PORT_RST_DIR |= RST;
	__delay_cycles(100);
	PORT_RST_OUT |= RST; 				//release the RF430CL330H

	//configure LEDs
	PORT_LED_SEL0 &= ~(LED5 + LED6); 	//GPIO
	PORT_LED_SEL1 &= ~(LED5 + LED6); 	//GPIO
	PORT_LED_DIR |= LED5 + LED6; 		//output
	PORT_LED_OUT &= ~(LED5 + LED6); 	//start out off

	// DRIVE CS Low to indicate I2C Mode
	PORT_CS_SEL0 |= PORT_CS_PIN;
	PORT_CS_DIR |= PORT_CS_PIN;
	PORT_CS &= ~PORT_CS_PIN;

	//configure pin for INTO interrupts
	PORT_INTO_SEL0 &= ~INTO; 		//GPIO
	PORT_INTO_SEL1 &= ~INTO; 		//GPIO
	PORT_INTO_DIR &= ~INTO; 		//input
	PORT_INTO_OUT |= INTO; 			//output high for pullup
	PORT_INTO_REN |= INTO; 			//internal pullup resistor
	PORT_INTO_IFG &= ~INTO; 		//clear interrupt flag
	PORT_INTO_IES |= INTO; 			//fire interrupt on high-to-low transition since INTO is setup active low

	//~ INT0 pin
	P1IE |= BIT4;

	Timer_Init();
}

// ISR
#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
	//INTO interrupt fired
	if(PORT_INTO_IFG & INTO)
	{
		into_fired = 1;

		//PORT_INTO_IE &= ~INTO; //disable INTO
		PORT_INTO_IFG &= ~INTO; //clear interrupt flag
		PORT_LED_OUT ^= BIT6;

		__bic_SR_register_on_exit(LPM3_bits); //wake up to handle INTO
	}
}

/*****************Timer Functions*********************/
void Timer_Init(){
	TA1CCTL0 = CCIE;                          // TACCR0 interrupt enabled
	TA1CCR0 = 20000;
	TA1CTL = TASSEL_1;                 // ACLK, up mode
}

// Timer A1 interrupt service routine
#pragma vector = TIMER1_A0_VECTOR
__interrupt void Timer1_A0_ISR(void)
{
    TA1CTL &= ~(MC_3);		//stops the Timer
	LPM3_EXIT;
}
/******************************************************/

file RF430.h

long temp;


void Rf430_I2C_Init(){
	//configure eUSCI for I2C
	UCB0CTL1 |= UCSWRST;	            			//Software reset enabled
	UCB0CTLW0 |= UCMODE_3  + UCMST + UCSYNC + UCTR;	//I2C mode, Master mode, sync, transmitter
	UCB0CTLW0 |= UCSSEL_2;                    		// SMCLK = 8MHz

	UCB0BRW = 30; 						// Baudrate = SMLK/40 = 200kHz

	UCB0I2CSA  = 0x0028;				//slave address - determined by pins E0, E1, and E2 on the RF430CL330H
	UCB0CTL1  &= ~UCSWRST;
}

void Update_RF430(void)
{
	temp = (RF_ENABLE | INT_ENABLE);
	Rf430_I2C_Init();

	Write_Continuous(26, &FRAM_Message[26], 23);	// Writing Record and NDEF Message to RF430

	Write_Register(INT_ENABLE_REG, EOR_INT_ENABLE);
	Write_Register(CONTROL_REG, temp);			// Enable RF
	Write_Register(INT_FLAG_REG, 0);
}


// Reads the register at reg_addr, returns the result
unsigned int Read_Register(unsigned int reg_addr)
{
	TxAddr[0] = reg_addr >> 8; 		// MSB of address
	TxAddr[1] = reg_addr & 0xFF; 	// LSB of address

	UCB0CTLW1 = UCASTP_1;
	UCB0TBCNT = 0x0002;
	UCB0CTL1  &= ~UCSWRST;
	UCB0CTL1 |= UCTXSTT + UCTR;		// Start i2c write operation
	while(!(UCB0IFG & UCTXIFG0));
	UCB0TXBUF = TxAddr[0];
	while(!(UCB0IFG & UCTXIFG0));
	UCB0TXBUF = TxAddr[1];
	while(!(UCB0IFG & UCBCNTIFG));
	UCB0CTL1 &= ~UCTR; 				// I2C read operation
	UCB0CTL1 |= UCTXSTT; 			// Repeated start
	while(!(UCB0IFG & UCRXIFG0));
	RxData[0] = UCB0RXBUF;
	UCB0CTLW0 |= UCTXSTP; 			// Send stop after next RX
	while(!(UCB0IFG & UCRXIFG0));
	RxData[1] = UCB0RXBUF;
	while (!(UCB0IFG & UCSTPIFG));  // Ensure stop condition got sent
	UCB0CTL1  |= UCSWRST;

	return RxData[1] << 8 | RxData[0];
}


//Continuous read data_length bytes and store in the area "read_data"
void Read_Continuous(unsigned int reg_addr, unsigned char* read_data, unsigned int data_length)
{
	unsigned int i;

	TxAddr[0] = reg_addr >> 8; 		// MSB of address
	TxAddr[1] = reg_addr & 0xFF; 	// LSB of address


	UCB0CTLW1 = UCASTP_1;
	UCB0TBCNT = 0x0002;
	UCB0CTL1  &= ~UCSWRST;
	UCB0CTL1 |= UCTXSTT + UCTR;		// Start i2c write operation

		while(!(UCB0IFG & UCTXIFG0));
		UCB0TXBUF = TxAddr[0];
		while(!(UCB0IFG & UCTXIFG0));
		UCB0TXBUF = TxAddr[1];
		while(!(UCB0IFG & UCBCNTIFG));
		UCB0CTL1 &= ~UCTR; 			//i2c read operation
		UCB0CTL1 |= UCTXSTT; 		//repeated start
		while(!(UCB0IFG & UCRXIFG0));

	for(i = 0; i < data_length-1; i++)
	{
		while(!(UCB0IFG & UCRXIFG0));
		read_data[i] = UCB0RXBUF;
		if(i == data_length-1)
			UCB0CTL1 |= UCTXSTP; 	//send stop after next RX
	}

	UCB0CTLW0 |= UCTXSTP; 			//send stop after next RX
	while(!(UCB0IFG & UCRXIFG0));
	read_data[i] = UCB0RXBUF;
	while (!(UCB0IFG & UCSTPIFG)); 	// Ensure stop condition got sent
	UCB0CTL1  |= UCSWRST;
}

//writes the register at reg_addr with value
void Write_Register(unsigned int reg_addr, unsigned int value)
{
	TxAddr[0] = reg_addr >> 8; 		// MSB of address
	TxAddr[1] = reg_addr & 0xFF; 	// LSB of address
	TxData[0] = value >> 8;
	TxData[1] = value & 0xFF;

	UCB0CTLW1 = UCASTP_1;
	UCB0TBCNT = 0x0004;
	UCB0CTL1  &= ~UCSWRST;
	UCB0CTL1 |= UCTXSTT + UCTR;		// Start i2c write operation
	//write the address
	while(!(UCB0IFG & UCTXIFG0));
	UCB0TXBUF = TxAddr[0];
	while(!(UCB0IFG & UCTXIFG0));
	UCB0TXBUF = TxAddr[1];
	//write the data
	while(!(UCB0IFG & UCTXIFG0));
	//UCB0TXBUF = TxData[0];
	UCB0TXBUF = TxData[1];
	while(!(UCB0IFG & UCTXIFG0));
	//UCB0TXBUF = TxData[1];
	UCB0TXBUF = TxData[0];
	while (!(UCB0IFG & UCBCNTIFG));
	UCB0CTL1 |= UCTXSTP;
	while (!(UCB0IFG & UCSTPIFG)); 	// Ensure stop condition got sent
	UCB0CTL1  |= UCSWRST;

}

//writes the register at reg_addr and incrementing addresses with the data at "write_data" of length data_length
void Write_Continuous(unsigned int reg_addr, unsigned char* write_data, unsigned int data_length)
{
	unsigned int i;

	TxAddr[0] = reg_addr >> 8; 		//MSB of address
	TxAddr[1] = reg_addr & 0xFF; 	//LSB of address

	UCB0CTLW1 = UCASTP_1;
	UCB0TBCNT = data_length; 		//data_length is in words, TBCNT is in bytes, so multiply by 2
	UCB0CTL1  &= ~UCSWRST;
	UCB0CTL1 |= UCTXSTT + UCTR;		//start i2c write operation
	//write the address
	while(!(UCB0IFG & UCTXIFG0));
	UCB0TXBUF = TxAddr[0];
	while(!(UCB0IFG & UCTXIFG0));
	UCB0TXBUF = TxAddr[1];
	//write the data
	for(i = 0; i < data_length; i++)
	{
		while(!(UCB0IFG & UCTXIFG0));
		UCB0TXBUF = write_data[i];
	}

	while(!(UCB0IFG & UCTXIFG0));
	while (!(UCB0IFG & UCBCNTIFG));
	UCB0CTL1 |= UCTXSTP;
	while (!(UCB0IFG & UCSTPIFG));     // Ensure stop condition got sent
	UCB0CTL1  |= UCSWRST;

}

Any idea of what can I be doing wrong? Please let me know :)