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.

MSP430F2416 - UART1 problem-> no output at TeraTerm

Other Parts Discussed in Thread: MSP430F2416, MAX232

Hello,

 

I just wanted to make sure that I have set up the clocks and other things correctly.

I am working on MSP430F2416 , UART1 with no hardware flow control. Still I have set CTS and RTS input and output low. They are left unconnected/floating on PCB. MCU is connected to Vcc, GND, UART-TX, UART-RX (115200 baud rate).

//////////////////////////CODE - START/////////////////////////////////////////////////////////////////////////////////////////

#include "msp430f2416.h"

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

    // Setup Clocks for DCO = 16 MHz
    // For DCO frequency = 16 MHz, RSELx = 15, DCOx = 7, MODx = 0

    DCOCTL = DCO2 + DCO1 + DCO0;
   
    BCSCTL1 = XT2OFF + RSEL3 + RSEL2 + RSEL1 + RSEL0;    
   
    // Do 'Oscillator Fault Interrupt Disable' and 'Oscillator Fault Interrupt Flag Clear' have to be done explicitely?????
   
    // Configure pins
    P3SEL = 0xc0; // Primary peripheral module function is selected for pins P3.6 (UCA1TXD), P3.7(UCA1RXD)
    P3DIR = 0x40; // All pins of port 3 are as input and only P3.6 (UCA1TXD) needs to be set as output
   
    P1SEL = 0x00;     //  Select pin 1.4 for I/O functions
    P1DIR = 0x00;     // Change CTS pin 1.4 to input direction
    P1IN = 0x00;    // Change CTS pin 1.4 to input always low
   
    P4SEL = 0x00;    // Select pin 4.3 for I/O functions
    P4DIR = 0xff;    // Change RTS pin 4.3 to output direction
    P4OUT = 0x00;    // Change RTS pin 4.3 to output always low

    // UART1 settings -> no parity, 8-bit, 1 stop bit, UART mode; hence no changes in UCA1CTL0
    UCA1CTL0 = 0x00;
   
    // Resets UART1 and selects SMLK as clock source
    UCA1CTL1 = UCSSEL1 + UCSSEL0 + UCSWRST;       

    // Setup Baud Rate/Modulation control of clock - 115200 baud
    UCA1BR0 = 138;        // Prescalar is 138 (BRCLK/BaudRate = 16,000,000/115200 = 138)
    UCA1BR1 = 0;
    UCA1MCTL = 0x00;     // No Modulation Necessary!
   
    // Initialize USCI state machine
    UCA1CTL1 &= ~UCSWRST;
       
    // Enable USCI_A1 TX & RX interrupts
    UC1IE = UCA1TXIE + UCA1RXIE;
   
    UC1IFG = 0x00; // Clearing UCSWRST sets TX interrupt flag which needs to be cleared
                                 // or it calls TX interrupt even when there is no transmission
   
    // Enable Interrupts
    __bis_SR_register(GIE);

    while(1)
    {
        UCA1TXBUF = 'u';
        for(i=0;i<10000;i++);    // Delay
    }

}

#pragma vector=USCIAB1TX_VECTOR
__interrupt void usciab1_tx(void)
{
}

#pragma vector=USCIAB1RX_VECTOR
__interrupt void usciab1_rx(void)
{           
}

//////////////////////////CODE - END/////////////////////////////////////////////////////////////////////////////////////////

 

I would really appreciate if someone can check my Clock settings and UART initialization. My hardware for hyperterminal / TeraTerm is working properly. However there seems to be some problem with setting up MCU/UART.

 

Thank you for your help.

 

Best,

