EmbeddedRelated.com
Forums

UART:can't RX a continuous stream of data , if "ABCDHEFG" is Tx'd , Rx'd is "A"

Started by Abhay July 8, 2011
Hi

I am having some issue with my UART code . I can't RX a continuous stream of data , if "ABCDHEFG" is Transmitted , Received stream of data is "A"

Here is my code , it would be great if anyone can point out any faults

/*
* File: uart.c
* Purpose: Serial interface functions
*/

/*
*header files
*/
#include
#include
#include
#include
#include
#include

/**
* Stop WDT
*/
void low_level_init( void )
{
WDTCTL = WDTPW+WDTHOLD;
}
/**
* Initialize clock
*/

void CLK_init(void)
{
UCSCTL6 &= ~XT2OFF; // Enable XT2
UCSCTL3 |= SELREF_2; // FLLref = REFO
// Since LFXT1 is not used,
// sourcing FLL with LFXT1 can cause
// XT1OFFG flag to set
UCSCTL6 &= ~XT2DRIVE0; // Decrease XT2 Drive according to
// expected frequency
UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT22MHz
UCSCTL5 = DIVA_5; // f_SMCLK/32
}

/*
* Initialize the UART
*/
void UART_init(void)
{
UCA0CTL0 = UCSPB; // UART0 CONTROL = 8-bit character , 1stop
UCA0CTL1 |= UCSWRST; // Put state machine in reset
UCA0CTL1 |= UCSSEL_2; // SMCLK

UCA0BR0 = 0x06; // 1MHz 9600
UCA0BR1 = 0x00; // 1MHz 9600

UCA0MCTL = UCBRS_0 + UCBRF_13 + UCOS16; // Modln UCBRSx=0, UCBRFx=0,

P3SEL = BIT3+BIT4; // P3.4,5 = USCI_A0 TXD/RXD

UCA0CTL1 &= ~UCSWRST; // Initialize USCI state machine
UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt

UCA0CTL0 |= UCMODE_0; // Set the mode in control register 0 to UART.
UCA0STAT = UCLISTEN; // Loop back

}

/**
* Send only byte via UART.
* @param c Character to send.
*/
void UART_putChar (char c) // UART1 Transmit Subroutine
{
while (UCTXIFG == 0); // Wait for ready U1TXBUF
UCA0TXBUF = c; // send data
}

/**
* Check UART's input buffer ,
* @return TRUE: if input buffer contains received data.
*/
int UART_getCharIsReady ()
{
return (UCA0IFG&UCRXIFG) != 0 ;
}

/**
* Receive one byte via UART. This function waits for the input (blocking).
* @return Received character.
*/
char *UART_getChar ()
{
int i= 0;
char *buf;
while (!UART_getCharIsReady ()){
//return UCA0RXBUF;
buf[i++] = UCA0RXBUF;
}
return buf;
}

/**
* Write string buffer to UART.
* @param buf String buffer to send.
* @param length Length of string buffer.
*/
void UART_write (const char *buf, int length)
{
int i;
for (i = 0; i < length; i++)
{
UART_putChar (buf[i]);
}
UART_putChar ('\0');
}

/**
* @param buf :TX buffer
* @return : size of buffer
*/
int buflen(char *buf)
{
int size=0;
while (buf[size] != '\0')
size++;
return size;
}

/**
* main.c
*/
void main(void)
{
int length;
char *rxBuffer;
char *txBuffer;
//int l = -1;

txBuffer = "ABCDEFGH";
length = buflen(txBuffer);

low_level_init();
CLK_init();
UART_init();

UART_write(txBuffer, length);
rxBuffer = UART_getChar();
//l = buflen(rxBuffer);

__bis_SR_register(LPM4_bits + GIE ); // Enter LPM4
__no_operation(); // For debugger
}

Beginning Microcontrollers with the MSP430

On 07/08/2011 11:22 AM, Abhay wrote:
> /**
> * Receive one byte via UART. This function waits for the input (blocking).
> * @return Received character.
> */
> char *UART_getChar ()
> {
> int i= 0;
> char *buf;
> while (!UART_getCharIsReady ()){
> //return UCA0RXBUF;
> buf[i++] = UCA0RXBUF;
> }
> return buf;
> }

This is poorly coded. Given the various styles present I suspect that
you just grabbed bits and pieces here and there without understanding
what any of them really did.

The comment and function name claims that exactly one character is
received yet the calling function assumes a string and more than one
byte is stuffed into an array. This is the least of the problems.

