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.

Software UART on MSP430F2274

Other Parts Discussed in Thread: MSP430F2274

Hi,

I have one board with MSP430F2274 which I want to use to build some simple testing environment. It is connected with other MCU by ports P3.0, P3.1, P3.2, P3.3. I would like to use two of those ports to create software UART interface. I know that TAx or TBx are not available on these ports so here comes the question - is there any other way to implement this functionality? Speed doesn't matter and it can be even 110 bauds per sec - actually I have to send max 5 bytes per second but it has to be via UART. 

I appreciate any help/suggestions/etc. Thank you in advance.

 

Best regards,

Lukasz Spas

  • Hello Lukasz,

    Here is a similar post to yours where they were successful in implementing a software UART.  You should be able to adapt it to your MCU version.

    http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/254393.aspx

    Thanks,

  •  Hi,

    Thank you for your answer.

    I saw those examples before but they won't work for me because they uses TA0, TA1 registers which are connected to P1.1 and P1.2. Unfortunatelly, I cannot use those ports so it's impossible to adapt those examples. I tried to set 0/1 state on designated port when timers event is being raised. However, it doesn't work well for the lowest speed (110 bauds). I tried also to callibrate UART's frequency by increatsing TICKS_PER_BIT every 8th Byte of data and I was sending "01010101" sequentions. I wasn't even close enough to this value. I suppose that it can be because of my oscilator settings (please, check below). On my board I don't have external oscilator soldered.

    Could you tell me what I'm doing wrong? Are there any other interupts which could replace missing TA0 TA1 registers?
    Thank you for any help. Below I attached my code.

    Best regards,
    Lukasz Spas



    Here is oscillator initialization code:

    //
    // Initialize Oscillator
    //

    if (CALBC1_8MHZ == 0xFF || CALDCO_8MHZ == 0xFF)
    {
      while(1); // Stop if calibration constants erased
    }
    BCSCTL1 = CALBC1_1MHZ; // Set DCO = 1MHz for MCLK
    DCOCTL = CALDCO_1MHZ;
    BCSCTL2 |= DIVS_1; // SMCLK = DCO/2 (0.5MHz)
    BCSCTL3 |= LFXT1S_2; // Use VLO for ACLK



    Here are UART methods:

    long i = 8;
    void SoftSerial_xmit(uint8_t c)
    {
      // SoftSerial_TX_ISR disables the interrupt flag when it has sent
      // the final data bit. While a transmit is in progress the
      // interrupt is enabled


      while (TACCTL0 & CCIE) {
        ; // wait for previous xmit to finish
      }

      if (!(--i))
      {
        TICKS_PER_BIT += 1;
        i = 8;
      }

      TACCR0 = TAR; // resync with current TIMERA counter
      TACCR0 += TICKS_PER_BIT; // set next start bit edge time
      TACCTL0 = OUTMOD0 | CCIE; // set TX_PIN HIGH on EQU0 and re-enable interrupts

      register unsigned int next;
      next = c | STOPBITS_1; // set data and add 1 stop bit, use 0x0300 for 2 stop bits
      next <<= 1; // add the start bit '0'

      USARTTXBUF=next; // set bits to sent
    }

    #ifndef __GNUC__
    #pragma vector = TIMERA0_VECTOR
    __interrupt
    #else

    __attribute__((interrupt(TIMERA0_VECTOR)))
    #endif
    void SoftSerial_TX_ISR(void)
    {
      TACCR0 += TICKS_PER_BIT; // setup next time to send a bit, OUT will be set then

      //TACCTL0 |= OUTMOD2; // reset OUT (set to 0) OUTMOD2|OUTMOD0 (0b101)
      //if ( USARTTXBUF & 0x01 ) { // look at LSB if 1 then set OUT high
      // TACCTL0 &= ~OUTMOD2; // set OUT (set to 1) OUTMOD0 (0b001)
      //}


      if ( (USARTTXBUF & 0x01 )) { // look at LSB if 1 then set OUT high
        P3OUT |= TX_PIN; // set OUT (set to 1) OUTMOD0 (0b001)
      } else {
        P3OUT &= ~TX_PIN; // reset OUT (set to 0) OUTMOD2|OUTMOD0 (0b101)
      }

      if (!(USARTTXBUF >>= 1)) { // All data bits transmitted ?
        TACCTL0 &= ~CCIE; // disable interrupt, indicates we are done
      }
    }

  • Does P3 not have interrupt capability? I would think that you could change the original code to:

    #define TXD BIT1 // TXD on P3.1
    #define RXD BIT2 // RXD on P3.2

    Then replace the configuration with
    P3SEL |= TXD;
    P3DIR |= TXD;
     
    P3IES |= RXD; // RXD Hi/lo edge interrupt
    P3IFG &= ~RXD; // Clear RXD (flag) before enabling interrupt
    P3IE |= RXD; // Enable RXD interrupt

    Unfortunately I am not familiar with the MSP430, only the UART protocal.

    If that solution cannot work with this MCU, I am sure someone else can provide you with an alternative solution.

    Thanks,
  • I was not refering to RX interface implementation but frequency mismatch or some frequency errors in this implementation. I'm testing this code via USB port on my laptop and I cannot find good frequency for this chip to be able to receive data without any errors - I assumed that it's caused by the way I'm setting 0/1 state on P3.1 which may have some kind of delay or frequency accuracy.

    Do anybody have any idea how to improve this code to be able to send data via UART via one port  of P3.0-P3.3 ports?

  •  Another thing is that P3 doesn't support interrupts on this chip. Interrupts are supported only on P1 and P2. I guess that in this case full-duplex UART is unimplementable, right?

     I think about below implementation:

     - RX: there is an infinite loop which waits for data's start-bit. If it occurs it turns on TIMERB0 interrupts for reading following 8 bits of data & stop-bit. When finished   TIMERB0  interrupt will be disabled.

     - TX: there will be routine configured to send some small amount of data every 1-2 seconds (lets say based on TIMERA1 interrupts). Then this routine will activate TIMERA0 interrupts for sending single bits of data (like in previously presented code). 

    However, I'm afraid that in this case I'd have only 1 UART protocol while I need two of them on the same chip. 

    Do you think this scenario will work? Do you have any other idea? 

  • Lukasz Spas said:
    I assumed that it's caused by the way I'm setting 0/1 state on P3.1 which may have some kind of delay or frequency accuracy.

    The usual implementation of the software UART uses TAx.0/TAx.1 for some reason. Without the hardware support of the capture and compare units of the timer, your code execution time adds a jitter or even a drift to the timing. This may even differ depending on the different way the code flows for 0 or 1 bits.

    On the TX side, you can eliminate this by abusing UCB0 as a pseudo-UART. Program the USCI for SPI mode and the desired baudrate, then add start bit (0) to your byte, add 7 stop bits and send two bytes through the USCI. Yes, it wastes 6 bits but generates a precise output timing without noticeable CPU load. P3.1 (UCBSIMO) would be the pin to use. UCB0CLK and UCBSOMI don' tneed to be in modul emdoe and may be used as GPIO still.

    Not having to handle the TX may allow a better implementation of the RX side.  However, P3 doesn't have any interrupt capability. Nor does any of the module funcitons available on P3.
    You could use P4, TimerB as a replacement for TimerA. TB.0/TB.1 is as good for this purpose as TA0.0/TA0.1 or TA1.0/TA1.1. Unless you also used this too for something else.

**Attention** This is a public forum