USART Problem

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi,

 

I try to send integer with UART but only the 2 highest bits are displayed in my terminal.

 

Someone has an idea of my error ?

 

here's my code :

 

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>

#define F_CPU 8000000UL                    // set the CPU clock

#define BAUD 9600                           // define baud
#define MYUBBR ((F_CPU)/(BAUD*16UL)-1)    // set baudrate value for UBRR

void uart_init (unsigned int ubrr)
{
    //set baud rate
    UBRR0H =(unsigned char)(ubrr>>8);
    UBRR0L =(unsigned char)ubrr;
    
    //enable receiver and transmitter                        
    UCSR0B |=(1<<TXEN0)|(1<<RXEN0);
    
    // 8bit data format + 2 STOP BIT            
    UCSR0C |= (1<<UCSZ00)|(1<<UCSZ01)|(1<<USBS0);
}

void uart_transmit (char data [5])
{
    for (int i=0;i<size of(data);i++)
    {
        // wait while register is free
        while (!( UCSR0A & (1<<UDRE0)));
            
        // Put data into buffer, sends the data
        UDR0 = data [i];
    }                          
}

int main (void)
{    
    int nbr;
    char buffer[5];
    
    uart_init(MYUBBR);                            // initialize UART
    
    while(1)
    {
        nbr = 5673;
        itoa(nbr,buffer,10);
        uart_transmit (buffer);
        _delay_ms(500);
    }
    return 0;
}

Last Edited: Thu. Jun 25, 2015 - 09:57 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sizeof(data)

I think you mean strlen() (assuming it's a string) not sizeof(). sizeof() is known at compile time, not run time and will be the width in bytes of the data[] pointer. On an AVR that will always be 2.

 

Personally I would write your string routine as either:

void uart_transmit (char data [])
{
    int i = 0;
    while (data[i])
    {
        // wait while register is free
        while (!( UCSR0A & (1<<UDRE0)));
            
        // Put data into buffer, sends the data
        UDR0 = data [i++];
    }                           
}

or

void uart_transmit (char data [])
{
    while (*data)
    {
        // wait while register is free
        while (!( UCSR0A & (1<<UDRE0)));
            
        // Put data into buffer, sends the data
        UDR0 = *data++;
    }                           
}

In actual fact I would first do:

void uart_char (char c)
{
        // wait while register is free
        while (!( UCSR0A & (1<<UDRE0)));
            
        // Put data into buffer, sends the data
        UDR0 = c;
}

and then call that from either implementation.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

void uart_transmit (char data [])
{
    int i = 0;
    while (data[i])
    {
        // wait while register is free
        while (!( UCSR0A & (1<<UDRE0)));
            
        // Put data into buffer, sends the data
        UDR0 = data [i++];
    }                           
}

 

Ok, I understand this method and it's work well !

 

But I don't understand the next method ... Why do you use the pointers ?

 

clawson wrote:

void uart_transmit (char data [])
{
    while (*data)
    {
        // wait while register is free
        while (!( UCSR0A & (1<<UDRE0)));
            
        // Put data into buffer, sends the data
        UDR0 = *data++;
    }                           
}

 

Now, if I want to send unsigned int for displayed my 16th timer value .. It's possible ?

Last Edited: Thu. Jun 25, 2015 - 10:20 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But I don't understand the next method ... Why do you use the pointers ?

I prefer pointers. Just compare those two implementations. Can you tell me how many characters I can output using data[i] and how many can I output using *data++ ? That is just one reason (to me anyway) why pointers are "better".

 

In fact it's often said that the "power" of C and the reason it's so widely used compared to a lot of alternatives is the very existence of pointers in the language.

 

For those coming from an asm background a pointer is an an "index register" - simple as that - it's great programming in a "high level" language where you can still make use of index registers.

Now, if I want to send unsigned int for displayed my 16th timer value .. It's possible ?

Your original code used itoa(). That's exactly the way to do it (well, OK, one of many but perhaps the preferred one?). Once you have a working uart_transmit() that can output the string created by itoa() you are all set with a solution aren't you?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And just a comment about a comment...

// wait while register is free

in this case is more accurately stated as...

// wait UNTIL register is free

 

Cheers,

 

Ross

 

Ross McKenzie ValuSoft Melbourne Australia

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Can you tell me how many characters I can output using data[i] and how many can I output using *data++ ?

 

I think you prefer pointer because they're no limitation. Whereas using data[i] we're limited by the maximum value of the integer.

 

clawson wrote:

Your original code used itoa(). That's exactly the way to do it (well, OK, one of many but perhaps the preferred one?). Once you have a working uart_transmit() that can output the string created by itoa() you are all set with a solution aren't you?

 

I think ITOA can't convert unsigned int ... True ? When I use a longer value than 32768 . The uart display an value with a negative sign

 

EDIT : I use ltoa and it work fine ! I didn't know this function.

 

Last Edited: Thu. Jun 25, 2015 - 12:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you prefer pointer because they're no limitation. Whereas using data[i] we're limited by the maximum value of the integer.

Spot on! If "i" is an int then it will count 0..32767 and the maximum characters you could output would be 32767. In the pointer case you are not limited by sizeof(int). It will go on through memory printing characters until it hits the 0x00 that stops the while() loop. Of course you may say that no AVR program wants to print a continuous string of characters that is more than 32,767 characters long and you would be right but it's a more general principle. In other places "int i" might have even been "signed char i" (127 max characters) or "unsigned char i" (255 characters). A pointer solution imposes no such limitations.

I think ITOA can't convert unsigned int ... True ? When I use a longer value than 32768 . The uart display an value with a negative sign

The function is called itoa() because the i stands for int and, by implication "signed int". A signed int can hold -32768..+32767 so, yes, when you get beyond 32767 things will start getting negative. If you want to stick with 16 bits but treat it as unsigned (0..65535) then utoa() (u = "unsigned int") should be your function of choice. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks a lot for your help!