Other Parts Discussed in Thread: MSP-EXP430FR2433, MSP430F5329
//=======================================================================
#include "msp430.h"
#include "driverlib.h"
#define DCOFREQ 8000000
#define I2C_0_BASE (EUSCI_B0_BASE)
#define I2C_RECEIVE_BUFFER_SIZE (32)
uint8_t I2C_0_rxBuffer[I2C_RECEIVE_BUFFER_SIZE];
int8_t I2C_0_rxBytesRemaining = 0;
int8_t I2C_0_rxCnt = 0;
void setup(void)
{
EUSCI_B_I2C_initMasterParam I2C_0;
// SMCLK = MCLK = DCO = 4MHz
// ACL = 32kHz
CS_initClockSignal(CS_FLLREF, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
CS_initClockSignal(CS_MCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1);
CS_initClockSignal(CS_SMCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1);
CS_initFLL((DCOFREQ/1000), DCOFREQ/32768);
CS_clearAllOscFlagsWithTimeout(1000);
// I2C port mux selection
P1OUT = 0;
P1DIR |= BIT0 | BIT1 | BIT4 | BIT5 | BIT6;
P1SEL0 |= BIT2 | BIT3;
PM5CTL0 &= ~LOCKLPM5;
// I2C Setup
I2C_0.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
I2C_0.i2cClk = DCOFREQ;
I2C_0.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS;
I2C_0.byteCounterThreshold = 0;
I2C_0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
EUSCI_B_I2C_disable(I2C_0_BASE);
EUSCI_B_I2C_initMaster(I2C_0_BASE, &I2C_0);
EUSCI_B_I2C_enable(I2C_0_BASE);
__delay_cycles(8000000);
}
uint8_t I2C_0_readCmd(uint8_t slave, uint8_t cmd)
{
P1OUT |= BIT0 | BIT4 | BIT5 | BIT6;
// Set slave address and wait for bus
EUSCI_B_I2C_setSlaveAddress(I2C_0_BASE, slave);
EUSCI_B_I2C_clearInterrupt(I2C_0_BASE,
EUSCI_B_I2C_RECEIVE_INTERRUPT0 |\
EUSCI_B_I2C_TRANSMIT_INTERRUPT0 |\
EUSCI_B_I2C_STOP_INTERRUPT );
EUSCI_B_I2C_enableInterrupt(I2C_0_BASE,
EUSCI_B_I2C_RECEIVE_INTERRUPT0 |\
EUSCI_B_I2C_STOP_INTERRUPT );
I2C_0_rxBytesRemaining = 0;
// Write command to slave
EUSCI_B_I2C_setMode(I2C_0_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
EUSCI_B_I2C_masterSendMultiByteStart(I2C_0_BASE, cmd);
while(!(EUSCI_B_I2C_getInterruptStatus(I2C_0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0)))
{
if (EUSCI_B_I2C_getInterruptStatus(I2C_0_BASE, EUSCI_B_I2C_NAK_INTERRUPT))
{
return 0;
}
}
// Read response from slave
EUSCI_B_I2C_masterReceiveStart(I2C_0_BASE);
while (EUSCI_B_I2C_isBusBusy(I2C_0_BASE));
EUSCI_B_I2C_disableInterrupt(I2C_0_BASE,
EUSCI_B_I2C_RECEIVE_INTERRUPT0 |\
EUSCI_B_I2C_STOP_INTERRUPT );
P1OUT &= ~BIT0;
return I2C_0_rxCnt;
}
void run(void)
{
I2C_0_readCmd(0x0B, 0x02);
__no_operation();
__delay_cycles(1000000);
}
void main(void)
{
WDTCTL = WDTPW | WDTHOLD;
__enable_interrupt();
setup();
while(1)
{
run();
}
}
#pragma vector=USCI_B0_VECTOR
__interrupt void I2C_0_ISR(void)
{
uint8_t data;
P1OUT |= BIT1;
switch(__even_in_range(UCB0IV,0x1E))
{
case 0x00: break; // Vector 0: No interrupts break;
case 0x02: break; // Vector 2: ALIFG break;
case 0x04: break; // Vector 4: NACKIFG break;
case 0x06: break; // Vector 6: STT IFG break;
case 0x08:
P1OUT &= ~BIT5;
break; // Vector 8: STPIFG break;
case 0x0a: break; // Vector 10: RXIFG3 break;
case 0x0c: break; // Vector 14: TXIFG3 break;
case 0x0e: break; // Vector 16: RXIFG2 break;
case 0x10: break; // Vector 18: TXIFG2 break;
case 0x12: break; // Vector 20: RXIFG1 break;
case 0x14: break; // Vector 22: TXIFG1 break;
case 0x16: // Vector 24: RXIFG0 break;
// Receive byte
data = EUSCI_B_I2C_masterReceiveMultiByteNext(I2C_0_BASE);
// If this is the first byte (RX Length Invalid), then save the length to read
// and reset the receive counter to 0
if (I2C_0_rxBytesRemaining == 0x00)
{
I2C_0_rxBytesRemaining = data;
if (I2C_0_rxBytesRemaining > I2C_RECEIVE_BUFFER_SIZE)
{
I2C_0_rxBytesRemaining = I2C_RECEIVE_BUFFER_SIZE;
}
I2C_0_rxCnt = 0;
}
// If this is not the first byte, append the response to the RX
// buffer
else
{
I2C_0_rxBuffer[I2C_0_rxCnt++] = data;
I2C_0_rxBytesRemaining--;
}
// Send NACK and STOP on last byte coming in
if (I2C_0_rxBytesRemaining == 1)
{
P1OUT &= ~BIT4;
EUSCI_B_I2C_masterReceiveMultiByteStop(I2C_0_BASE);
}
break;
case 0x18: break; // Vector 26: TXIFG0 break;
case 0x1a: break; // Vector 28: BCNTIFG break;
case 0x1c: break; // Vector 30: clock low timeout break;
case 0x1e: break; // Vector 32: 9th bit break;
default: break;
}
P1OUT &= ~BIT1;
}
I got this code from Walter in the "MSP430F5329: How do you send a NAK in I2C SMBus Protocol"
post.
I thought I understood it and used it to write my code. I was not getting any SDA or SCL pin movement in my code. So I decided to start with Walter's "working code" and slowly migrate to my application.
In the main routine
void main(void)
{
WDTCTL = WDTPW | WDTHOLD;
__enable_interrupt();
setup();
while(1)
{
run();
}
}
I compile no warnings or errors.
When I single step it appears to go out of control just after the __enable_Interrupt(); when I try to step into the setup(); .
The Disassembly looks like a valid call to #setup
But it jumped to 00C400 __program_start
Why would it do that?
Is this a watchdog timer? Or another interrupt not handled?
I am confused. I am using the MSP-EXP430FR2433 with the IAR compiler.
Thanks,
Kip

