Skip to main content
infoinfo962
Associate II
August 15, 2010
Question

USART only sends last character

  • August 15, 2010
  • 10 replies
  • 2107 views

33123

    This topic has been closed for replies.

    10 replies

    John F.
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 14:02

    Your code looks OK. The following will send a zero terminated string using USART3 (and works!).

    void Usart3SendString(int8_t * pSrc)

    {

      //transmit outbox contents

      while(*pSrc)

      {

        USART_SendData(USART3, *pSrc++);

        //Loop until USART DR register is empty

        while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);

      }

    }

    I'm not sure why you've renamed USART1 as BT_USART.

    I wonder why you are not testing with ordinary ASCII chars like 'a' '0' etc. Maybe you are sending the chars but just not receiving them properly. Can you single step through your code? If you are seeing the last char, you must be executing the preceding code to get there!

    kashif
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:02

    try 

    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)

    just a blind shot. i didn't looked at your code all the way. i use TC flag generally.

    infoinfo962
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:02

    Forgot some defines used in the above code

    [code]

    // LEDs

    #define LED_READY_PORT            GPIOC

    #define LED_ERROR_PIN                GPIO_Pin_10

    #define LED_READY_PIN                GPIO_Pin_11

    #define LED_MOUNTED_PIN            GPIO_Pin_12

    #define LED_ACCESS_PIN            GPIO_Pin_13

    // bluetooth

    #define BT_USART                         USART1

    #define BT_BAUDRATE                    38400

    [/code]

    swhite2
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:02

    I doubt this is your problem but I'd replace the

    return 0;

    statement in main() with

    for (;;);

    Returning from main() usually causes a (hidden) reset/hang in embedded systems. Better, IMO, to make things explicit.

    infoinfo962
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:02

    Same story with USART3 using Usart3SendString(). Only the last character is received. To make sure it's not the receiving end I've hooked up a digiscope to the STM32's TX pin. Scope shows 1 character being transmitted, the others never leave the controller.

    I've renamed USART1 as BT_USART for convinience. I'll be attaching a bluetooth module to an USART and the name BT_USART (BlueTooth_USART) makes the code a bit easier to understand later on without having to know to which USART the module is actually attached.

    Also replaced USART_FLAG_TXE with USART_FLAG_TC but that makes no difference.

    To be continued...

    infoinfo962
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:02

    Tried your suggestion of resetting first, but again no difference. Also I find it unlikely the hardware is broken. USART 1 and 3 both suffering from the exact same issue? Unlikely.

    I'm leaning more and more towards a software problem. First I started playing around with compiler options (different optimisation options), but no change. Then I tried the following code with LED's hooked up to GPIOC pin 10 and 13:

    USART_SendData(USART3, 'x');

    FlagStatus status = USART_GetFlagStatus(USART3, USART_FLAG_TXE);

    switch (status) {

    case SET:

    GPIO_WriteBit(GPIOC, GPIO_Pin_10, Bit_SET);

    break;

    case RESET:

    GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);

    break;

    } Instead of focusing on sending a string, I wanted to know if the TXE bit was set or cleared after a write to the USART_DR register. I expected 1 LED to be on and the other OFF. But instead both LEDs remained off.

    Either I'm doing something very wrong or something very strange is going on.

    Used software:

    Ride7 v7.30.10.0159

    Ride7 patch v7.30.10.0169

    RKit-ARM for Ride7 v1.26.10.0130

    StdPeriph lib v3.3.0

    edit:

    Found the cause- for unknown reasons RESET does not equal 0 even though headerfile stm32f10x.h contains the line

    typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;

    Using this line

    while((USART3->SR & USART_FLAG_TXE) == 0);

    instead of

    while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);

    and it works. So a software problem after all, although I have no idea yet where in the chain this goes wrong.

    John F.
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 14:02

    Doesn't make any sense unless your hardware is broken.

    Try calling USART_DeInit() before you use the usart. This function toggles the reset to the peripheral as,

    RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE);

    RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE);

    infoinfo962
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:02

    Ok got something that does work - instead of checking if the TXE bit is cleared, this just loops until the TXE bit is set. I'm at a loss for words at the moment.

    void Usart3SendString(int8_t * pSrc)

    {

      //transmit outbox contents

      while(*pSrc)

      {

        USART_SendData(USART3, *pSrc++);

       

            while(1) {

                if (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == SET) {

                    break;

                }

            }

      }

    }

    Please note the above is just for testing purposes.

    infoinfo962
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:02

    Finally got a change to pick this up again after a few hectic days. Which wasn't a bad thing since it offered a fresh look again and I quickly found the root of the problem. It's one of those 'headdesk' moments...

    You were right John. One of my headerfiles defined RESET aswell. But since I hadn't touched that file after migrating existing code to STM32, I never thought of it. Renaming that specific define solved it all and all pieces of the puzzle fell into place.

    There's just 1 thing bothering me. Why didn't the compiler warn about a redefinition? Ride7 projects disable all warnings by default, but even after enabling all warnings with -Wall you don't get a redefinition error.

    Thanks to all for providing hints and tips!

    John F.
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 14:02

    I've been using STM32 library version V3.1.2

    In that library,

    USART_GetFlagStatus() returns a FlagStatus defined as

    typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;

    I suppose you have redefined RESET somehow. Pleased to hear you have it working now. I'm using CrossWorks GCC so can't comment on the compiler etc.