Skip to main content
cnocbarra
Visitor II
January 15, 2011
Question

Setting up RS232 USART on STM32-P103

  • January 15, 2011
  • 20 replies
  • 3978 views
Posted on January 15, 2011 at 23:47

Setting up RS232 USART on STM32-P103

    This topic has been closed for replies.

    20 replies

    Tesla DeLorean
    Guru
    May 17, 2011
    Posted on May 17, 2011 at 14:21

    This board?

    http://www.olimex.com/dev/pdf/ARM/ST/STM32-P103.pdf

    Aren't there some solder bridge jumpers on the board for the RTS and CTS?

    If it's a coding issue you'll need to post some code for review. At least one of the CTS/RTS pairs has an errata with a CAN bus controller. I don't recall which, you'll have to review the errata yourself. You have to park the unused CAN some place else using the ReMap function.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    sara2
    Associate
    August 31, 2011
    Posted on August 31, 2011 at 11:12

    The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6aP&d=%2Fa%2F0X0000000brF%2FrTAPpFPZ.eKqMqjKRix65MYbr7KNVCttuRUjDcVUWHk&asPdf=false
    sara2
    Associate
    August 31, 2011
    Posted on August 31, 2011 at 14:16

    I just found out that the USART2 cannot receive a string longer than 3 characters, can this be possible?? when I try sending 'aaa' it works fine with this piece of code I wrote:

    int main(void)

    { //(Some configuration missing)

    unsigned int i = 0;

            unsigned int j = 0;

            unsigned char ascii = '0';

            unsigned char buf[128];

            int size= 128;

            char szInput[] = ''aaa'';

            char inp[50] = '''';

            int countchar (char []);

            int numchar;

            unsigned char gottenCharacter = '\0';        // character from USART

            while (1)                                   // Loop forever

            {

                puts2(szInput);

                numchar = countchar (szInput);

                j = 0;

                putChar3(numchar);

                while (numchar != 0)

                {

                    numchar--;

                    inp[j] = getChar2();

                    j++;

                }

                puts3(inp);

                for(i=0; i<0xFFFFF; i++);               // wait

            }

            return 0;// end while

    }

    but as soon as I increase the number of characters to 'aaaa' I can see how the USART2 tx sends the 4 a's and I can see how the USART3 sends a number going out (putChar3(numchar);) but then it gets stuck in the receiving loop...

    Why can this be?? Have I done anything wrong??

    Also, is there any other way I can see the inputs and outputs of the ports apart from the oscilloscope? A way to see the actual values of what it has been sent??

    Sorry if some of these questions are easy for some people, I am really just starting...

    Thanks!

    Tesla DeLorean
    Guru
    August 31, 2011
    Posted on August 31, 2011 at 17:38

    Can anyone see why it gets stuck in receiving a string?? It works perfectly sending a single character?? Thanks for your help!

    There are several problems here. One of the basic ones is that USART can't hold multiple characters, buffering them for you to read later. I doesn't work like that, the characters move through the pipe one at a time. So you can't send three characters out of USART Tx, and then expect to be able to pull three characters from the USART Rx.
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Tesla DeLorean
    Guru
    August 31, 2011
    Posted on August 31, 2011 at 17:48

    int putChar2 (int c)

    {while (!(USART2->SR & USART_FLAG_TXE));

        USART2->DR = (c & 0x1FF);

        return (c);

    }

    int putChar3 (int c)

    {while (!(USART3->SR & USART_FLAG_TXE));

        USART3->DR = (c & 0x1FF);

        return (c);

    }

    int getChar2 (void)

    {while (!(USART2->SR & USART_FLAG_RXNE));

        return ((int)(USART2->DR & 0x1FF));

    }

    int main(void)

    {

        *NVIC_CCR = *NVIC_CCR | 0x200; // Set STKALIGN in NVIC

    // ENable clocks BEFORE using/configuring peripherals that expect them to be running

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

            // Configure PC.12 as output push-pull (LED)

            GPIO_WriteBit(GPIOC,GPIO_Pin_12,Bit_SET);

            GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_12;

            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

            GPIO_Init(GPIOC, &GPIO_InitStructure);

            // Configure USART2 Tx (PA.2) as alternate function push-pull

            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

            GPIO_Init(GPIOA, &GPIO_InitStructure);

            // Configure USART2 Rx (PA.3) as input floating

            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

            GPIO_Init(GPIOA, &GPIO_InitStructure);

            // Configure USART3 Tx (PB.10) as alternate function push-pull

            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

            GPIO_Init(GPIOB, &GPIO_InitStructure);

            // enable UART peripheral by activating clock

            RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

            RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

            // USART2 configuration

            USART2_InitStructure.USART_BaudRate = 38400;

            USART2_InitStructure.USART_WordLength = USART_WordLength_8b;  //Word Length = 8 Bits

            USART2_InitStructure.USART_StopBits = USART_StopBits_1;  //Two Stop Bit

            USART2_InitStructure.USART_Parity = USART_Parity_No ;   //No parity

            USART2_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  //Hardware flow control disabled (RTS and CTS signals)

            USART2_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  //Receive and transmit enabled

            // USART3 configuration

            USART3_InitStructure.USART_BaudRate = 38400;

            USART3_InitStructure.USART_WordLength = USART_WordLength_8b;  //Word Length = 8 Bits

            USART3_InitStructure.USART_StopBits = USART_StopBits_1;  //Two Stop Bit

            USART3_InitStructure.USART_Parity = USART_Parity_No ;   //No parity

            USART3_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  //Hardware flow control disabled (RTS and CTS signals)

            USART3_InitStructure.USART_Mode = USART_Mode_Tx;  //Transmit enabled

            //Configure USARTs

            USART_Init(USART2,&USART2_InitStructure);

            USART_Init(USART3,&USART3_InitStructure);

           

            //Enable USARTs

            USART_Cmd(USART2, ENABLE);

            USART_Cmd(USART3, ENABLE);

            unsigned int i = 0;

            char str[] = ''Welcome to wherever you are\r\n'';

            while (1)                                   // Loop forever

            {

              char *s = str;

              while(*s)

              {

                putChar2((char)*s++); // Send character from string to USART2 TX

                putChar3(getChar2()); // Send character from USART2 RX to USART3 TX

              }

              for(i=0; i<0xFFFFF; i++);               // wait

            }

            return 0;// end while

    }

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    sara2
    Associate
    September 1, 2011
    Posted on September 01, 2011 at 15:44

    Clive1!I cant thank you enough for that answer...I cannot believe it was that simple in the end...

    However I have another question that you might be able to answer, the loop-back test was just to see if I could sent and receive data, but the data I need to receive is really from an NMEA input. Why does it not decode the characters received from the NMEA input if it does from the string already sent??

    Is is anything really stupid that I am missing or is it actually I need to start learning from the beggining??

    Can it be the baud rate? I am generating NMEA data at 4800 baud...

    Thanks for your patience!
    Tesla DeLorean
    Guru
    September 1, 2011
    Posted on September 01, 2011 at 19:24

    NMEA can often be at 4800 8N1, but I tend to work with receivers in the 9600 or 38400 rates, based on the amount of data they are sending, latency, or the update rates I want to use.

    Really to deal with stream data like this you need to build an interrupt driven serial layer, with reasonably large software fifo's or ring buffers. You're foreground task then pulls data and accumulates NMEA sentence data, and then passes that to a routine that parses out the fields in those sentences, and processes the GPGLL, GPGSA, GPGGA, GPGSV, etc records.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    sara2
    Associate
    September 2, 2011
    Posted on September 02, 2011 at 13:46

    Ok....this is a bit too advanced for me. I think I am going to start taking little step before starting running...

    First...how can I save the sentences that I receive from the USART2 in a little buffer to start decoding them? At the moment I can see that every character that is received is resent again.

    I got this pieces of code that I think make the interrupts but I might be very wrong...:

    void USART2_IRQHandler (void)

    {

        volatile unsigned int IIR;

        struct buf_st *p;

        char receivedChar;

        IIR = USART2->SR;

        if (IIR & USART_FLAG_RXNE)

        {                  // read interrupt   Receive

            USART2->SR &= ~USART_FLAG_RXNE;             // clear interrupt

            p = &rbuf2;

            if (((p->in - p->out) & ~(RBUF_SIZE-1)) == 0)

            {

                receivedChar = (USART2->DR & 0x1FF);

                p->buf [p->in & (RBUF_SIZE-1)] = receivedChar;// (USART2->DR & 0x1FF);    // put into buffer

                if(receivedChar == '\n')

                    newlineDetected2 = 1;

                p->in++;

            }

        }

        if (IIR & USART_FLAG_TXE)                   // Transmit (Send)

        {                     

            USART2->SR &= ~USART_FLAG_TXE;           // clear interrupt

            p = &tbuf2;

            if (p->in != p->out)                   // stuff to send

            {                     

                USART2->DR = (p->buf [p->out & (TBUF_SIZE-1)] & 0x1FF);

                p->out++;

                tx_restart2 = 0;

            }

            else                                   // stuff to send (buffer empty)

            {                                     

                tx_restart2 = 1;

                USART2->CR1 &= ~USART_FLAG_TXE;       // disable TX interrupt if nothing to send

            }

        }

    }

    And then I have changed the sender and receiver to:

    int putChar2 (int c)

    {

        struct buf_st *p = &tbuf2;

        if (SIO_TBUFLEN2 >= TBUF_SIZE)                   // If the buffer is full, return an error value

            return (-1);

        p->buf [p->in & (TBUF_SIZE - 1)] = c;           // Add data to the transmit buffer.

        p->in++;

        if (tx_restart2)

        {                                              // If transmit interrupt is disabled, enable it

            tx_restart2 = 0;

            USART2->CR1 |= USART_FLAG_TXE;               // enable TX interrupt

        }

        return (0);

    }

    and

    int getChar2 (void)

    {

        struct buf_st *p = &rbuf2;

        if (SIO_RBUFLEN2 == 0)

            return (-1);

        return (p->buf [(p->out++) & (RBUF_SIZE - 1)]);

    }

    Can I with this make a buffer and keep the sentences for long enough for the system to decode them?

    Thanks again for your patience!

    Tesla DeLorean
    Guru
    September 2, 2011
    Posted on September 03, 2011 at 01:20

    #define NMEA_MAX 200 // Depends on receiver, should be adequate for most non-proprietary sentences

    void ProcessNMEALine(char *s)

    {

     .. Code to parse/crack NMEA sentence data

    }

    void ReceiveNMEALines(void)

    {

      char NMEALine[NMEA_MAX];

      int i;

      i = 0; // Buffer index

      while(1)

      {

        int x = getChar2();

        if (x >= 0) // valid character

        {

          char ch = (char)x;

          if (ch == '$') // Line resync

            i = 0;

          else if (ch == 0x0D) // First of end-of-line <CR><LF> pair

            ch = 0; // NUL string termination

          NMEALine[i++] = ch;

          if (i == NMEA_MAX) // Catch excessive line condition, and loop buffer

            i = 0;

          if (ch == 0) // Was last NUL placed?

            ProcessNMEALine(NMEALine); // Hand sentence to parser

       }

      }

    }

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Andrew Neil
    Super User
    September 5, 2011
    Posted on September 05, 2011 at 23:28

    At last - forum fixed!

    Here is an example of decoding an NMEA stream using a State Machine:

    http://www.visualgps.net/WhitePapers/NMEAParser/NMEAParser.html

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.