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.

Voltage inverted UART on MSP430F4270

Other Parts Discussed in Thread: MSP430F4270

Hi everyone,

I'm new to the forums and I look for help on a problem with a software UART implementation.

I'm using an MSP430F4270 and I modified TI's software UART examples to have a voltage INVERTED software UART.

Here are the interesting pieces of code:

void sendRequestSetup(void)
{
    sent = 0;
    UART_TXconfig();
    _bis_SR_register(GIE);
    UARTsendChar('?');
    UARTsendChar(0x0D);
}

void receiveDataSetup(void)
{
    received = 0;
    iM = 0;                                //reset buffer tail pointer

    UART_RXconfig();
    _bis_SR_register(GIE);
}

void setup(void)
{
    WDTCTL = WDTPW + WDTHOLD;                        //stop watchdog
    FLL_CTL0 |= XCAP14PF;                            //set crystal load capacitance
}

void portConfig(void)
{
    P1SEL = UART_TXD + UART_RXD;                     //timer function for TX/RX pins
    P1DIR = UART_TXD;                                //pins configured as output
}

void clearTimerA(void)
{
    TACTL = 0;
    TACCTL0 = 0;
}

void UART_TXconfig(void)
{
    TACTL = TASSEL_2 + MC_2;
    TACCTL0 = 0;
    TACCTL0 |= CCIE;
}

void UART_RXconfig(void)
{
    rxBitCounter = 8;                                                                                     //number of bits to receive
    rxBuffer = 0;
    TACCTL0 = SCS + CM_1 + CCIS_1 + OUTMOD0 + CAP + CCIE;// capture positive edge (Inverted UART!), default output mode LOW (Inverted UART!)
    TACTL = TASSEL_2 + MC_2;                                                              //clock SMCLK, start in continuous mode up
}

void UARTsendChar(unsigned char byte)
{
    while(TACCTL0 & CCIE);            //wait while interrupt flag is enabled - last character sent?
    TACCR0 = TAR;                            //start from current counter value
    TACCR0 += UART_TBIT;
    TACCTL0 = OUTMOD_5;            //output LOW for start (Inverted UART!)
    TACCTL0 |= CCIE;                      //interrupt enabled
    txBuffer = ~byte;                            //byte values are negated (Inverted UART!)
    txBuffer &= 0x0FF;                        //after MSB is all zeros - stop bits are 2 zeros (Inverted UART!)
    txBuffer <<= 1;                              //add room for start bit
    txBuffer += 0x01;                           //start bit is 1 (data will move from LSB to MSB) (Inverted UART!)
    lastByte = byte & 0x7F;                //save copy
    while(TACCTL0 & CCIE);            //only move to the next when the previous was sent
}

#pragma vector = TIMERA0_VECTOR
__interrupt void timer_A0_ISR(void)
{
    static unsigned char txBitCounter = 11;

    TACCR0 += UART_TBIT;                                            //timer offset for next bit

    //RX
    if(TACCTL0 & CCIS0){                                            //ready to receive or transmit?
        P1OUT |= TEST_POINT2;
        if(TACCTL0 & CAP){                                            //capture mode for start bit edge
            TACCTL0 &= ~CAP;
            TACCTL0 &= ~OUTMOD0;
            TACCR0 += UART_HALF_TBIT;
        }else{
            rxBuffer >>= 1;                                            //advance buffer for next bit
            if(TACCTL0 & SCCI)                                        //get bit waiting in receive latch
                rxBuffer |= 0x80;
            rxBitCounter--;
            if(rxBitCounter == 0){                                    //all bits received?
                rxBuffer = ~rxBuffer;                                //negate the outcome (Inverted UART!)
                mBuffer[iM++] = rxBuffer;                                    //save character
                if(((rxBuffer & 0x7F) == 0x0D) | (iM >= M_BUFFER_SIZE)){//all characters received? - check for last character <CR> or buffer overflow
                    TACCTL0 = 0;
                    received = 1;
                    _bic_SR_register_on_exit(GIE);                    //disable global interrupts
                }else{
                    rxBitCounter = 8;                                //number of bits to receive
                    rxBuffer = 0;
                    TACCTL0 |= CAP;                                    //get ready to receive another character
                }
            }
        }
        P1OUT &= ~TEST_POINT2;
    }else{//TX
        P5OUT |= TEST_POINT;
        if(txBitCounter == 0){                                            //something to transmit?
            TACCTL0 &= ~CCIE;                                            //disable interrupt
            txBitCounter = 11;                                            //re-load bit counter
            if(lastByte == 0x0D){                                        //check for last character <CR>
                sent = 1;
            }
        }else{
            if(txBuffer & 0x01) {
                TACCTL0 = OUTMOD_7;                                        //to make the transition between modes without producing a glitch that changes to OUTMOD_0!!!
                TACCTL0 &= ~OUTMOD_5;                                    //output LOW (Inverted UART!)
            }else{
                TACCTL0 = OUTMOD_7;
                TACCTL0 &= ~OUTMOD_1;                                    //output HIGH (Inverted UART!)
            }
            TACCTL0 |= CCIE;
            txBuffer >>= 1;
            txBitCounter--;
        }
        P5OUT &= ~TEST_POINT;
    }
}

