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.

MSP430 TrxEB Accelerometer

Other Parts Discussed in Thread: MSP430F2274, MSP430F5438A, MSP430WARE

Hi!
I am interested in reading values from the Accelerometer that is in the TrxEB and send them continuosly by SPI to the Raspberry Pi. I've been reading the User's guide of the board and it says that the accelerometer uses the SPI1 interface with:
P9.0 --> SCLK
P9.4 --> MOSI
P9.5 -->MISO
P8.7 -->CS
and the interrupt line is in P2.0 (ACC_INT) but I don't know how can I do what I want. Where can I find the register/s where is store the value/s of the accelerometer? What would be the interrupt for the accelerometer? is there any sample code for that? If I get the register to read the value of the accelerometer I just need to copy that value to the transmitter buffer of the SPI?
Thanks in advance!

  • The accelerometer on the TrxEB is a CMA3000-D01 produced by Murata. There is a pdf available from Murata that shows example code for how to read data from the accel. using an MSP430F2274 (here: http://www.muratamems.fi/sites/default/files/documents/tn80_spi_and_i2c_communication_with_cma3000-d1_rev_0.4.pdf). This should give you a good starting point for what you will need to do to use the accelerometer. You will need to change the example code some for the different MSP430 on the TrxEB.

    -Matt

  • Hello,

    I've been reading the code and modifying it to leave it like that:

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

    //******************************************************************************
    // MSP430F2274 Demo-USCI_B0, SPI Interface to CMA3000 Acceleration Sensor
    //
    // Uses Texas Instruments eZ430-RF2500 Development Tool with Murata Adapter PCB
    //VTI29631A0. Wireless connection not used.
    //******************************************************************************

    // CONSTANTS

    #define XTAL 16000000L
    #define TICKSPERMS (XTAL / 1000 / 5-1)
    #define TICKSPERUS (TICKSPERMS / 1000)

    // LIBRARIES

    #include "msp430f5438a.h"

    // PORT DEFINITIONS

    #define PORT_INT_IN     P2IN
    #define PORT_INT_OUT    P2OUT
    #define PORT_INT_DIR    P2DIR
    #define PORT_INT_IE     P2IE
    #define PORT_INT_IES    P2IES
    #define PORT_INT_IFG    P2IFG
    #define PORT_INT_VECTOR PORT2_VECTOR
    #define PORT_CSB_OUT    P4OUT
    #define PORT_CSB_DIR    P4DIR
    #define PORT_SPI_DIR    P3DIR
    #define PORT_SPI_SEL    P3SEL

    // REGISTER AND FLAG DEFINITIONS

    #define TX_BUFFER       UCB0TXBUF
    #define RX_BUFFER       UCB0RXBUF
    #define IRQ_REG         UCB0IFG
    #define RX_IFG          UCRXIFG
    #define SPI_CTL0        UCB0CTL0
    #define SPI_CTL1        UCB0CTL1
    #define SPI_BR0         UCB0BR0
    #define SPI_BR1         UCB0BR1

    // CMA3000 Registers

    #define WHO_AM_I        0x00
    #define REVID           0x01
    #define CTRL            0x02
    #define STATUS          0x03
    #define RSTR            0x04
    #define INT_STATUS      0x05
    #define DOUTX           0x06
    #define DOUTY           0x07
    #define DOUTZ           0x08
    #define MDTHR           0x09
    #define MDFFTMR         0x0A
    #define FFTHR           0x0B
    #define I2C_ADDR        0x0C

    // Control Register setup
    #define G_RANGE_2       0x80

    // 2g range
    #define INT_LEVEL_LOW   0x40

    // INT active high
    #define MDET_NO_EXIT    0x20

    // Remain in motion detection mode
    #define I2C_DIS         0x10

    // I2C disabled
    #define MODE_PD         0x00

    // Power Down
    #define MODE_100        0x02

    // Measurement mode 100 Hz ODR
    #define MODE_400        0x04

    // Measurement mode 400 Hz ODR
    #define MODE_40         0x06

    // Measurement mode 40 Hz ODR
    #define MODE_MD_10      0x08

    // Motion detection mode 10 Hz ODR
    #define MODE_FF_100     0x0A

    // Free fall detection mode 100 Hz ODR
    #define MODE_FF_400     0x0C

    // Free fall detection mode 400 Hz ODR
    #define INT_DIS         0x01

    // Interrupts enabled

    // PIN DEFINITIONS
    #define PIN_INT         BIT4
    #define PIN_CSB         BIT3
    #define PIN_MOSI        BIT1
    #define PIN_MISO        BIT2
    #define PIN_SCK         BIT3

    // FUNCTION PROTOTYPES

    unsigned char ReadRegister(unsigned char Address);
    unsigned char WriteRegister(unsigned char Address, unsigned char Data);
    void wait_ms(unsigned short ms);
    void wait_us(unsigned short us);
    unsigned char Data;
    unsigned char RevID;
    unsigned char Xdata;
    unsigned char Ydata;
    unsigned char Zdata;

    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD;// Stop watchdog timer
    //UCSCTL1 = CALBC1_16MHZ; // Set DCO to calibrated 16MHz
    //DCOCTL = CALDCO_16MHZ;
    UCSCTL2 |= DIVS_3; // SMCLK to 2 MHz
    PORT_INT_DIR &= ~PIN_INT;
    PORT_INT_IE |= PIN_INT;

    // INT pin interrupt enabled
    PORT_INT_IES = 0x00;

    // Generate interrupt on Lo to Hi edge
    PORT_INT_IFG &= ~PIN_INT;

    // Clear interrupt flag
    PORT_CSB_DIR |= PIN_CSB;
    PORT_CSB_OUT |= PIN_CSB;

    // Unselect acceleration sensor
    PORT_SPI_SEL |= PIN_MOSI | PIN_MISO | PIN_SCK;

    // P3.3,2,1 USCI_B0 option select
    PORT_SPI_DIR |= BIT0;

    // P3.0 output direction
    // Initialize SPI interface to acceleration sensor

    SPI_CTL0 |= UCSYNC | UCMST | UCMSB | UCCKPH; // SPI master, 8 data bits,MSB first,
                                                 // clock idle low, data output on falling edge

    SPI_CTL1 |= UCSSEL1;

    // SMCLK as clock source
    SPI_BR0 = 0x08;

    // Low byte of division factor for baud rate(250 kHz)
    SPI_BR1 = 0x00;

    // High byte of division factor for baud rate
    SPI_CTL1 &= ~UCSWRST;

    // Start SPI hardware
    RevID = ReadRegister(REVID);

    // Read REVID register
    wait_us(44);

    // 11 * tsck
    Data = WriteRegister(CTRL, G_RANGE_2 | I2C_DIS | MODE_400);

    // Activate measurement mode: 2g/400Hz
    wait_us(44);
    Xdata = ReadRegister(DOUTX);

    // Dummy read to generate first INT pin LotoHi
    // transition in all situations, also while debugging

    __bis_SR_register(LPM4_bits + GIE);
    // Enter LPM4 w/interrupt

    }

    // Port 2 interrupt service routine, INT pin

    #pragma vector=PORT_INT_VECTOR
    __interrupt void Port_INT_ISR(void)
    {
    if (PORT_INT_IN & PIN_INT)
    {
    Xdata = ReadRegister(DOUTX);
    // Read DOUTX register
    wait_us(44);
    // 11 * tsck
    Ydata = ReadRegister(DOUTY);
    // Read DOUTY register
    wait_us(44);
    Zdata = ReadRegister(DOUTZ);
    // Read DOUTZ register
    PORT_INT_IFG &= ~PIN_INT;
    // Clear interrupt flag
    }
    }

    // Read a byte from the acceleration sensor
    unsigned char ReadRegister(unsigned char Address)
    {
    unsigned char Result;
    Address <<= 2;
    // Address to be shifted left by 2 and RW bit to be reset
    PORT_CSB_OUT &= ~PIN_CSB;
    // Select acceleration sensor
    Result = RX_BUFFER;
    // Read RX buffer just to clear interrupt flag
    TX_BUFFER = Address;
    // Write address to TX buffer
    while (!(IRQ_REG & RX_IFG));
    // Wait until new data was written into RX buffer
    Result = RX_BUFFER;
    // Read RX buffer just to clear interrupt flag
    TX_BUFFER = 0;
    // Write dummy data to TX buffer
    while (!(IRQ_REG & RX_IFG));
    // Wait until new data was written into RX buffer
    Result = RX_BUFFER;
    // Read RX buffer
    PORT_CSB_OUT |= PIN_CSB;
    // Deselect acceleration sensor
    // Return new data from RX buffer
    return Result;
    }

    // Write a byte to the acceleration sensor
    unsigned char WriteRegister(unsigned char Address, unsigned char Data)
    {
    unsigned char Result;
    Address <<= 2;
    // Address to be shifted left by 2
    Address |= 2;
    // RW bit to be set
    PORT_CSB_OUT &= ~PIN_CSB;
    // Select acceleration sensor
    Result = RX_BUFFER;
    // Read RX buffer just to clear interrupt flag
    TX_BUFFER = Address;
    // Write address to TX buffer
    while (!(IRQ_REG & RX_IFG));
    // Wait until new data was written into RX buffer
    Result = RX_BUFFER;
    //Read RX buffer just to clear interrupt flag
    TX_BUFFER = Data;
    // Write data to TX buffer
    while (!(IRQ_REG & RX_IFG));
    // Wait until new data was written into RX buffer
    Result = RX_BUFFER;
    // Read RX buffer
    PORT_CSB_OUT |= PIN_CSB;
    // Deselect acceleration sensor
    return Result;
    }

    // wait ms
    void wait_ms(unsigned short ms)
    {
    unsigned short a, b;
    for (a = ms; a > 0; a--);
    // outer loop takes 5 ck per round
    for (b = TICKSPERMS; b> 0; b--);
    // inner loop takes 5 ck per round
    asm("nop");
    }
    // wait us
    void wait_us(unsigned short us)
    {
    unsigned short a;
    us *= TICKSPERUS;
    for (a = us; a > 0; a--);
    // loop takes 5 ck per round
    asm("nop");
    }

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

    But I can't know if the changes that I've done are correct because when I build the project in IAR workbench get this error:

    Error[Pe702]: expected an "=" C:\Users\Dit\Documents\Texas Instruments\Accelerometer\msp430f5438a.h

    in the msp430f5438a.h file in this line:

    #pragma diag_suppress 1107

    Any ideas of why is not working or any suggestion for the code, because I am not sure if  what I've changed is what I should have changed. My changes are in red.

    Thanks.

  • You should start from a project that you can build in IAR. We provide examples/projects for IAR that will configure one of the USCI systems to a SPI master. If you haven't yet done so, download our latest MSP430ware release at http://www.ti.com/tool/msp430ware. This will install into your C:\ti\msp430\MSP430ware_<version>\ directory. Go to that directory and look into driver\examples\MSP430FR5xx_6xx and you will find a list of examples.

    Open on of the example folders (eusci_b_spi might fight closest to what you are doing) and go to the IAR folder and open the .eww project. This will open the project in IAR and you can build it here. I would maybe add some quick code to blink an LED or something just to make sure everything is building and running on the board.

    If that all works then use the example code provided for the accel. as a guide to what changes you should make in the project that you are able to get running.

    -Matt

  • I tried to do what you said in IAR but when I compile it says that the code exceeds the maximum capacity. So, I moved to CSS and there is compiling and building the project properly but the problem is that the program doesn't goes into the interrupt when I move the board. I am not really sure if I am modifying the sample code properly, so I copy here my code and I will explain the changes:

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


    #include <msp430.h>
    #include "msp430f5438a.h"


    unsigned char MST_Data,SLV_Data;
    // CONSTANTS
    #define XTAL 16000000L
    #define TICKSPERMS (XTAL / 1000 / 5 - 1)
    #define TICKSPERUS (TICKSPERMS / 1000)





    // PORT DEFINITIONS
    #define PORT_INT_IN          P2IN
    #define PORT_INT_OUT     P2OUT
    #define PORT_INT_DIR     P2DIR
    #define PORT_INT_IE     P2IE
    #define PORT_INT_IES     P2IES
    #define PORT_INT_IFG     P2IFG
    #define PORT_INT_VECTOR PORT2_VECTOR

    #define PORT_CSB_OUT     P8OUT//P4OUT
    #define PORT_CSB_DIR     P8DIR//P4DIR
    #define PORT_SPI_DIR     P9DIR//P3DIR
    #define PORT_SPI_SEL     P9SEL//P3SEL

    // REGISTER AND FLAG DEFINITIONS
    #define TX_BUFFER     UCB0TXBUF
    #define RX_BUFFER     UCB0RXBUF
    #define IRQ_REG     UCB0IFG
    #define RX_IFG         UCRXIFG
    #define SPI_CTL0     UCB0CTL0
    #define SPI_CTL1     UCB0CTL1
    #define SPI_BR0     UCB0BR0
    #define SPI_BR1     UCB0BR1

    // CMA3000 Registers
    #define WHO_AM_I     0x00
    #define REVID         0x01
    #define CTRL         0x02
    #define STATUS         0x03
    #define RSTR         0x04
    #define INT_STATUS     0x05
    #define DOUTX         0x06
    #define DOUTY         0x07
    #define DOUTZ         0x08
    #define MDTHR         0x09
    #define MDFFTMR     0x0A
    #define FFTHR         0x0B
    #define I2C_ADDR     0x0C

    // Control Register setup
    #define G_RANGE_2         0x80 // 2g range
    #define INT_LEVEL_LOW     0x40 // INT active high
    #define MDET_NO_EXIT     0x20 // Remain in motion detection mode
    #define I2C_DIS         0x10 // I2C disabled
    #define MODE_PD         0x00 // Power Down
    #define MODE_100         0x02 // Measurement mode 100 Hz ODR
    #define MODE_400         0x04 // Measurement mode 400 Hz ODR
    #define MODE_40         0x06 // Measurement mode 40 Hz ODR
    #define MODE_MD_10         0x08 // Motion detection mode 10 Hz ODR
    #define MODE_FF_100     0x0A // Free fall detection mode 100 Hz ODR
    #define MODE_FF_400     0x0C // Free fall detection mode 400 Hz ODR
    #define INT_DIS         0x01 // Interrupts enabled

    // PIN DEFINITIONS
    #define PIN_INT         BIT0//BIT4
    #define PIN_CSB         BIT7//BIT3
    #define PIN_MOSI         BIT4//BIT1
    #define PIN_MISO         BIT5//BIT2
    #define PIN_SCK         BIT0//BIT3

    // FUNCTION PROTOTYPES
    unsigned char ReadRegister(unsigned char Address);
    unsigned char WriteRegister(unsigned char Address, unsigned char Data);
    void wait_ms(unsigned short ms);
    void wait_us(unsigned short us);
    unsigned char Data;
    unsigned char RevID;
    unsigned char Xdata;
    unsigned char Ydata;
    unsigned char Zdata;

    int main(void)
    {
      WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer

     
      UCSCTL2 |= DIVS_3; // SMCLK to 2 MHz
      PORT_INT_DIR &= ~PIN_INT;
      PORT_INT_IE |= PIN_INT; // INT pin interrupt enabled
      PORT_INT_IES = 0x00; // Generate interrupt on Lo to Hi edge
      PORT_INT_IFG &= ~PIN_INT; // Clear interrupt flag
      PORT_CSB_DIR |= PIN_CSB;
      PORT_CSB_OUT |= PIN_CSB; // Unselect acceleration sensor
      PORT_SPI_SEL |= PIN_MOSI | PIN_MISO | PIN_SCK; // P9.4,5,0 USCI_B0 option select
      //PORT_SPI_DIR |= BIT0; // P9.0 output direction
      // Initialize SPI interface to acceleration sensor
      SPI_CTL0 |= UCSYNC | UCMST | UCMSB | UCCKPH; // SPI master, 8 data bits, MSB first,
      // clock idle low, data output on falling edge

      SPI_CTL1 |= UCSSEL1; // SMCLK as clock source
      SPI_BR0 = 0x08; // Low byte of division factor for baud rate (250 kHz)
      SPI_BR1 = 0x00; // High byte of division factor for baud rate
      SPI_CTL1 &= ~UCSWRST; // Start SPI hardware

      //UCB0IE |= UCRXIE;       // Enable USCI_B0 RX interrupt

      RevID = ReadRegister(REVID); // Read REVID register
      __delay_cycles(440); // 11 * tsck
      Data = WriteRegister(CTRL, G_RANGE_2 | I2C_DIS | MODE_400); // Activate measurement mode: 2g/400Hz
      __delay_cycles(440);
      Xdata = ReadRegister(DOUTX); // Dummy read to generate first INT pin Lo to Hi
      // transition in all situations, also while debugging*/
      __bis_SR_register(LPM4_bits + GIE); // Enter LPM4 w/interrupt
      }


    /*I don't use this:*/
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(UCB0IV,4))
      {
        case 0: break;                          // Vector 0 - no interrupt
        case 2:                                 // Vector 2 - RXIFG
          while (!(UCB0IFG&UCTXIFG));           // USCI_A0 TX buffer ready?

          if (UCB0RXBUF==SLV_Data)              // Test for correct character RX'd
            P4OUT |= 0x01;                      // If correct, light LED
          else
            P4OUT &= ~0x01;                     // If incorrect, clear LED

          MST_Data++;                           // Increment data
          SLV_Data++;
          UCB0TXBUF = MST_Data;                 // Send next value

          __delay_cycles(40);                   // Add time between transmissions to
                                                // make sure slave can process information
          break;
        case 4: break;                          // Vector 4 - TXIFG
        default: break;
      }
    }

    /*This is the interrupt of the accelerometer, but the code never comes into it*/
    // Port 2 interrupt service routine, INT pin
    #pragma vector=PORT_INT_VECTOR
    __interrupt void Port_INT_ISR(void)
    {
    if (PORT_INT_IN & PIN_INT)
    {
    Xdata = ReadRegister(DOUTX); // Read DOUTX register
    __delay_cycles(440); // 11 * tsck
    Ydata = ReadRegister(DOUTY); // Read DOUTY register
    __delay_cycles(440);
    Zdata = ReadRegister(DOUTZ); // Read DOUTZ register
    PORT_INT_IFG &= ~PIN_INT; // Clear interrupt flag
    }
    }
    // Read a byte from the acceleration sensor
    unsigned char ReadRegister(unsigned char Address)
    {
    unsigned char Result;
    Address <<= 2; // Address to be shifted left by 2 and RW bit to be reset
    PORT_CSB_OUT &= ~PIN_CSB; // Select acceleration sensor
    Result = RX_BUFFER; // Read RX buffer just to clear interrupt flag
    TX_BUFFER = Address; // Write address to TX buffer
    while (!(IRQ_REG & RX_IFG)); // Wait until new data was written into RX buffer
    Result = RX_BUFFER; // Read RX buffer just to clear interrupt flag
    TX_BUFFER = 0; // Write dummy data to TX buffer
    while (!(IRQ_REG & RX_IFG)); // Wait until new data was written into RX buffer
    Result = RX_BUFFER; // Read RX buffer
    PORT_CSB_OUT |= PIN_CSB; // Deselect acceleration sensor
    // Return new data from RX buffer
    return Result;
    }
    // Write a byte to the acceleration sensor
    unsigned char WriteRegister(unsigned char Address, unsigned char Data)
    {
    unsigned char Result;
    Address <<= 2; // Address to be shifted left by 2
    Address |= 2; // RW bit to be set
    PORT_CSB_OUT &= ~PIN_CSB; // Select acceleration sensor
    Result = RX_BUFFER; // Read RX buffer just to clear interrupt flag
    TX_BUFFER = Address; // Write address to TX buffer
    while (!(IRQ_REG & RX_IFG)); // Wait until new data was written into RX buffer
    Result = RX_BUFFER; // Read RX buffer just to clear interrupt flag
    TX_BUFFER = Data; // Write data to TX buffer
    while (!(IRQ_REG & RX_IFG)); // Wait until new data was written into RX buffer
    Result = RX_BUFFER; // Read RX buffer
    PORT_CSB_OUT |= PIN_CSB; // Deselect acceleration sensor
    return Result;
    }
    // wait ms
    /*void wait_ms(unsigned short ms)
    {
    unsigned short a, b;
    for (a = ms; a > 0; a--) // outer loop takes 5 ck per round
    for (b = TICKSPERMS; b > 0; b--) // inner loop takes 5 ck per round
    asm("nop");
    }
    // wait us
    void wait_us(unsigned short us)
    {
    unsigned short a;
    us *= TICKSPERUS;
    for (a = us; a > 0; a--) // loop takes 5 ck per round
    asm("nop");
    }
    */
    /***************************************************************************************************************************/

    The code in red are my changes. At the beginning I change the port configuration because I think that CSB means chip select and according to the user's guide of the board it for the accelerometer is the P8.7 so that's why I changed the P8 instead of P4. With the PORT_SPI_DIR and PORT_SPI_SEL I change to P9 instead of P3 because according to the user's guide the MOSI and MISO of the accelerometer are in port9.
    After that I changed the PIN Definitions and I changed PIN_INT from BIT4 to BIT0 because the interrupt pinfor the accelerometer is P2.0, the PIN_CBS from BIT3 to BIT7 because the CS is P8.7, the MOSI, MISO and SCK because according to the user's guide they are P9.4,5 and 0.
    Those are basically the changes that I've made but still the code is not going into the interrupt of PORT2.
    Any ideas of what I am doing wrong?
    Thanks in advance.

  • You need to start simple and then work your way to a solution that will work. Porting is not always as straightforward changing defines and it's difficult to debug when you have a monolithic chunk of code where it is unknown whether any part works.

    Start by looking at the SPI lines and see if the values being written out for that first ReadRegister() call are in fact being written out on the lines.

    -Matt

  • Hi, I am checking the registers to which is the accelerometer connected which are the P9.4,P9.5 and P9.0 which according to the schematic of the TrxEB are also UCA2SIMO and UCA2SOMI and they are not changing. I am checking them in the Watch window during the debug. The UCA2RXBUF or UCA2RXBUF_SPI are not changing when I move the board.
    Any Idea of where I can see the values of the accelerometer?
    Because I can't see anything changing when I move the board...

    btw,
    I've checked that the SPI registers are written. But in the function ReadRegister() in this instruction: Result = RX_BUFFER; the variable Result = 0x01; (is in Register 12) but after next line: TX_BUFFER = Address; Result changes to  0x04. And after the last Result = RX_BUFFER; Result=0x00.

    Can someone please let me know if the changes that I've done are correct?
    I really don't know what I am doing wrong.

    Thanks.

  • Ok, It is working the problem was that the accelerometer wasn't powered up, so when I activate the port P6.0 is working. Thank you for the help.

    Now, I am trying to send by SPI to the Raspberry pi the value of the Xdata, but when I enable both interrupts, the interrupt of the accelerometer P2.0 stops and it only goes into the SPI interrupt and the values of the Xdata, Ydata and Zdata are not changing. Any idea of why it happens? could be due to the priorities of the interrupts? if that's the problem, is there any way to change that priorities?

    Thanks.
    EDIT:
    Finally is working and sending by SPI the values that I want. The problem of the blocking interrupt has been solved using the enable command of each interrupt. I made inside of the ISR of one interrupt the enabling of the other one and the disabling of that one.

    Thank you for the answers! :)

  • You are getting interrupts from the accelerometer on P2.0 and then also getting interrupts for receiving data on SPI, right? Which USCI_A interface are you using for each SPI bus?

    I'm not sure that priorities are necessarily the issue because the only thing running should be the 2 ISRs which means that your ISR handling the RaspPi comms must be running 100% of the time in order to completely block your accel. ISR.

    -Matt

**Attention** This is a public forum