1) The pointer buf is used uninitialized so there is no telling where
the data is stored. Only by shear luck will it be RAM. Enable -Wall when
compiling so that the compiler can complain about this sort of problem.
2) The while() loop is the worst. It checks to see if the UART has a
character ready. If it doesn't, it reads the receive buffer and stores
that value into the random memory location and checks again. If the UART
is ready then it quits (without reading the character!) and returns.
3) The received string is not terminated which I suppose isn't a big
deal since the string is filled with junk and the pointer likely isn't
even pointing at RAM.
I have purposely ignored the crucial detail of if this code correctly
accesses the hardware.
--
David W. Schultz
http://home.earthlink.net/~david.schultz
"Pooh just is." Tao of Pooh
Howdy,
So I assume that you have a loopback setup so that you are trying to send and receive from the same unit. I believe that the problem is that you are using polling to send all of the data before you start to try and receive any of the data. You will need to implement interrupts, at least on the receive side, if you want to send a stream of data and be able to receive all of it.

HTH,
Barry

--- In m..., "Abhay" wrote:
>
> Hi
>
> I am having some issue with my UART code . I can't RX a continuous stream of data , if "ABCDHEFG" is Transmitted , Received stream of data is "A"
>
> Here is my code , it would be great if anyone can point out any faults
>
> /*
> * File: uart.c
> * Purpose: Serial interface functions
> */
>
> /*
> *header files
> */
> #include
> #include
> #include
> #include
> #include
> #include /**
> * Stop WDT
> */
> void low_level_init( void )
> {
> WDTCTL = WDTPW+WDTHOLD;
> }
> /**
> * Initialize clock
> */
>
> void CLK_init(void)
> {
> UCSCTL6 &= ~XT2OFF; // Enable XT2
> UCSCTL3 |= SELREF_2; // FLLref = REFO
> // Since LFXT1 is not used,
> // sourcing FLL with LFXT1 can cause
> // XT1OFFG flag to set
> UCSCTL6 &= ~XT2DRIVE0; // Decrease XT2 Drive according to
> // expected frequency
> UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT22MHz
> UCSCTL5 = DIVA_5; // f_SMCLK/32
> }
>
>
> /*
> * Initialize the UART
> */
> void UART_init(void)
> {
> UCA0CTL0 = UCSPB; // UART0 CONTROL = 8-bit character , 1stop
> UCA0CTL1 |= UCSWRST; // Put state machine in reset
> UCA0CTL1 |= UCSSEL_2; // SMCLK
>
> UCA0BR0 = 0x06; // 1MHz 9600
> UCA0BR1 = 0x00; // 1MHz 9600
>
> UCA0MCTL = UCBRS_0 + UCBRF_13 + UCOS16; // Modln UCBRSx=0, UCBRFx=0,
>
> P3SEL = BIT3+BIT4; // P3.4,5 = USCI_A0 TXD/RXD
>
> UCA0CTL1 &= ~UCSWRST; // Initialize USCI state machine
> UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
>
> UCA0CTL0 |= UCMODE_0; // Set the mode in control register 0 to UART.
> UCA0STAT = UCLISTEN; // Loop back
>
> }
>
>
>
> /**
> * Send only byte via UART.
> * @param c Character to send.
> */
> void UART_putChar (char c) // UART1 Transmit Subroutine
> {
> while (UCTXIFG == 0); // Wait for ready U1TXBUF
> UCA0TXBUF = c; // send data
> }
>
>
> /**
> * Check UART's input buffer ,
> * @return TRUE: if input buffer contains received data.
> */
> int UART_getCharIsReady ()
> {
> return (UCA0IFG&UCRXIFG) != 0 ;
> }
>
>
> /**
> * Receive one byte via UART. This function waits for the input (blocking).
> * @return Received character.
> */
> char *UART_getChar ()
> {
> int i= 0;
> char *buf;
> while (!UART_getCharIsReady ()){
> //return UCA0RXBUF;
> buf[i++] = UCA0RXBUF;
> }
> return buf;
> }
>
>
> /**
> * Write string buffer to UART.
> * @param buf String buffer to send.
> * @param length Length of string buffer.
> */
> void UART_write (const char *buf, int length)
> {
> int i;
> for (i = 0; i < length; i++)
> {
> UART_putChar (buf[i]);
> }
> UART_putChar ('\0');
> }
>
>
>
> /**
> * @param buf :TX buffer
> * @return : size of buffer
> */
> int buflen(char *buf)
> {
> int size=0;
> while (buf[size] != '\0')
> size++;
> return size;
> }
>
>
>
>
> /**
> * main.c
> */
> void main(void)
> {
> int length;
> char *rxBuffer;
> char *txBuffer;
> //int l = -1;
>
>
> txBuffer = "ABCDEFGH";
> length = buflen(txBuffer);
>
> low_level_init();
> CLK_init();
> UART_init();
>
> UART_write(txBuffer, length);
> rxBuffer = UART_getChar();
> //l = buflen(rxBuffer);
>
> __bis_SR_register(LPM4_bits + GIE ); // Enter LPM4
> __no_operation(); // For debugger
> }
>

The original poster also posted the same thing on TI E2E. He said the problem was solved a long time ago.

