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.

MSP430FR2532: DMX512 (RS485 with 2 StopBit, no Parity) and eUSCI serial interface

Part Number: MSP430FR2532

Hello,

I have some problems to configure the eUSCI with the correct settings and the right clock settings/deviders. First I think the hardware is okay. There are some bus participans wokring on Atmel processors and some bought ones. Between the RS485 IC and the MSP430 the scope shows me valid Data (analog scope, not data logger). For this reason I think I only fail with the right software settings. ;-)

I'm using IAR Embedded Workbench IDE 6.50.5.


I tried to remix some code examples: https://github.com/j-windsor/MSP430-DMX512/blob/master/main.c

The one from your example: msp430fr243x_euscia0_uart_01.c www.ti.com/.../slac700

The actual one of my try:

//#include "io430.h"
#include "msp430fr2532.h"

#define CHAN_1  BIT4            //PORT1 //OUTPUT 1 
#define CHAN_2  BIT1            //PORT1 //OUTPUT 2
#define CHAN_3  BIT5            //PORT1 //OUTPUT 3
#define CHAN_4  BIT2            //PORT1 //OUTPUT 4

#define RX      BIT5            //PORT2 //RX UART
#define TX      BIT6            //PORT2 //TX UART
#define DE      BIT7            //PORT2 //transmit enable UART
#define RE      BIT1            //PORT3 //_receive enable UART (inverted)

//DMX512/RS485 Setup
  unsigned int actChannel = 0;          //variable for actual receiving byte
  unsigned char busAddress = 0;           //DMX Adress + 1
  unsigned char rxData = 0;             //value of received byte
  //unsigned char byteReceived = 0;       //byte received yet?

int main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;

  P1SEL0 = 0x00;                                
  P1SEL1 = 0x00;
  P1DIR = CHAN_1 + CHAN_2 + CHAN_3 + CHAN_4; //chan1 and chan3 works
  P1OUT = 0x00;//CHAN_1 + CHAN_2 + CHAN_3 + CHAN_4;
  
  P2SEL0 = RX;
  P2SEL1 = RX;
  P2DIR = DE; //and ~RX
  P2OUT = 0x00;
  
  P3SEL0 = 0x00;
  P3SEL1 = 0x00;
  P3DIR = RE;
  P3OUT = 0x00;
  
  PM5CTL0 &= ~(LOCKLPM5);
  
  //set oscillators:
  __bis_SR_register(SCG0);                 // disable FLL
  CSCTL3 |= SELREF__REFOCLK;               // Set REFO as FLL reference source
  CSCTL0 = 0;                              // clear DCO and MOD registers
  CSCTL1 &= ~(DCORSEL_7);                  // Clear DCO frequency select bits first
  CSCTL1 |= DCORSEL_3;                     // Set DCO = 8MHz
  CSCTL2 = FLLD_0 + 243;                   // DCODIV = 8MHz
  __delay_cycles(3);
  __bic_SR_register(SCG0);                 // enable FLL
  while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // Poll until FLL is locked

  CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK; // set default REFO(~32768Hz) as ACLK source, ACLK = 32768Hz
                                           // default DCODIV as MCLK and SMCLK source
  
  UCA1CTL1 |= UCSWRST; //pause for init
  UCA1CTL1 |= UCSSEL1; //small clock, no error detection, no parity
  UCA1CTL0 = UCSPB | UCMODE_1; //two low stop bits
  //UCA1CTLW0 = 
  UCA1BR0 = 32; //250kBaud => 8.000.000 / 250.000 = 32
  UCA1BR1 = 0;
  UCA1CTLW0 &= ~UCSWRST; //restart after init
  UCA1IE |= UCRXIE; //interrupt on receive
  
  _BIS_SR(GIE); //interrupt enable
    
  while(1)
  {
    if(UCA1STATW & UCBRK)
    {
      actChannel = 0; //reset channel counter
    }
    /*P1OUT = CHAN_1 + CHAN_2 + CHAN_3 + CHAN_4;
    for(int i=0; i< 30000; i++); 
    P1OUT = 0x00;
    for(int i=0; i< 30000; i++); */
  }
}


#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A1_VECTOR))) USCI_A1_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(UCA1IV,USCI_UART_UCTXCPTIFG))
  {
  case 0x02: //receive
    rxData = UCA1RXBUF;
    //byteReceived = 1;
    if(actChannel == 2){
      if(rxData > 127)
      {
        P1OUT |= CHAN_1;
      }
      else
      {
        P1OUT &= ~CHAN_1;
      }
    }
    actChannel++; //increment channel
    break;
  default: break;
  }
  UCA1IFG &= ~UCTXIFG; //clear flag
}

