Hi
I am trying to communicate between two MSP430F5438s using SPI. I tried with my code . It was not working . So i tried using example code (TI)which is pasted below . Still it was not working .I doubt there might be a problem in hardware connection between two MCs. regarding hardware , I connected using 3 wire mode which connects SIMO(master p3.4)-SIMO (Slave p3.4) , SOMI(master p3.5)-SOMI (Slave p3.5) and clocks using p3.0(master )- p3.0(slave) and necessary power suppply to both the controllers . please let me know if there is any hardware problem or any code issue .
I have used following master code :
#include "msp430x54xA.h"
unsigned char MST_Data,SLV_Data;
void main(void){ WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer
P1OUT |= 0x02; // Set P1.0 for LED // Set P1.1 for slave reset P1DIR |= 0x03; // Set P1.0-2 to output direction P3SEL |= 0x31; // P3.5,4,0 option select
UCA0CTL1 |= UCSWRST; // **Put state machine in reset** UCA0CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB; // 3-pin, 8-bit SPI master // Clock polarity high, MSB UCA0CTL1 |= UCSSEL_2; // SMCLK UCA0BR0 = 0x02; // /2 UCA0BR1 = 0; // UCA0MCTL = 0; // No modulation UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
P1OUT &= ~0x02; // Now with SPI signals initialized, P1OUT |= 0x02; // reset slave
__delay_cycles(100); // Wait for slave to initialize
MST_Data = 0x01; // Initialize data values SLV_Data = 0x00; //
while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = MST_Data; // Transmit first character
__bis_SR_register(LPM0_bits + GIE); // CPU off, enable interrupts}
#pragma vector=USCI_A0_VECTOR__interrupt void USCI_A0_ISR(void){ switch(__even_in_range(UCA0IV,4)) { case 0: break; // Vector 0 - no interrupt case 2: // Vector 2 - RXIFG while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
if (UCA0RXBUF==SLV_Data) // Test for correct character RX'd P1OUT |= 0x01; // If correct, light LED else P1OUT &= ~0x01; // If incorrect, clear LED
MST_Data++; // Increment data SLV_Data++; UCA0TXBUF = 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; }}
also the save code is :
while(!(P3IN&0x01)); // If clock sig from mstr stays low, // it is not yet in SPI mode P3SEL |= 0x31; // P3.5,4,0 option select UCA0CTL1 |= UCSWRST; // **Put state machine in reset** UCA0CTL0 |= UCSYNC+UCCKPL+UCMSB; // 3-pin, 8-bit SPI slave, // Clock polarity high, MSB UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
__bis_SR_register(LPM4_bits + GIE); // Enter LPM4, enable interrupts}
// Echo character#pragma vector=USCI_A0_VECTOR__interrupt void USCI_A0_ISR(void){ switch(__even_in_range(UCA0IV,4)) { case 0:break; // Vector 0 - no interrupt case 2: // Vector 2 - RXIFG while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = UCA0RXBUF; break; case 4:break; // Vector 4 - TXIFG default: break; }}
with this code dumped on master and slave UCs ,, and connections as told , I am not able to communicate between the two controllers . Please suggest some breakthrough .
Thanks
Karthik
Hi Michael
When I am reading from RXBUF in slave code , RXIFG is not resetting as told in the datasheet even GIE and RXIE are set . Please tell why it is not resetting once we read data from RXBUF .
It should reset. How do you know it isn'tß By playing a debugger there? Then it is already set again. Halting the PCu with the debugger does not mean that the peripherls stop working. The USCI is stillr eceiving. And it will receive a lot of bytes while the debugger is haltign the CPU and refreshing its register displays.
In master mode, teh debugger may (on some MSPs) halt the clocks, so sending stops (with desastrous results if it is an asynchronous transfer), but in slave mode, the clock comes from outside and the USCI continues receiving, whether the CPU is stopped or not.
p.s.: reading UxyIV register, in your switch, already clears the IFG bit of the interrupt it returns. So the IFG bit should not be set at all when you read RXBUF. (well, if it is, it means that another byte just arrived and you were too slow readign the previous one)
_____________________________________Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.
Yes Micheal , with the things told ..i made some changes in the code Now I am sending some array of character ":master " to the slave .I can see the ouput (:master ) in the slave .
When this is received i am tryin to send some response command from slave to the master . But in master I am not able to see the response command from Slave . I am unable to figure out whether it is issue in master code or slave code . hardware connections are unchanged . Please guide . Here is the latest code
Master code
//******************************************************************************// MSP430F543xA Demo - USCI_A0, SPI 3-Wire Master Incremented Data
unsigned char counter =0;unsigned char a[7]={':','m','a','s','t','e','r'};unsigned char b[6]={'0','0','0','0','0','0'};unsigned char i=0,j=0,p=0;unsigned char MST_Data,SLV_Data;unsigned char temp,counter , msendflag=1;void main(void){ WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer
UCA0CTL1 |= UCSWRST; // **Put state machine in reset** UCA0CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB; // 3-pin, 8-bit SPI master // Clock polarity high, MSB UCA0CTL1 |= UCSSEL_2; // SMCLK UCA0BR0 = 0x02; // /2 UCA0BR1 = 0; // UCA0MCTL = 0; // No modulation UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt UCA0IE |= UCTXIE; P1OUT &= ~0x02; // Now with SPI signals initialized, __delay_cycles(100); // Wait for slave to initialize MST_Data = 0xAA; // Initialize data values SLV_Data = MST_Data; //
while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = MST_Data; // Transmit first character MST_Data = 0; __bis_SR_register(LPM0_bits + GIE); // CPU off, enable interrupts}
#pragma vector=USCI_A0_VECTOR__interrupt void USCI_A0_ISR(void){ switch(__even_in_range(UCA0IV,4)) { case 0: break; // Vector 0 - no interrupt case 4:
if (UCA0RXBUF==':')
{ P1OUT ^=0x02; }
// Test for correct character RX'd // P1OUT |= 0x01; // If correct, light LED // else // P1OUT &= ~0x01; // If incorrect, clear LED
MST_Data++; // Increment data if( msendflag==1)
{ for(j=0;j<100;j++) { __delay_cycles(30000); } for(i=0;i<7;i++) { __delay_cycles(30000); P1OUT ^=0x01; for(j=0;j<100;j++) { __delay_cycles(30000); } UCA0TXBUF=a[i]; msendflag=0; __delay_cycles(40); } } if(i==4) { i=0; }
for(j=0;j< 255;j++); for(j=0;j< 255;j++); __delay_cycles(30000); // Vector 2 - RXIFG // make sure slave can process information break; case 2:
if (UCA0RXBUF=='s')
{ P1OUT ^=0x02; } b[p]= UCA0RXBUF; p++; break; // Vector 4 - TXIFG default: break; }}
Slave Code
unsigned char a[6] ={':','s','l','a','v','e'};unsigned char b[8]= {0,0,0,0,0,0,0,0};unsigned char c[6]={0,0,0,0,0,0};unsigned char d[6]={0,0,0,0,0,0};
unsigned char i = 0,j=0,q=0 ,k=0 ;unsigned char slv_data;unsigned char counter =0,recvflag = 0;unsigned char sendflag = 0,slvflag=0;void main(void){ WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer
while(!(P3IN&0x01)); // If clock sig from mstr stays low, P1DIR |=0x03; // it is not yet in SPI mode P3SEL |= 0x31; // P3.5,4,0 option select UCA0CTL1 |= UCSWRST; // **Put state machine in reset** UCA0CTL0 |= UCSYNC+UCCKPL+UCMSB; // 3-pin, 8-bit SPI slave, // Clock polarity high, MSB UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** UCA0IE |= UCRXIE; UCA0IE |= UCTXIE;// Enable USCI_A0 RX interrupt// while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready? //UCA0TXBUF = 0x00;//MST_Data; // Transmit first character
__bis_SR_register( GIE); while(1) { if(sendflag==1) { sendflag=0; UCA0TXBUF = 's'; slvflag=1;
} }// Enter LPM4, enable interrupts}
// Echo character#pragma vector=USCI_A0_VECTOR__interrupt void USCI_A0_ISR(void){ switch(__even_in_range(UCA0IV,4)) { case 0:break; // Vector 0 - no interrupt case 2: // Vector 2 - RXIFG // while (!(UCA0IFG&UCTXIFG));
if(UCA0RXBUF == ':') { recvflag= 1; }
if(recvflag==1) { // for(i =0;i<4;i++) b[i]= UCA0RXBUF; i++; counter++; }
if(counter ==7 ) {
UCA0TXBUF = ':'; P1OUT ^=0x01; sendflag=1; recvflag =0 ; P1OUT ^= 0X02; counter =0 ;//UCA0TXBUF = ':'; }
//if(sendflag==1)//{ for(j=0;j<10;j++) {
UCA0TXBUF = 'v';
c[j]= UCA0TXBUF; }
break; case 4: for(k=0;k<10;k++) {
d[k]= UCA0TXBUF; } break; // Vector 4 - TXIFG default: break; }}
Here I am not getting any data in RXBUF of master code even when slave is continously sending data .
hello karthik,
I am new for MSP430 and working on SPI with one MSP device to another device ... i hv seen the code which you have written above... some doubts on slave code..you have define " slave" on a buffer but not reffering in any other place of the code...plz suugest me..
Hi michael
Any update from you to the last rpoblem posted ???
Hi Richa
In master code as you see, I have set UCMST in UCA0CTL0 which sets it as master device . If it is not set high , it acts as a slave .check msp4305x family guide to know more ..
thanks
hello Karthik,
I am trying to communicate between MSP430F5438 to MSP430BT5190 via SPI sending only one charcter 'a'.
on the other end on slave side we are able to recieve the character but in between we are recieving some random data(not 'a'). here i paste the code. plz chk if you find any bug
SPI master code
unsigned char MST_Data;volatile unsigned int i;void main(void){
WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer
P1OUT |= 0x02; // Set P1.0 for LED // Set P1.1 for slave reset P1DIR |= 0x03; // Set P1.0-2 to output direction// init_clocks();
P3OUT |= 0x40; // Set P1.0 for LED // Set P1.1 for slave reset P3DIR |= 0x40;
P10SEL |= 0x0E; P10DS |= 0x0E; P3SEL |= BIT0; P3DIR |= BIT0; P10DS |= BIT0;
UCB3CTL1 |= UCSWRST; // **Put state machine in reset**UCB3CTL0 |= UCMST+UCSYNC+UCMSB + UCCKPL; // 3-pin, 8-bit SPI master UCSYNC++UCMSB+UCMODE_0 //UCB3CTL0 |= UCMODE_0; // Clock polarity high, MSB UCB3CTL1 |= UCSSEL_2; // SMCLK UCB3BR0 = 0x02; // UCB3BR1 = 0; UCB3CTL1 &= ~UCSWRST;
// //UCB0MCTL = 0; // No modulation
// **Initialize USCI state machine** UCB3IE |= UCRXIE; // Enable USCI_A0 RX interrupt
//P1OUT &= ~0x02; // Now with SPI signals initialized, //P1OUT |= 0x02; // reset slave
MST_Data = 'a';// 'b'; // // Initialize data values //SLV_Data = 0x00; //P3OUT |= 0x40; for (i = 0xFFF; i > 0; i--); // Time for slave to ready P3OUT &= ~0x40; P3OUT &= ~0x40; P3OUT &= ~0x40;
while (!(UCB3IFG&UCTXIFG)); // USCI_B3 TX buffer ready? //P3OUT &= ~BIT0; UCB3TXBUF = MST_Data; // Transmit first characterl// while (UCB3STAT & UCBUSY);//P3OUT |=BIT0; __bis_SR_register(LPM0_bits + GIE); // CPU off, enable interrupts
// while(1){//// }
}
#pragma vector=USCI_B3_VECTOR__interrupt void USCI_B3_ISR(void){
unsigned int j = 0;// RXIFG switch(__even_in_range(UCB3IV,4)) { case 0: break; case 2:// while (!(UCB3IFG&UCTXIFG)); // USCI_A0 TX buffer ready?//// if (UCB3RXBUF == 'a') // Test for correct character RX'd// {P1OUT |= 0x01; // If correct, light LED//// } // else // P1OUT &= ~0x01; // If incorrect, clear LED
// MST_Data++; // Increment data // SLV_Data++; // Send next value //for(int i=0;i<500;i++) // UCB3TXBUF[i] =; // P3OUT &= ~BIT0;
P3OUT |= 0x40; for (j = 0xFFF; j > 0; j--); // Time for slave to ready
P3OUT &= ~0x40; P3OUT &= ~0x40; P3OUT &= ~0x40;
UCB3TXBUF = MST_Data;
P1OUT |= 0x01; // printf("%s\n", UCB3TXBUF); // printf("Hello World\n");
// while (UCB3STAT & UCBUSY);// P3OUT |=BIT0; //__delay_cycles(10000); // Add time between transmissions to information
// printf()
break; case 4: break; // Vector 4 - TXIFG default: break; }}
Thanks in advance
In your master ISR, oyu react on the RX interrupt (UCB3IV=2) to send something. The demo code used that because it was just echoing incoming data back to the output. However, in your code, you should place all send-related stuff into the TX interrupt case, which is case 4.And you don't need any delay. If TX interrupt comes, then you can write to TXBUF and the slave will eventually get it. If there is no TX interrupt, then the USCI is still working on send.
When an RX interrupt comes, it means that one byte has been received (which in turn means that one byte has been sent,as this is symmetrical, but shifted by 1/2 clock cycle). However, it doesn't mean that you can (or want to) send.
You should play the order of events on a whiteboard once more before implementing it in software. The users guide gives you all the information about what happens when.