Part Number: MSP430FR6889
Im trying to run below code in Code composer studio where MSP430FR6889 is being used to read BMI160 z-axis accel readings and show it on console. Issue that Im facing is that sometimes everything works perfectly and I can read the accel values and can see them on console, but sometimes same exact code does not show readings on console. I can only see "MSP430: Flash/FRAM usage is 20840 bytes. RAM usage is 784 bytes." this message in console. Did anyone else also faced similar problem?
//Only Accel Woreking
#include "driverlib.h"
#include <gpio.h>
#include <intrinsics.h>
#include <msp430fr5xx_6xxgeneric.h>
#include <stdint.h>
#include <stdio.h>
#include <msp430.h>
//Address if the BMI160
#define SLAVE_ADDR 0x69
//Maximum I2C buffer size
#define MAX_BUFFER_SIZE 20
//Number of FFT samples
#define SAMPLES 10
//#define TimeStampSample 10
#pragma PERSISTENT(input)
int16_t input[SAMPLES] = {0}; //Store samples
volatile uint32_t cycleCount;
#define UP 0x0010 // Timer_A Up mode
#define CONTINUOUS 0x0020 // Timer_A Continuous mode
#define ACLK 0x0100 // Timer_A SMCLK source
#define DEVELOPMENT 0x5A80 // Stop the watchdog timer
#define BOUNCE_DELAY 0xA000 // Delay for Button Bounce
#define MS_10 100 // Approximate value to count for 10ms
#define SMCLK 0x0200 // Timer_A SMCLK source
void timer_init(void)
{
TA0CCTL0 = CCIE; //Enable counter interrupt
TA0CCR0 = 0; //Initially stop Timer by starting at 0
TA0CTL = TASSEL__SMCLK | MC__UP | ID__8; //Set clock source to ACLK, the count mode to Continuous, and the clock divider to 8
TA0EX0 = TAIDEX_7; //Set expansion clock divider to 8
TA1CCTL0 = CCIE; // TACCR0 interrupt enabled
TA1CCR0 = 0; // Set count target to 0 by default
// Set timer clock speed to 4.5898 ticks/s, or 16524 ticks/hour
TA1CTL = TASSEL__ACLK | MC__STOP | ID__8; //Set clock source to ACLK, the count mode to Continuous, and the clock divider to 8
TA1EX0 = TAIDEX_7; //Set expansion clock divider to 8
}
int delay(int count)
{
if(TA1CTL & TAIFG) // If Timer_1 is done counting
{
count = count-1; // Decrement count
TA1CTL = TA1CTL & (~TAIFG); // Reset Timer_1
}
return count; // Return the value of count
}
void UART_transmitString( char *pStr ) //Transmits a string over UART0
{
while( *pStr )
{
while(!(UCA0IFG&UCTXIFG));
UCA0TXBUF = *pStr;
pStr++;
}
}
typedef enum I2C_ModeEnum{
IDLE_MODE,
NACK_MODE,
TX_REG_ADDRESS_MODE,
RX_REG_ADDRESS_MODE,
TX_DATA_MODE,
RX_DATA_MODE,
SWITCH_TO_RX_MODE,
SWITHC_TO_TX_MODE,
TIMEOUT_MODE
} I2C_Mode;
I2C_Mode MasterMode = IDLE_MODE;
uint8_t TransmitRegAddr = 0; //Register address for transmission
uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0}; //Buffer for received values
uint8_t RXByteCtr = 0; //Count received bytes
uint8_t ReceiveIndex = 0; //Index of received data
uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0}; //Buffer for transmitted values
uint8_t TXByteCtr = 0; //Count transmitted bytes
uint8_t TransmitIndex = 0; //Index of transmitted data
void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count)
{
uint8_t copyIndex = 0;
for (copyIndex=0; copyIndex<count; copyIndex++)
{
dest[copyIndex]=source[copyIndex];
}
}
I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count)
{
//printf("R\n");
/* Initialize state machine */
MasterMode = TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;
RXByteCtr = count;
TXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;
/* Initialize slave address and interrupts */
UCB1I2CSA = dev_addr;
UCB1IFG &= ~(UCTXIFG + UCRXIFG); // Clear any pending interrupts
UCB1IE &= ~UCRXIE; // Disable RX interrupt
UCB1IE |= UCTXIE; // Enable TX interrupt
UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
// UCB1IE &= ~UCRXIE; // Disable RX interrupt
return MasterMode;
}
I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
{
/* Initialize state machine */
MasterMode = TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;
//Copy register data to TransmitBuffer
CopyArray(reg_data, TransmitBuffer, count);
TXByteCtr = count;
RXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;
/* Initialize slave address and interrupts */
UCB1I2CSA = dev_addr;
UCB1IFG &= ~(UCTXIFG + UCRXIFG); // Clear any pending interrupts
UCB1IE &= ~UCRXIE; // Disable RX interrupt
UCB1IE |= UCTXIE; // Enable TX interrupt
UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
//printf("W\n");
return MasterMode;
}
//******************************************************************************
// BMI160 Functions ************************************************************
//******************************************************************************
void bmi160_init(char FOC_axis)
{
uint8_t writeData[1];
//Read Chip ID, which is D1
I2C_Master_ReadReg(SLAVE_ADDR, 0x00, 1);
if(ReceiveBuffer[0] != 0xD1)
{
UART_transmitString(" Incorrect sensor chip ID ");
printf("Incorrect sensor chip ID\n");
}
//Configure the accelerometer
writeData[0]=0b00101000; //Set acc_us to 0 for off, and acc_bwp must then be 010. Set acc_odr to 1011(800Hz),1100(1600Hz),1000(100Hz),0001(25/32Hz)
I2C_Master_WriteReg(SLAVE_ADDR, 0x40, writeData, 1);
//Check if configuration worked
I2C_Master_ReadReg(SLAVE_ADDR, 0x40, 1);
if(ReceiveBuffer[0] != writeData[0])
{
UART_transmitString(" Accelerometer config failed ");
printf("Accelerometer config failed\n");
}
//Set the range of the accelerometer
writeData[0]=0b1000; //0b0011 for 2g, 0b0101 for 4g, 0b1000 for 8g
I2C_Master_WriteReg(SLAVE_ADDR, 0x41, writeData, 1);
//Check if range is set
I2C_Master_ReadReg(SLAVE_ADDR, 0x41, 1);
if(ReceiveBuffer[0] != writeData[0])
{
UART_transmitString(" Accelerometer range set failed ");
printf("Accelerometer range set failed\n");
}
//Set the Accelerometer to normal power mode
writeData[0] = 0x11;
I2C_Master_WriteReg(SLAVE_ADDR, 0x7E, writeData, 1);
//Read power mode status of sensors
I2C_Master_ReadReg(SLAVE_ADDR, 0x03, 1);
if(ReceiveBuffer[0] != 0x10)
{
UART_transmitString(" Accelerometer not on ");
printf("Accelerometer not on\n");
}
}
void initGPIO()
{
// I2C pins (P4.0 is SDA, P4.1 is SCL)
P4SEL1 |= BIT0 | BIT1;
P4SEL0 &= ~(BIT0 | BIT1);
// Configure P3.4 and P3.5 to UART (Primary, TX and RX respectively) for NeoCortec
P3SEL0 |= BIT4 | BIT5; // USCI_A1 UART operation
P3SEL1 &= ~(BIT4 | BIT5); // SEL1 is 0 and SEL0 is 1 for primary operation, inverse for secondary
// Configure P2.0 and P2.1 to UART (Primary, TX and RX respectively) for PC
P2SEL0 |= BIT0 | BIT1; // USCI_A0 UART operation
P2SEL1 &= ~(BIT0 | BIT1); // SEL1 is 0 and SEL0 is 1 for primary operation, inverse for secondary
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
__bis_SR_register(GIE);
}
void initClockTo16MHz()
{
FRCTL0 = FRCTLPW | NWAITS_1;
// Clock System Setup
CSCTL0_H = CSKEY_H; // Unlock CS registers
CSCTL1 = DCOFSEL_0; // Set DCO to 1MHz
// Set SMCLK = MCLK = DCO, ACLK = VLOCLK (9.4kHz)
CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;
// Per Device Errata set divider to 4 before changing frequency to
// prevent out of spec operation from overshoot transient
CSCTL3 = DIVA__4 | DIVS__4 | DIVM__4; // Set all corresponding clk sources to divide by 4 for errata
CSCTL1 = DCOFSEL_4 | DCORSEL; // Set DCO to 16MHz
// Delay by ~10us to let DCO settle. 60 cycles = 20 cycles buffer + (10us / (1/4MHz))
__delay_cycles(60);
CSCTL3 = DIVA__32 | DIVS__1 | DIVM__1; // Set ACLK to 239.75Hz, SMCLK to 16MHz, and MCLK to 16MHz
CSCTL0_H = 0; // Lock CS registers
}
void initI2C()
{
UCB1CTLW0 = UCSWRST; // Enable SW reset
UCB1CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSYNC; // I2C master mode, SMCLK
UCB1BRW = 160; // fSCL = ACLK/160 = ~100kHz
UCB1I2CSA = SLAVE_ADDR; // Slave Address
UCB1CTLW0 &= ~UCSWRST; // Clear SW reset, resume operation
UCB1IE |= UCNACKIE;
}
void UART_init(void)
{
// Configure USCI_A1 for UART mode
UCA1CTLW0 = UCSWRST; // Put eUSCI in reset
UCA1CTLW0 |= UCSSEL__SMCLK; // CLK = SMCLK
UCA1BR0 = 8; // Clock prescaler set to 8
UCA1BR1 = 0x00; // High byte empty, low byte is 8
UCA1MCTLW |= UCOS16 | UCBRF_10 | 0xF700; // Over-sampling on, first modulation register set to 10, second modulation register set to 0xF7 (247) for high byte, 0 for low byte
UCA1CTLW0 &= ~UCSWRST; // Initialize eUSCI
UCA1IE |= UCRXIE; // Enable USCI_A1 RX interrupt
// Configure USCI_A0 for UART mode
UCA0CTLW0 = UCSWRST; // Put eUSCI in reset
UCA0CTLW0 |= UCSSEL__SMCLK; // CLK = SMCLK
UCA0BR0 = 8; // Clock prescaler set to 8
UCA0BR1 = 0x00; // High byte empty, low byte is 8
UCA0MCTLW |= UCOS16 | UCBRF_10 | 0xF700; // Over-sampling on, first modulation register set to 10, second modulation register set to 0xF7 (247) for high byte, 0 for low byte
UCA0CTLW0 &= ~UCSWRST; // Initialize eUSCI
UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
}
int main(void)
{
WDTCTL = WDTPW; // Stop watchdog timer
//Initialize all peripherals
initClockTo16MHz();
initGPIO();
UART_init();
initI2C();
timer_init();
bmi160_init('Z');
TA0CTL = TA0CTL | (SMCLK + CONTINUOUS); // SMCLK: Counts faster than ACLK
TA0CCTL0 = CCIE; // Timer_0 interrupt
TA1CTL = TA1CTL | (ACLK + UP ); // Count up from 0 with ACLK
TA1CCR0 = MS_10; // Duration approximatley 10ms
_BIS_SR(GIE);
int i=0;
// Activate all interrupts
while(1)
{
printf("Reading samples\n");
//Read SAMPLES amount of data from the BMI160
for(i=0;i<SAMPLES;i++)
{
I2C_Master_ReadReg(SLAVE_ADDR, 0x16, 2); //Read the acceleration value from the BMI160 registers
input[i]= ReceiveBuffer[0] | (ReceiveBuffer[1] << 8); //Store the value in an array
printf("%d\n", (unsigned)(input[i]));
}
}
}
//I2C Interrupt
#pragma vector = USCI_B1_VECTOR
__interrupt void USCI_B1_ISR(void)
{
//Must read from UCB1RXBUF
uint8_t rx_val = 0;
switch(__even_in_range(UCB1IV, USCI_I2C_UCBIT9IFG))
{
case USCI_NONE: break; // Vector 0: No interrupts
case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG
case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG
UCB1CTLW0 |= UCTXSTT; // Re-send start if NACK
break;
case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG
case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG
case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3
case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3
case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2
case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2
case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1
case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1
case USCI_I2C_UCRXIFG0: // Vector 22: RXIFG0
rx_val = UCB1RXBUF;
if (RXByteCtr)
{
ReceiveBuffer[ReceiveIndex++] = rx_val;
RXByteCtr--;
}
if (RXByteCtr == 1)
{
UCB1CTLW0 |= UCTXSTP;
}
else if (RXByteCtr == 0)
{
UCB1IE &= ~UCRXIE;
MasterMode = IDLE_MODE;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
break;
case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0
switch (MasterMode)
{
case TX_REG_ADDRESS_MODE:
UCB1TXBUF = TransmitRegAddr;
if (RXByteCtr)
MasterMode = SWITCH_TO_RX_MODE; // Need to start receiving now
else
MasterMode = TX_DATA_MODE; // Continue to transmision with the data in Transmit Buffer
break;
case SWITCH_TO_RX_MODE:
UCB1IE |= UCRXIE; // Enable RX interrupt
UCB1IE &= ~UCTXIE; // Disable TX interrupt
UCB1CTLW0 &= ~UCTR; // Switch to receiver
MasterMode = RX_DATA_MODE; // State state is to receive data
UCB1CTLW0 |= UCTXSTT; // Send repeated start
if (RXByteCtr == 1)
{
//Must send stop since this is the N-1 byte
while((UCB1CTLW0 & UCTXSTT));
UCB1CTLW0 |= UCTXSTP; // Send stop condition
}
break;
case TX_DATA_MODE:
if (TXByteCtr)
{
UCB1TXBUF = TransmitBuffer[TransmitIndex++];
TXByteCtr--;
}
else
{
//Done with transmission
UCB1CTLW0 |= UCTXSTP; // Send stop condition
MasterMode = IDLE_MODE;
UCB1IE &= ~UCTXIE; // disable TX interrupt
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
break;
default:
__no_operation();
break;
}
break;
default: break;
}
}
// Timer_0 Interrupt Service Routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0 (void)
{
TA0CTL = TA0CTL & (~TAIFG); // Reset Timer_0 so it keeps counting
}
