cancel
Showing results for 
Search instead for 
Did you mean: 

USART only sends last character

infoinfo962
Associate II

33123

10 REPLIES 10
infoinfo962
Associate II
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]

kashif
Associate II
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.

John F.
Senior
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!

infoinfo962
Associate II
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...

swhite2
Associate III
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
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.

John F.
Senior
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
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.
Senior
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.