Quantcast
Channel: MSP430 Technical Forums
Viewing all articles
Browse latest Browse all 2077

MSP430G2553 SPI Slave mode behaviour

$
0
0

As a part of my teaching work, I wanted to demonstrate connecting Raspberry Pi-2 (as SPI Master) to MSP430 LP with MSP430G2553 (as SPI Slave), as an alternative to Arduino-Uno as a SPI Slave. It was aimed at utilizing the ADC's of either of these micro-controller boards, as Raspberry Pi-2 does not have ADC modules. The working of Arduino Uno as the SPI Slave device was smooth and painless, but I spent many hours getting the MSP430G2553 working as a SPI SLave. Ultimately, I hit upon a hack (if there was one) and MSP430G2553 started working as SPI Slave! However, I do not understand why this hack works, or, why such a hack is needed at all. I shall appreciate any hints, help, explanations regarding this. I hope to be excused for this long posting.

--------------- SPI Master code: helloArdu.c ---------------------

/**********************************************************
 SPI_Hello_Arduino
   Configures an Raspberry Pi as an SPI master and  
   demonstrates bidirectional communication with an
   Arduino Slave by repeatedly sending the text
   "Hello Arduino" and receiving a response

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

#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <fcntl.h>
#include <cstring>
#include <iostream>

using namespace std;

int fd;
unsigned char hello[] = {'H','e','l','l','o',' ',
                           'A','r','d','u','i','n','o'};
unsigned char result;
int spiTxRx(unsigned char txDat);

int main (void){
  fd = open("/dev/spidev0.0", O_RDWR);
  unsigned int speed = 1000000;
   ioctl (fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
  while (1){
      for (int i = 0; i < sizeof(hello); i++) {
         result = spiTxRx(hello[i]);
         cout << result;
         usleep (10);   
      }
  }
}

 

int spiTxRx(unsigned char txDat){
   unsigned char rxDat;
   struct spi_ioc_transfer spi;
   memset (&spi, 0, sizeof (spi));
  spi.tx_buf        = (unsigned long)&txDat;
  spi.rx_buf        = (unsigned long)&rxDat;
  spi.len           = 1;
  ioctl (fd, SPI_IOC_MESSAGE(1), &spi);
  return rxDat;
}
--------------------------------------------------------------------------

 

The Arduino Uno Slave code is:

---------------------- helloRaspi.ino --------------------------------

/*************************************************************
 SPI_Hello_Raspi
   Configures an ATMEGA as an SPI slave and demonstrates
   bidirectional communication with an Raspberry Pi SPI master
   by repeatedly sending the text "Hello Raspi"
****************************************************************/

unsigned char hello[] = {'H','e','l','l','o',' ',
                         'R','a','s','p','i','\n'};
byte marker = 0;
void setup (void) {
  pinMode(MISO, OUTPUT);
  SPCR |= _BV(SPE);
}

 

void loop (void){
  if((SPSR & (1 << SPIF)) != 0) {
    SPDR = hello[marker];
    marker++;
    if(marker > sizeof(hello)){
      marker = 0;
    }  
  }    
}
-------------------------------------------------------------------------

 

My Slave code for MSP430G2553 is:

------------------------- helloRaspi.c -------------------------------

#include "msp430g2553.h"
#include <string.h>

unsigned char cmdbuf[20];
char cmd_index=0;
unsigned char hello[] = "Hello Raspi \n";
void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
  P1DIR |= BIT0 + BIT6;  
  while (!(P1IN & BIT5));

  P1SEL = BIT5 + BIT6+ BIT7;
  P1SEL2 = BIT5 + BIT6 + BIT7;
  P2SEL = BIT0;
  P2SEL2 = BIT0;
  UCB0CTL1 = UCSWRST;                       // **Put state machine in reset**
  UCB0CTL0 |=  UCCKPL + UCMSB + UCMODE_2 + UCSYNC; // 3-pin, 8-bit SPI master
  UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine*
  IE2 |= UCB0RXIE;                          // Enable USCI0 RX interrupt
  IE2 |= UCB0TXIE;
  __bis_SR_register(LPM4_bits + GIE);       // Enter LPM4, enable interrupts

}  // end main()

 

int index = 0;
__attribute__((interrupt(USCIAB0TX_VECTOR))) void USCI0TX_ISR (void){
  UCB0TXBUF = hello[index]<<1;   // <---- Note this hack
  index++;
  if(index == 13) index = 0;
}
 __attribute__((interrupt(USCIAB0RX_VECTOR))) void USCI0RX_ISR (void){
  char value = UCB0RXBUF;
  if (cmd_index == 13) {
    if (strncmp(cmdbuf, "Hello Arduino", 13) == 0) {
      P1OUT |= BIT0;
    } else {
      P1OUT &= ~BIT0;
    }
    cmd_index = 0;
  } else {
    cmdbuf[cmd_index] = value;
    cmd_index++;
  }

}

-------------------------------------------------------------------------

 

Note the hack indicated by <---, where the character to be transmitted to back to RaspberryPi is shifted to left by one bit.

Without this hack, which would be normal way, I found that, e,g, Character 'A' (0x41) sent was received as 0xA0, indicating that the character bits are being rotated to the right one place. With this hack, transmission was fine!

 

Why this is so? Am I missing something or doing something wrong? Digging various discussion lists and forums, unfortunately, have not given any clue. There are plenty of example code for MSP430G2553 working in SPI Master mode, but few for Slave mode.


Viewing all articles
Browse latest Browse all 2077

Trending Articles