I am a little bit confused with all the settings of the eUSCI. On page 575 of the Family/Users Guide there are some correction/modulation patterns. I just thought I can set the Clock to 8MHz and devide it down to 250 kBaud. The datasheet makes differences on page 576, if you will need  a devider of more or less than 16. The example in slac700 is only for 9600 Baud and need all the corrections, right?

I would be very pleased if anyone has additional information or hints for me! :) I hope I pasted all important information.

Yours, Carsten

  • Hi Carsten,

    If you use the formula provided in section 3.3.5 of the MSP430FR4xx and MSP430FR2xx Family User's Guide (fDCOCLKDIV = (FLLN + 1) × (fFLLREFCLK ÷ n)) to calculate the clock speed, you'll see that it's not exactly 8MHz. In reality it's closer to 7995392 Hz. This can introduce error into your baud rate that causes a communication failure.

    The 250k baud rate is not a standard baud rate that shows up the user's guide so you have to calculate your own divider values. TI provides a UART baud rate generation tool for Driverlib, but this can also be applied to register level code as well. I entered in your specifications and got the following:

    While your initial calculation was correct. I believe the error associated with the slightly different source clock may be causing the problem. Can you try this out and let me know how it works?

    Best regards, 

    Caleb Overbay

  • Hey, thanks a lot! I tried another some hours... :D

      UCA1CTLW0 |= UCSWRST; //pause for init
      UCA1CTLW0 |= UCSSEL__SMCLK; //small clock, no error detection, no parity
      UCA1CTLW0 = UCSPB | UCMODE_1; //two low stop bits and linear mode with start condition
      /*UCA1BRW = 0x0001; //250kBaud => 8.000.000 / 250.000 = 32
      //UCBRF1 = 15;
      //UCBRS1 = 255;
      //UCOS16 = 1;
      UCA1MCTLW =  0xff00 | UCBRF_15 | UCOS16;*/
      UCA1BRW = 0x0002; //250kBaud => 8.000.000 / 250.000 = 32
      //UCBRF1 = 0;
      //UCBRS1 = 1;
      //UCOS16 = 1;
      UCA1MCTLW =  0x0100 | UCOS16;
      UCA1CTLW0 &= ~UCSWRST; //restart after init
      UCA1IE |= UCRXIE; //interrupt on receive
      
      _BIS_SR(GIE); //interrupt enable

    This is what I made of this. I first tried your configuration (commented out), than I put the SMLK on the output and meassured 8.015.414Hz. I put that in the calculator and got  2 - 0 - 1 -  1.

    I tried to change registers a litle bit random, checked everyone in the Family Guide but I won't get in the interrupt routine... :( I put the breakpoint on the switch instruction in the ISR. I try to read the second byte of the UART for test. I think the error shouldn't be that big at the beginning to let it fail for unprecise timing.

  • I added these UCRXEIE bit as I have seen in the example of DMX512 https://github.com/j-windsor/MSP430-DMX512/blob/master/main.c#L88

    I put a logic analyzer in between the RS485 IC and the MSP430 and got valid DMX512 data.

    I tried a lot of combinations of registers that I thought could be logical.

    I added a code example of an ADC to my code and it called an ISR instantly. The UART ISR is never called.

    That is my actual code:

    //#include "io430.h"
    #include "msp430fr2532.h"
    
    #define CHAN_1  BIT4            //PORT1 //OUTPUT 1 
    #define CHAN_2  BIT1            //PORT1 //OUTPUT 2
    #define CHAN_3  BIT5            //PORT1 //OUTPUT 3
    #define CHAN_4  BIT2            //PORT1 //OUTPUT 4
    
    #define RX      BIT5            //PORT2 //RX UART
    #define TX      BIT6            //PORT2 //TX UART
    #define DE      BIT7            //PORT2 //transmit enable UART
    #define RE      BIT1            //PORT3 //_receive enable UART (inverted)
    
    //DMX512/RS485 Setup
      unsigned int actChannel = 0;          //variable for actual receiving byte
      unsigned char busAddress = 0;           //DMX Adress + 1
      unsigned char rxData = 0;             //value of received byte
      //unsigned char byteReceived = 0;       //byte received yet?
    
    
    int main( void )
    {
      // Stop watchdog timer to prevent time out reset
      WDTCTL = WDTPW + WDTHOLD;
    
      PM5CTL0 &= ~(LOCKLPM5);
      
      P1SEL0 = 0x00;                                
      P1SEL1 = 0x00 | BIT7; //BIT7 is fpr SMCLK output
      P1DIR = CHAN_1 + CHAN_2 + CHAN_3 + CHAN_4 + BIT7; //BIT7 is fpr SMCLK output
      P1OUT = 0x00;//CHAN_1 + CHAN_2 + CHAN_3 + CHAN_4;
      
      P2SEL0 = RX;
      P2SEL1 = 0x00;
      P2DIR = DE; //and ~RX
      P2OUT = 0x00;
      
      P3SEL0 = 0x00;
      P3SEL1 = 0x00;
      P3DIR = RE;
      P3OUT = 0x00;
      
      //set oscillators:
      __bis_SR_register(SCG0);                 // disable FLL
      CSCTL3 |= SELREF__REFOCLK;               // Set REFO as FLL reference source
      CSCTL0 = 0;                              // clear DCO and MOD registers
      CSCTL1 &= ~(DCORSEL_7);                  // Clear DCO frequency select bits first
      CSCTL1 |= DCORSEL_3;                     // Set DCO = 8MHz
      CSCTL2 = FLLD_0 + 243;                   // DCODIV = 8MHz
      __delay_cycles(3);
      __bic_SR_register(SCG0);                 // enable FLL
      while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // Poll until FLL is locked
    
      CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK; // set default REFO(~32768Hz) as ACLK source, ACLK = 32768Hz
                                               // default DCODIV as MCLK and SMCLK source
      
      UCA1CTLW0 |= UCSWRST; //pause for init
      UCA1CTLW0 |= UCSSEL__SMCLK; //small clock, no error detection, no parity
      UCA1CTLW0 = UCSPB | UCMODE_1 | UCRXEIE; //two low stop bits and linear mode with start condition | receive eroneous
      UCA1BRW = 0x0001; //250kBaud => 8.000.000 / 250.000 = 32
      //UCBRF1 = 15;
      //UCBRS1 = 255;
      //UCOS16 = 1;
      UCA1MCTLW =  0xff00 | UCBRF_15 | UCOS16;
      /*UCA1BRW = 0x0002; //250kBaud => 8.000.000 / 250.000 = 32
      //UCBRF1 = 0;
      //UCBRS1 = 1;
      //UCOS16 = 1;
      UCA1MCTLW =  0x0100 | UCOS16;*/
      UCA1CTLW0 &= ~UCSWRST; //restart after init
      UCA1IE |= UCRXIE; //interrupt on receive
      
      //_BIS_SR(GIE); //interrupt enable
      __bis_SR_register(GIE);
      while(1)
      {
        if(UCA1STATW & UCBRK)
        {
          actChannel = 0; //reset channel counter
        }
        //P1OUT = CHAN_1 + CHAN_2 + CHAN_3 + CHAN_4;
        //for(int i=0; i< 30000; i++); 
        //P1OUT = 0x00;
        //for(int i=0; i< 30000; i++); 
      }
    }
    
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_A1_VECTOR
    __interrupt void USCI_A1_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_A1_VECTOR))) USCI_A1_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      P1OUT |= CHAN_1;
    switch(__even_in_range(UCA1IV,USCI_UART_UCTXCPTIFG))
    //switch(__even_in_range(UCA1IV,USCI_UART_UCRXIFG))
      {
      case 0x02: //receive
        rxData = UCA1RXBUF;
        //byteReceived = 1;
        if(actChannel == 2){
          if(rxData > 127)
          {
            P1OUT |= CHAN_1;
          }
          else
          {
            //P1OUT &= ~CHAN_1;
          }
        }
        actChannel++; //increment channel
        break;
      default: break;
      }
      UCA1IFG &= ~UCTXIFG; //clear flag
    }
    

    Anyone ideas what I could try? Thanks a lot!

  • Hi Carsten,

    I apologize for the delay in communication. Have you made any progress on this?

    I would suggest lowering the baud rate to one of the values specified in Table 21-5 of the MSP430FR4xx and MSP430FR2xx Family User's Guide to see if this is a result of the high baud rate. Can you test this out at say 9600 baud and let me know the results?

    Best regards,

    Caleb Overbay

  • I am not able to set the senders baud rate. It is a fix value of this protocol. :(
  • Hi Carsten,

    That's ok. I see you're using idle-line multiprocessor formatting. When the MSP430 detects an idle line the baud rate generator is turned off. This baud rate generator needs to be turned back on when a start condition is present. I have a suspicion that this could be causing the issue since you are running at such a high baud rate. Can you try not using idle-line multiprocessor format as a test and see if you enter the ISR?

    Best regards,
    Caleb Overbay
  • Hi Carsten,

    Have you had a chance to try out the experiment I suggested?

    Best regards
    Caleb Overbay

**Attention** This is a public forum