cancel
Showing results for 
Search instead for 
Did you mean: 

Setting up RS232 USART on STM32-P103

cnocbarra
Associate
Posted on January 15, 2011 at 23:47

Setting up RS232 USART on STM32-P103

20 REPLIES 20
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
Up vote any posts that you find helpful, it shows what's working..
sara2
Associate II
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 II
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!

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
Up vote any posts that you find helpful, it shows what's working..
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
Up vote any posts that you find helpful, it shows what's working..
sara2
Associate II
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!
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
Up vote any posts that you find helpful, it shows what's working..
sara2
Associate II
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!

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
Up vote any posts that you find helpful, it shows what's working..