My problem is more exactly in the fact that I only get the capture working with these settings (from function UART_RXconfig):

 TACCTL0 = SCS + CM_1 + CCIS_1 + OUTMOD0 + CAP + CCIE;

which makes OUTMODx=001 -> which is mode SET, and produces a HIGH state when the TX pin is idle (TX needs to idle in LOW state since it's an voltage inverted UART).

My question is then, is there a dependence between the CAPTURE mode and the OUTPUT settings on TIMER_A?

Looking at the block diagram of the capture/compare blocks in the datasheet I don't seem to find one...

Thanks,

David

  • David Copeto said:
                    TACCTL0 = OUTMOD_7;
                    TACCTL0 &= ~OUTMOD_1;                                    //output HIGH (Inverted UART!)

    This looks rather odd. First, i twill clear all bits except for the OUTMOD bits (which likely isn't intended) and then clear the bits for OUTMOD_1.
    I guess the original code was clearign all OUTMOD_7 bits (not to end OUTMOD 7, but to just clear the bits so the correct OUTMOD can be set with the next instruction.

    However, to not produce a glitch, when switching ot a new OUTMODE, why not using

    TACCTL0 = (TACCTL0 &~OUTMOD_7) | OUTMOD_x;

    But if I remember a TI example correctly (not necessarily the one you used as starting poiont), the OUTMODES were chosen so that setting/clearing a single bit was performing a switch between the two requried modes. Without touching the other two bits in the OUTMODx bitfield.

    David Copeto said:
    My question is then, is there a dependence between the CAPTURE mode and the OUTPUT settings on TIMER_A?

    Only if your code forms it. :) Well, ther eis one dependency: if you are in capture mode, no OUTMODe is available on the same CCR unit. Obviously. :)

  • Thanks for your reply :)


    Jens-Michael Gross said:

    This looks rather odd. First, i twill clear all bits except for the OUTMOD bits (which likely isn't intended) and then clear the bits for OUTMOD_1.
    I guess the original code was clearign all OUTMOD_7 bits (not to end OUTMOD 7, but to just clear the bits so the correct OUTMOD can be set with the next instruction.

    However, to not produce a glitch, when switching ot a new OUTMODE, why not using

    TACCTL0 = (TACCTL0 &~OUTMOD_7) | OUTMOD_x;

    You are right, it was already working right before but it looks more clear like that. I think I left it like that after trying so many modes... :/

    Jens-Michael Gross said:

    But if I remember a TI example correctly (not necessarily the one you used as starting poiont), the OUTMODES were chosen so that setting/clearing a single bit was performing a switch between the two requried modes. Without touching the other two bits in the OUTMODx bitfield.

    The TI example switches between modes that are mutually exclusive and that's why no "cleaning" (ORing with OUTMOD_7 or ANDing with ~OUTMOD_7) is needed in seems to me.

    Jens-Michael Gross said:

    Well, ther eis one dependency: if you are in capture mode, no OUTMODe is available on the same CCR unit. Obviously. :)

    This is the point! "No OUTMODE is available" means what? At which state is the OUT pin left? I needed it to stay LOW.

    Anyway, I decided to have RX and TX in two separated cap/comp blocks. I have it now working fine that way.

  • David Copeto said:
    This is the point! "No OUTMODE is available" means what? At which state is the OUT pin left? I needed it to stay LOW.

    On most MSPs, there is only one pin assigned for both operations: outputing the PWM in compare mode or getting the trigger in capture mode. So if in capture mdoe, the pin is input and in compare mode the pin is output (if needed at all). Both at the same time is therefore not possible. However, the direction of the port pin is controlled by teh PxDIR bit and not the CAP bit. So you cn go from capture into compare mode and still won't output anything. (if requiring compare mode only for internal timing and IRQ generation)

    However, on some MSPs, there are multiple port pins assigned, some even only for one of the two directions. Also, the MSPs with por tmapping capability can map the functions to more than oen pin.

    My best guess is that in captur emode, teh OUT bit controls the state of the output signal. However, it is only a guess. I never tried. And I don't know whether the OUT bit updates when the output signal is changed by an OUTMOD event.

**Attention** This is a public forum