Janet

  • Hello Janet,

     

    If you left the handshaking signals floating on PCB then you do not handle them in software.

    Why are you writing to read only register PxIN? It will increase your current consumption. Just check the user guide (Digital I/O section).

    If you are not using transmit using interrupt then do not enable transmit interrupt.

    Check for buffer to be empty before transmitting a new value.

     

    Regards,

    Harshal

  • Janet D said:
    // Do 'Oscillator Fault Interrupt Disable' and 'Oscillator Fault Interrupt Flag Clear' have to be done explicitely?????


    If you disable the fault interupt, you can ignore the interrupt flags.
    Threre are some cross-effects. If you disable the external oscillator because you don't have one, this may reduce power consumption. Also, if you then clear the fault flag, it won't come up. If you don't disable the oscillator, the fault flag will come up again. But if the fault interrupt is disabled, the rest belongs to the 'tuning' category :)

    Janet D said:
    // For DCO frequency = 16 MHz, RSELx = 15, DCOx = 7, MODx = 0

    Where do you get this information? The DCO as well as the RSEL settings have a BIG tolerance. With these settings, the resulting DCO frequency can be as low as 8MHz or beyond the allowed maximum MSP frequency.
    Even if you're lucky and tolerances are next to zero, the long-term stability (temperature coeficient, drift etc.)  disqualify a plain DCO as clock source for UART usage. (In a different thread, we discovered that a difference of +-4% breaks UART communication. THis includes both, MSP and PC tolerances, which may add)

    Some MSPs have calibration data stored in INFOA segment or a separate TLV structure. There the settings for 1,4,8MHz are stored for each individual MSP. Other MSPs have an FLL hardware that constantly adjusts the DCO based on an external, stable low frequency source such as a clock crystal.
    If you can get a trustworthy, stable external clock source (1 second signal, or 1kHz or whatever), you can even write a software function that keeps the DCO inside the required tolerances. I don't have the 2416 datasheet (but you should have if you use this processor), but on a 23x0 device, your DCO settings can result in 16MHz to 26MHz DCO frequency. Both extremes are equally possible and the reality is likely to be somewhere around 20MHz. Way too much for the MSP (the 23x0 allows only 12MHz @2.7V and 16MHz@3.3V supply voltage)

    Janet D said:
    P1DIR = 0x00;     // Change CTS pin 1.4 to input direction
        P1IN = 0x00;    // Change CTS pin 1.4 to input always low


    As already pointed out, this makes not much sense. You don't use 1.4 at all and if it is not required to EMIT low on this line (if, then change the pin to output), just skip it.
    Also, you are (mis)configuring ALL P1 pins with this write, not just P1.4.

    Janet D said:
    P4DIR = 0xff;    // Change RTS pin 4.3 to output direction
        P4OUT = 0x00;    // Change RTS pin 4.3 to output always low


    Here, you are switching ALL P4 pins to low output. Not just P4.3.

    Janet D said:
    UCA1CTL0 = 0x00;    
        // Resets UART1 and selects SMLK as clock source
        UCA1CTL1 = UCSSEL1 + UCSSEL0 + UCSWRST;         //


    This only works by coincidence. Because UCSWRST is set after a device boot. I twon't work if you are reconfiguring the USART later.
    The firs tline when changing USCI configuration should be
        UCxyCTL1 |= UCSWRST;
    UCSWRST needs to be set BEFORE any other change is done (including setting UCA1CTL0). You even may not set it together with the other bits in UCA1CTL1 (but you must of course keep it set when altering the other bits)

    Janet D said:
      // Enable USCI_A1 TX & RX interrupts
        UC1IE = UCA1TXIE + UCA1RXIE;
        UC1IFG = 0x00; // Clearing UCSWRST sets TX interrupt flag which needs to be cleared
                                     // or it calls TX interrupt even when there is no transmission

    First, you should clear and IFG before you set the IE bits. For every module, not just the USCI.
    And in case of the USCI thing sshould be done differently. If there's nothing to be sent, clear the TXIE bit.
    Using a TX ISR makes only sense if you're sending 'in the background', with a buffer that contains the data to be sent.

    So once you filled that buffer, the the TXIE bit and immediately the ISR will be called (twice, if TXBUF and TX shift register are empty), and called again each time a byte has been sent. In fact, TXIFG is set as soon as TXBUF is empty, even if the byte wou put into it is still being sent.
    Once the TXIFG detects that there are no more bytes to send, it should clear the TXIE bit, so there is no more TX interrupt until the buffer is filled again and the TXIE bit is set once more.

    Janet D said:
           UCA1TXBUF = 'u';
            for(i=0;i<10000;i++);    // Delay 


    If you're sending busy-waiting (not in the background with a buffer) , then leave both IE bits clear. And in your sending loop, check for TXIFG. If it's clear, TXBUF is still filled and the byte in it ha snot yet started sending. Once TXIFG is set, you can oput the next byte in. At this point, the last byte you put into TXBUF has not necessarily been sent yet. If you want to ensure that the transmission was complete, check the UCBUSY bit in UCxySTAT. If it is clear, all ist sent and nothing is currently received.

    Don't use an empty for-loop as a delay. It may be considered dead code (does nothing but setting the loop variable to the final value) and will be eliminated by any optimizing compiler. If you need a delay, either use a timer (that's what they are made for: counting precise delays) or use the _delay_cycles() intrinsic for a given number of processor cycles to be 'wasted'.
    I know that even TI has used for loops for delays, but I guess these examples have been written in the stone-age of optimizing compilers.

    But there is a completely different problem, not related to your source code:

    If you leave RTS/CTS and DTR/DSR unconnected, you don't need to configure them at all. The MSP UART hardware has no built-in support for these signals. Either you handle them in software as normal I/O pins or you ignore them.

    Anyway, the PC side most likely needs the CTS line high or it won't accept any data from the MSP even IF your software is 100% working and the MSP is correctly sending. The PC just won't hear. So if you have something like the MAX232 on your PCB for interfacing the PC, you'll need to not only connect one input to the MSPs TX pin, but also a second input to VCC and the corresponding output to the CTS line of the cable, OR you must short RTS/CTS and DTR/DSR on the cable (or on the connector). Don't leave CTS and DSR unconnected on the cable.

     

**Attention** This is a public forum