--- In m..., "blb026" wrote:
>
> Howdy,
> So I assume that you have a loopback setup so that you are trying to send and receive from the same unit. I believe that the problem is that you are using polling to send all of the data before you start to try and receive any of the data. You will need to implement interrupts, at least on the receive side, if you want to send a stream of data and be able to receive all of it.
>
> HTH,
> Barry
>
> --- In m..., "Abhay" wrote:
> >
> > Hi
> >
> > I am having some issue with my UART code . I can't RX a continuous stream of data , if "ABCDHEFG" is Transmitted , Received stream of data is "A"
> >
> > Here is my code , it would be great if anyone can point out any faults
> >
> >
> >
> > /*
> > * File: uart.c
> > * Purpose: Serial interface functions
> > */
> >
> > /*
> > *header files
> > */
> > #include
> > #include
> > #include
> > #include
> > #include
> > #include
> >
> > /**
> > * Stop WDT
> > */
> > void low_level_init( void )
> > {
> > WDTCTL = WDTPW+WDTHOLD;
> > }
> >
> >
> > /**
> > * Initialize clock
> > */
> >
> > void CLK_init(void)
> > {
> > UCSCTL6 &= ~XT2OFF; // Enable XT2
> > UCSCTL3 |= SELREF_2; // FLLref = REFO
> > // Since LFXT1 is not used,
> > // sourcing FLL with LFXT1 can cause
> > // XT1OFFG flag to set
> > UCSCTL6 &= ~XT2DRIVE0; // Decrease XT2 Drive according to
> > // expected frequency
> > UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT22MHz
> > UCSCTL5 = DIVA_5; // f_SMCLK/32
> > }
> >
> >
> > /*
> > * Initialize the UART
> > */
> > void UART_init(void)
> > {
> > UCA0CTL0 = UCSPB; // UART0 CONTROL = 8-bit character , 1stop
> > UCA0CTL1 |= UCSWRST; // Put state machine in reset
> > UCA0CTL1 |= UCSSEL_2; // SMCLK
> >
> > UCA0BR0 = 0x06; // 1MHz 9600
> > UCA0BR1 = 0x00; // 1MHz 9600
> >
> > UCA0MCTL = UCBRS_0 + UCBRF_13 + UCOS16; // Modln UCBRSx=0, UCBRFx=0,
> >
> > P3SEL = BIT3+BIT4; // P3.4,5 = USCI_A0 TXD/RXD
> >
> > UCA0CTL1 &= ~UCSWRST; // Initialize USCI state machine
> > UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
> >
> > UCA0CTL0 |= UCMODE_0; // Set the mode in control register 0 to UART.
> > UCA0STAT = UCLISTEN; // Loop back
> >
> > }
> >
> >
> >
> > /**
> > * Send only byte via UART.
> > * @param c Character to send.
> > */
> > void UART_putChar (char c) // UART1 Transmit Subroutine
> > {
> > while (UCTXIFG == 0); // Wait for ready U1TXBUF
> > UCA0TXBUF = c; // send data
> > }
> >
> >
> > /**
> > * Check UART's input buffer ,
> > * @return TRUE: if input buffer contains received data.
> > */
> > int UART_getCharIsReady ()
> > {
> > return (UCA0IFG&UCRXIFG) != 0 ;
> > }
> >
> >
> > /**
> > * Receive one byte via UART. This function waits for the input (blocking).
> > * @return Received character.
> > */
> > char *UART_getChar ()
> > {
> > int i= 0;
> > char *buf;
> > while (!UART_getCharIsReady ()){
> > //return UCA0RXBUF;
> > buf[i++] = UCA0RXBUF;
> > }
> > return buf;
> > }
> >
> >
> > /**
> > * Write string buffer to UART.
> > * @param buf String buffer to send.
> > * @param length Length of string buffer.
> > */
> > void UART_write (const char *buf, int length)
> > {
> > int i;
> > for (i = 0; i < length; i++)
> > {
> > UART_putChar (buf[i]);
> > }
> > UART_putChar ('\0');
> > }
> >
> >
> >
> > /**
> > * @param buf :TX buffer
> > * @return : size of buffer
> > */
> > int buflen(char *buf)
> > {
> > int size=0;
> > while (buf[size] != '\0')
> > size++;
> > return size;
> > }
> >
> >
> >
> >
> > /**
> > * main.c
> > */
> > void main(void)
> > {
> > int length;
> > char *rxBuffer;
> > char *txBuffer;
> > //int l = -1;
> >
> >
> > txBuffer = "ABCDEFGH";
> > length = buflen(txBuffer);
> >
> > low_level_init();
> > CLK_init();
> > UART_init();
> >
> > UART_write(txBuffer, length);
> > rxBuffer = UART_getChar();
> > //l = buflen(rxBuffer);
> >
> > __bis_SR_register(LPM4_bits + GIE ); // Enter LPM4
> > __no_operation(); // For debugger
> > }
>