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.

MSP430F2013 interrupts: SD16_A conflict with USI i2c, why?

Hi,

My USI i2c LCD code does not want to work properly if SD16_A interrupt is not disabled.

These 2 lines do not work (see in the code below)
                 LCD_Cmd(0xC0);                    // Set Line2 (position for output)
                 printf ("%u ",SD16MEM0);     // SD16MEMO
      and LCD freezed with last message [Ready for start!]

The code works fine if I disable SD16_A interrupt before USI i2C LCD output.
(just uncomment 2 lines ### inside while (1) cycle)

Could you explain, why there is a conflict between SD16_A and USI interrupts?

/******************************************************************************
 * 				SD16_A + I2C output (23 Feb 2015)
******************************************************************************/
//	BASED ON TI SAMPLE APPLICATION:
//******************************************************************************
//
//
//  MSP430F20x3 Demo - SD16A, Sample A1+ Continuously, Set P1.0 if > 0.3V
//
//  Description: A continuous single-ended sample is made on A1+ using internal
//  VRef Unipolar output format used.
//  Inside of SD16 ISR, if A1 > 1/2VRef (0.3V), P1.0 set, else reset.
//  ACLK = n/a, MCLK = SMCLK = SD16CLK = default DCO
//
//                MSP430F20x3
//             ------------------
//         /|\|              XIN|-
//          | |                 |
//          --|RST          XOUT|-
//            |                 |
//    Vin+ -->|A2+ P1.4 (4)     |
//            |A2- = VSS    P1.0|-->LED
//            |                 |
//
//  M. Buccini / L. Westlund
//  Texas Instruments Inc.
//  October 2005
//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.40A
//******************************************************************************


#include	"msp430f2013.h"
#include	"stdbool.h"



// Function Definitions

void Master_Transmit(void);					// DRIVER I2C LCD WX1602
void Master_Recieve(void);

void Setup_USI_Master_TX(void);
void Setup_USI_Master_RX(void);

void Data_TX (void);
void Data_RX (void);

void LCD_Init(void);								// FRIVER LCD
void LCD_Cmd(unsigned char sym);
void LCD_Print(unsigned char sym);
void LCD_Clear(void);
void Clear_Line1  (void);
void Clear_Line2  (void);
void  printf(char *, ...);
void 	putc	(unsigned char c);
unsigned char number_of_bytes = 1;  

// Variables

unsigned char *MST_Data;
const unsigned char Slave_Address = 0x74;  //WX1602 
int I2C_State, Bytecount, Transmit_i2c = 0;     // State variable
unsigned int i;	// for loop variable

// LCD specific commands

unsigned char init[12] = {0,0,0x35,0x02,0x04,0x08,0x12,0x41,0x98,0x34,0x06,0x0C};  
unsigned char symbol[3] = {0x40,0x40,0x35};
unsigned char command[3] = {0,0,0xC0};
unsigned char clear[3] = {0,0,0x02}; 

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

void main(void)
{
	WDTCTL = WDTPW + WDTHOLD;		// Stop WDT
	BCSCTL1 = CALBC1_1MHZ;			// Set range
	DCOCTL = CALDCO_1MHZ;				// SMCLK = DCO = 1MHz  

	
                               // Hello world!
	P1DIR |= BIT0;			         // LED1 (red)
	P1OUT |= BIT0;               // Turn on RED LED at P1.0
	__delay_cycles (400000);     // Delay	
	P1OUT &= ~BIT0;              // Turn off RED LED at P1.0
	__delay_cycles (100000);     // Delay	
 
	
  LCD_Init();
	printf ("23.02.2015 ");	
	LCD_Cmd(0xC0);                // Set Line 2
	printf ("Sigma-Delta ADC ");	
	__delay_cycles (500000);      // just delay	
	
	
   
                                       // SD16_A Init
                                       // ===========
	SD16CTL = SD16REFON + SD16SSEL_1;    // 1.2V ref, SMCLK
  SD16INCTL0 = SD16INCH_2;             // P1.4	A2+/-
  SD16CCTL0 =  SD16UNI;                // 256OSR, unipolar, interrupt enable
	SD16CCTL0 |= SD16OSR_1024;           // over sample rate is 1024
  SD16CCTL0 |= SD16IE;                 // interrupt enable
	__delay_cycles (50000);              // Delay for 1.2V ref startup


	
    Clear_Line2 ();
    printf ("Ready for start!");	
    __delay_cycles (800000);              // just delay 0.8 sec

		
	
	while(1)
		
	{

//  SD16CCTL0 |= SD16IE;               // ### interrupt enable
		
		
  SD16CCTL0 |= SD16SC;                 // Set bit to start conversion
  __bis_SR_register(LPM0_bits + GIE);  // wait for SD16_A interrupt
	
		
																// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
																// IF WE DO NOT DISABLE SD16_A INTERRUPT
																// WE CANT SEE ANYTHING NEW ON LCD - WHY?
																// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!	
//	  SD16CCTL0 &= ~SD16IE;       // ### interrupt disable

	
		LCD_Cmd(0xC0);		                  // Set Line2 (position for output)
		printf	("%u          ",SD16MEM0);  // SD16MEMO 

		P1OUT |= BIT0;             // Turn on RED LED at P1.0
		__delay_cycles (100000);   // Delay	for LED indication
		P1OUT &= ~BIT0;            // Turn off RED LED at P1.0
		__delay_cycles (300000);   // Delay	for LCD indication
	}

}



//******************************************************************************
// 						DRIVER I2C LCD WX1602
//******************************************************************************


void LCD_Init(void)
{  
														// LCD PORT INIT
														// -------------	
	
  P1OUT |= BIT7+BIT6+BIT2; // P1.6 & P1.7 - I2C, P1.2-Power-On-Rest 
  P1REN |= BIT7+BIT6;      // P1.6 (blue wire) & P1.7 (green wire) Pullups
  P1DIR |= BIT7+BIT6+BIT2; // LCD pins as outputs
  __delay_cycles (100000); // Delay for LCD POR
  P1OUT &= ~BIT2;          // finish LCD power on reset  (P1.2)
  __delay_cycles (1000);   // Delay

                          // send initializatuion string into LCD
  number_of_bytes = 11;
  MST_Data = init;        // pointer to chunk of bytes
  Setup_USI_Master_TX(); 	// I2C to tx mode
  USICTL1 |= USIIFG;      // Set flag and start communication
  LPM0;                   // CPU off, await USI interrupt
  __delay_cycles (1000);	
}

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

void LCD_Cmd(unsigned char sym)
{
  command[2] = sym;					// change dummy byte to char for output
  number_of_bytes = 2;
  MST_Data = command;
  Setup_USI_Master_TX();
  USICTL1 |= USIIFG;        // Set flag and start communication
  LPM0;                     // CPU off, await USI interrupt
  __delay_cycles (1000);    // Delay
}


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

void LCD_Print(unsigned char sym)
{  
  symbol[2] = (sym ^ 0x80);	// because of [char table not equal to HD44780]
  number_of_bytes = 2;
  MST_Data = symbol;
  Setup_USI_Master_TX();
  USICTL1 |= USIIFG;        // Set flag and start communication
  LPM0;                     // CPU off, await USI interrupt
}

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

void LCD_Clear(void)

{
  number_of_bytes = 2;
  MST_Data = clear;
  
  Setup_USI_Master_TX();
  USICTL1 |= USIIFG;                      // Set flag and start communication
  LPM0;                                   // CPU off, await USI interrupt
	
    	for( i = 0; i < 80; i++ )
		{
			  LCD_Print(' ');
  	}

}

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

void Clear_Line2  (void)

{
	
	LCD_Cmd(0xC0);		// Set Line2

	for( i = 0; i < 16; i++ )
		{
		  LCD_Print(' ');
  		}

		LCD_Cmd(0xC0);		// Set Line2

}

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

void Clear_Line1  (void)

{
	LCD_Cmd(0x80);		// Set Line1
	for( i = 0; i < 16; i++ )
	{
	  LCD_Print(' ');
  	}
	LCD_Cmd(0x80);		// Set Line1

}




/******************************************************
// SD16_A interrupt
******************************************************/

#pragma vector = SD16_VECTOR
__interrupt void SD16ISR(void)

{
	SD16CCTL0 &= ~SD16IFG ;
	__low_power_mode_off_on_exit () ; 
}


/******************************************************
// USI interrupt service routine
// Data Transmit : state 0 -> 2 -> 4 -> 10 -> 12 -> 14
// Data Recieve  : state 0 -> 2 -> 4 -> 6 -> 8 -> 14
******************************************************/

#pragma vector = USI_VECTOR

__interrupt void USI_TXRX (void)

{
  switch(__even_in_range(I2C_State,14))
    {
      case 0: // Generate Start Condition & send address to slave
              Bytecount = 0;
              USISRL = 0x00;                // Generate Start Condition...
              USICTL0 |= USIGE+USIOE;
              USICTL0 &= ~USIGE;
              if (Transmit_i2c == 1){
                USISRL = Slave_Address;     // Address is 0x74 << 1 bit + 0 (rw)
																		
              }
               if (Transmit_i2c == 0){
               USISRL = Slave_Address+1;   	// Address is 0x74 << 1 bit 
							 											
               }
              USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, TX Address
              I2C_State = 2;                // next state: rcv address (N)Ack
              break;

      case 2: // Receive Address Ack/Nack bit
              USICTL0 &= ~USIOE;            // SDA = input
              USICNT |= 0x01;               // Bit counter=1, receive (N)Ack bit
              I2C_State = 4;                // Go to next state: check (N)Ack
              break;

      case 4: // Process Address Ack/Nack & handle data TX
             
 if(Transmit_i2c == 1)
 
	{
              USICTL0 |= USIOE;             // SDA = output
              if (USISRL & 0x01)            // If Nack received...
              { // Send stop...
                USISRL = 0x00;
                USICNT |=  0x01;            // Bit counter=1, SCL high, SDA low
                I2C_State = 14;             // Go to next state: generate Stop
              }
              else
              { // Ack received, TX data to slave...
              MST_Data = MST_Data + 1;  
		USISRL = *MST_Data;
              USICNT |=  0x08;            // Bit counter = 8, start TX
              I2C_State = 10;             // next state: receive data (N)Ack
              Bytecount++;
              break;
              }
							
 	} 
 
 		if(Transmit_i2c == 0)
 
				{

           if (USISRL & 0x01)            // If Nack received
						 
              { // Prep Stop Condition
                USICTL0 |= USIOE;
                USISRL = 0x00;
                USICNT |=  0x01;            // Bit counter= 1, SCL high, SDA low
                I2C_State = 8;              // Go to next state: generate Stop
              }
					 
              else{ Data_RX();}             // Ack received

		}
              break;

case 6: // Send Data Ack/Nack bit      
              USICTL0 |= USIOE;             // SDA = output
              if (Bytecount <= number_of_bytes-2)
              {                             // If this is not the last byte
                USISRL = 0x00;              // Send Ack
                I2C_State = 4;              // Go to next state: data/rcv again
                Bytecount++;
              }
                
              else //last byte: send NACK
              
		{
                USISRL = 0xFF;              // Send NAck
                I2C_State = 8;              // stop condition
              }
							
              USICNT |= 0x01;               // Bit counter = 1, send (N)Ack bit
              break;

      case 8: // Prep Stop Condition
              USICTL0 |= USIOE;             // SDA = output
              USISRL = 0x00;
              USICNT |=  0x01;              // Bit counter= 1, SCL high, SDA low
              I2C_State = 14;               // Go to next state: generate Stop
              break;

      case 10: // Receive Data Ack/Nack bit
              USICTL0 &= ~USIOE;            // SDA = input
              USICNT |= 0x01;               // Bit counter = 1, receive (N)Ack bit
              I2C_State = 12;               // Go to next state: check (N)Ack
              break;

      case 12: // Process Data Ack/Nack & send Stop
              USICTL0 |= USIOE;
              if (Bytecount == number_of_bytes)		// If last byte
		{
              		USISRL = 0x00;
              		I2C_State = 14;   // Go to next state: generate Stop
              		USICNT |=  0x01;  // set count=1 to trigger next state
		}  
							
              else
								
		{
                	Data_TX();                  // TX byte
              	}
							
              break;

      case 14:// Generate Stop Condition
              USISRL = 0x0FF;               // USISRL = 1 to release SDA
              USICTL0 |= USIGE;             // Transparent latch enabled
              USICTL0 &= ~(USIGE+USIOE);    // Latch/SDA output disabled
              I2C_State = 0;                // Reset state machine for next xmt
              LPM0_EXIT;                    // Exit active for next transfer
              break;
    }

  USICTL1 &= ~USIIFG;                     // Clear pending flag
}

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

void Data_TX (void)

{
  MST_Data = MST_Data + 1;
  USISRL = *MST_Data;          // Load data byte
  USICNT |=  0x08;              // Bit counter = 8, start TX
  I2C_State = 10;               // next state: receive data (N)Ack
  Bytecount++;
}

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

void Data_RX (void)

{
  USICTL0 &= ~USIOE;                  // SDA = input --> redundant
  USICNT |=  0x08;                    // Bit counter = 8, RX data
  I2C_State = 6;                      // Next state: Test data and (N)Ack
}

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

void Setup_USI_Master_TX (void)

{ 
  __disable_interrupt();
  Bytecount = 0;
  Transmit_i2c = 1;
  USICTL0 = USIPE6+USIPE7+USIMST+USISWRST;  // Port & USI mode setup
  USICTL1 = USII2C+USIIE;                   // Enable I2C mode & USI interrupt
  USICKCTL = USIDIV_7+USISSEL_2+USICKPL;    // USI clk: SCL = SMCLK/128
  USICNT |= USIIFGCC;                       // Disable automatic clear control
  USICTL0 &= ~USISWRST;                     // Enable USI
  USICTL1 &= ~USIIFG;                       // Clear pending flag
  __enable_interrupt();
}

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

void Setup_USI_Master_RX (void)

{ 
  __disable_interrupt();
  Bytecount = 0;
  Transmit_i2c = 0;
  USICTL0 = USIPE6+USIPE7+USIMST+USISWRST;  // Port & USI mode setup
  USICTL1 = USII2C+USIIE;                   // Enable I2C mode & USI interrupt
  USICKCTL = USIDIV_7+USISSEL_2+USICKPL;    // USI clks: SCL = SMCLK/128
  USICNT |= USIIFGCC;                       // Disable automatic clear control
  USICTL0 &= ~USISWRST;                     // Enable USI
  USICTL1 &= ~USIIFG;                       // Clear pending flag
  __enable_interrupt();
}

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

void Master_Transmit(void)

{
  Setup_USI_Master_TX();
  USICTL1 |= USIIFG;                      // Set flag and start communication
  LPM0;                                   // CPU off, await USI interrupt
}

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

void Master_Recieve(void)

{
  Setup_USI_Master_RX();
  USICTL1 |= USIIFG;                        // Set flag and start communication
  LPM0;                                     // CPU off, await USI interrupt
}


/*****************************************************************
* puts() is used by printf() to display or send a string.
* This function determines where printf prints to.
* It could send a string out over UART, another option could be
* to display the string on an LCD display.
 *****************************************************************/

void puts(char *s)
{
	char c;

	// Loops through each character in string 's'
	while (c = *s++)
		{
			LCD_Print (c);	
		}
}
/****************************************************************
* putc() is used by printf() to display or send a character.
* This function determines where printf prints to. 
 ***************************************************************/

void putc (unsigned char c)
{
	LCD_Print (c);
}

  • You are asking quite a lot of your tiny MCU.
    What happens when you increase Stack size?
  • Hi, I would like to try, but I don't know how to increase Stack size in IAR.
  • Sorry me also, must wait for an IAR specialist.

    But in the main time you can do this (don’t know if the symbols in IAR are equal);

    To easily check stack-use add the following lines to your program, immediately at the begin of main and just after stopping the watchdog. Let the program run a while and stop it, check the stack contents with the memory-browser, if all A5 are gone you can be sure you have a stack overflow and needs to increase stack-size.

    	extern unsigned int _stack;
    	extern unsigned int __STACK_END;
    	unsigned int* p;
    
    	p = &_stack;
    	while (p < (&__STACK_END -3))
    	{
    		*p = 0xA5A5;
    		p++;
    	}
    

     

**Attention** This is a public forum