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.

MSP430 software UART with parity detection in receiver side?

Other Parts Discussed in Thread: MSP430G2553

I am currently working on (Timer A0) software based half duplex UART in MSP430G2553. I have one doubt how is parity in receiver side works. Can you guys help me in detecting parity and removing stop bit.

  • The parity bit is just an additional bit after the data bits.
    The stop bit is just a constant 1 bit after that.

    How to handle them depends on the structure of your existing code. Show it.

  • #include <msp430.h>
    #include "msp430g2553.h"
    #include "inttypes.h"
    #include "stdbool.h"



    // MSP430g2553 Signal / PINs
    #define TXD BIT4 // TXD an P1.4
    #define RXD BIT3 // RXD an P1.5
    #define USB BIT3

    // Software UART
    #define BITTIME 1666 // 9600 Baud, SMCLK=8MHz (16MHz/9600)=833
    #define BITTIME_5 833 // BITTIME / 2
    #define BITTIME_1 416 // 4tel eines bits
    #define LED_GREEN BIT6
    #define LED_RED BIT0

    /* ---- Global Varable ------------------------------------------------------------------------------------ */
    unsigned int BitCnt; // Bit count, used when transmitting byte
    volatile uint16_t TXByte; // Value sent over UART when Transmit() is called
    unsigned int RXByte; // Value recieved once hasRecieved is set
    unsigned int checkingcount =0;
    uint16_t bytequality=0;
    bool isReceiving;
    bool hasReceived;
    unsigned int subsampleclk = 0;
    unsigned int bitquality[12];
    unsigned int bit =0;
    unsigned char checkingChar;
    unsigned char checked;

    unsigned int FIFO_array[13];
    /* ---- Prototypes ------------------------------------------------------------------------------------------- */
    void putChar (unsigned char checked);
    void printfEasy (char *s);
    unsigned int parity = 0;

    void main (void)
    {
    WDTCTL = WDTPW + WDTHOLD; // stop WDT
    BCSCTL1 = CALBC1_16MHZ; // set range
    DCOCTL = CALDCO_16MHZ; // subsampleclk = DCO = 1MHz
    P2DIR |= TXD; // TXD als Ausgang
    P1DIR |= USB;
    P2IES |= RXD; // RXD Hi/lo edge interrupt
    P2IFG &= ~RXD; // clear RXD (flag) before enabling interrupt
    P2IE |= RXD; // Enable RXD interrupt

    // ---- Soft. UART Timer Setup ----
    isReceiving = false; // set initial values
    hasReceived = false;
    _bis_SR_register (GIE); // interrupts enabledg
    RXByte = 0x66;

    printfEasy ("Hello World\n\r");

    while (1) {
    if (hasReceived) { // Zeichen empfangen ?
    hasReceived = false; // clear "hasReceived" flag
    putChar (RXByte); // echo received Byte
    }
    if (~hasReceived) __bis_SR_register (CPUOFF + GIE);
    }

    }

    /* ---- simple printf ---------------------------------------------------------------------------------------- */
    void printfEasy (char *s)
    {
    while (*s != '\0')
    {
    putChar (*s++);
    }
    }

    /* ---- simple putChar --------------------------------------------------------------------------------------- */
    void putChar (unsigned char checked)
    {
    checkingChar =~ checked;
    while (isReceiving); // Receiver busy ?
    BitCnt = 12;
    TA0CCTL0 = OUT;
    TA0CCR0 = TAR;
    TACTL = TASSEL_2 + ID_0 + MC_2; // Initialize compare register
    TA0CCR0 += BITTIME_1;
    parity = 0; // for even Parity
    int i;
    for( i = 0; i < 8; i++)
    {
    parity = (parity^(checked>>1))&(1>>0);
    }
    parity &=~ parity;
    TXByte = (((uint16_t)0<<10)|((uint16_t)parity<<9)|((uint16_t)checkingChar<<1)|(1<<0)); // stop // parity // data // start
    bit=0;
    subsampleclk=0;
    bytequality=0;
    TA0CCTL0 = OUTMOD0 + CCIE; // Enable Timer Interrupt -- Set signal, intial value, enable interrupts
    while (TA0CCTL0 & CCIE); // Warten bis alle BIT's ausgesendet sind
    // todo do smoething with
    //bytequality
    }
    //------------------------------------------------------------------------------------


    /* ---- Start receive timer and disable any current transmission --------------------------------------------- */
    #pragma vector=PORT1_VECTOR
    __interrupt void Port_1 (void)
    {
    isReceiving = true;
    P2IE &= ~RXD; // Disable RXD interrupt
    P2IFG &= ~RXD; // Clear RXD IFG (interrupt flag)
    TACTL = TASSEL_2 + ID_0 + MC_2; // subsampleclk, continuous mode
    TA0CCR0 = TAR; // Compare Register initialisieren
    TA0CCR0 += BITTIME_5; // BIT Zeit/2 aufaddieren
    TA0CCTL0 = OUTMOD1 + CCIE; // Disable TX and enable interrupts
    RXByte = 0; // RXByte initialisieren
    BitCnt = 11; // BitCounter 8 BIT + ST + ST
    }

    /* ---- Timer interrupt routine, transmitting and receiving bytes. ------------------------------------------- */
    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void Timer_A0_ISR (void)
    {
    if (!isReceiving)
    {
    // we are Transmitting
    TA0CCR0 += BITTIME_1; // BIT Zeit aufaddieren
    // what to do now?
    if (subsampleclk==0)
    {
    bitquality[bit]=0;
    // set output
    // becuase its the beginning of a bit
    checkingcount = TXByte & (1>>bit);
    if (TXByte & (1<<bit))
    {
    //set tx low = rec
    P2OUT&=~TXD;
    P1OUT |= USB;
    }
    else
    {
    //set tx hgh = dom
    P2OUT |= TXD;
    P2OUT &=~ USB;
    }
    }
    // now quality control
    //if (( tx is low and RX is low) or (tx is high and rx is high)) // that is "good", so we increase bitqual
    if ( (!(P2OUT & TXD) && !(P2IN & RXD)) || ((P2OUT & TXD) && (P2IN & RXD)) )
    {
    // increase weighted by position in bit
    if (subsampleclk == 0) bitquality[bit] += 0;
    else if (subsampleclk == 1) bitquality[bit] += 4;
    else if (subsampleclk == 2) bitquality[bit] += 8;
    else if (subsampleclk == 3) bitquality[bit] += 4;
    }
    // for next loop
    subsampleclk++;
    if (subsampleclk==4)
    {
    // bit finished
    // calculate bytequality
    uint8_t ii;
    for (ii=0; ii<12; ii++)
    {
    bytequality+=bitquality[ii];
    }
    bytequality/=12;
    subsampleclk=0;
    bit++;
    if (bit>11)
    {
    // char finished
    TA0CCTL0 &= ~ CCIE; // Disable interrupt
    }
    }
    }
    else
    {
    TA0CCR0 += BITTIME; // BIT Zeit aufaddieren
    if (BitCnt == 0)
    {
    TA0CCTL0 &= ~ CCIE; // Disable interrupt
    isReceiving = false;
    P2IFG &= ~RXD; // clear RXD IFG (interrupt flag)
    P2IE |= RXD; // enable RXD interrupt
    if ((RXByte & 0x401) == 0x400)
    { // START/STOP BIT
    RXByte >>= 1; // Remove START BIT
    RXByte &= 0xFF; // Remove STOP BIT
    hasReceived = true;
    }
    __bic_SR_register_on_exit (CPUOFF); // Enable CPU so the main while loop continues
    }
    else
    {
    if (((P2IN & RXD) == RXD))
    {
    RXByte |= 0xe00; // If bit is set? Set the value in RXByte
    }
    RXByte >>= 1; // BIT's einschieben

    BitCnt --;
    }
    }
    }

    My frame sequence is 1+8+1+2 i.e 1 Start Bit + 8Databits+ 1 Parity + 2 Stopbits
  • You need to add the parity bit calculation after the // START/STOP BIT comment.
    The data bits and the received parity bit are stored in the RXByte variable.

    What exactly is the problem?

**Attention** This is a public forum