How to initialize USART?

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

Guys,

I tried to init USART on ATMEGA128 by following this tutorial:

https://www.avrfreaks.net/index.p...

but I got this message
../mainV5.c:49:2: error: 'UCSRB' undeclared (first use in this function)

Did I miss a library here ?
I put
#include already...

Thanks

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

Look at your atmega128 datasheet. You will find i9t has two UARTs. When you look at the chapter about the UART you will find that because of this the registers are called UDR0/UDR1, UCSR0A/UCSR1A, UCSR0B/UCSR1B, UCSR0C/UCSR1C.

So first you need to pick whether you want to use UART0 or UART1. If you have connected to pins 2 and 3 of the chip (TXD0/RXD0) then you are using UART0. If you have connected to pins 27 and 28 (TXD1/RXD1) then you are using UART1.

Let's say you are using UART0 then if you see lines in example code that does:

UDR = ByteToSend; // Send out the byte value in the variable "ByteToSend"
while ((UCSRA & (1 << TXC)) == 0) {}; // Do nothing until transmission complete flag set 

You would change this to be:

UDR0 = ByteToSend; // Send out the byte value in the variable "ByteToSend"
while ((UCSR0A & (1 << TXC0)) == 0) {}; // Do nothing until transmission complete flag set 

Where both the register and the bitnames have 0 added.

Note however that some things in that tutorial simply don't apply to the mega128. In the tutorial Dean uses a bit called URSEL. You might guess that there would be a URSEL0 but you'd be wrong. The mega128 has far more registers than a mega16 so it does not need to share a register so it does not need a URSEL bit. This does mean that UBRRH and UCSRC (or rather UCSR0C/UCSR1C) are not a shared register.

So you need to do a little work to port that tutorial code to the mega128.

To be honest you may be better off finding a UART tutorial specifically written for mega128.

EDIT: OK the following is written for Arduino (mega168/mega328) but as they have a UART with number "0" it may be closer to what you need than the tutorial you have been looking at:

http://hekilledmywire.wordpress....

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

To clawson,

Thank you very much for the reply,

I got it :

void usart_Init( unsigned int ubrr )
{
/* Set baud rate */

	UBRR0H = (unsigned char)(ubrr>>8);
	UBRR0L = (unsigned char)ubrr;
	/* Enable receiver and transmitter */
	UCSR0B = (1<<RXEN)|(1<<TXEN);
	/* Set frame format: 8data, 2stop bit */
	UCSR0C = (1<<USBS)|(3<<UCSZ0);
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How can I transmit a complete string with this function ?

thanks

void usart_transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE)) )
;
/* Put data into buffer, sends the data */
UDR0 = data;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Found with a Google search for "usart_transmit"...\
https://sites.google.com/site/em...

/*Send a character through UART*/
void USART_Transmit(unsigned char data) {
    /* Wait for empty transmit buffer */
    while (!(UCSR0A & (1 << UDRE0)))
        ;
    /* Put data into buffer, sends the data */
    UDR0 = data;
}

/*Send a string of characters through UART*/
void send_str(unsigned char text[], unsigned char n) {
    unsigned char i;
    for (i = 0; i < n; i++) {
        USART_Transmit(text[i]);
    }
    USART_Transmit(13);
}

...and others

// Transmit a string
void USART_transmit_string(const unsigned char* data) {
	while(*data) {
		while ( !( UCSRA & (1<<UDRE)) )
		;
		UDR = *data;
		++data;
	}
}
// Write a string to the UART Transmitter buffer
void putstring(char *s)
{
	while (*s)
  		{
		putc(*s++);
		}
}

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Quote:

How can I transmit a complete string with this function ?

You will note that all the suggestions above fit this description: Send the first character, then the next, and the next, and ... until there are no more characters.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

If you used then I guess you are using avr-gcc. If so I'd read this:

http://www.nongnu.org/avr-libc/u...

Copy the UART stuff from that (with adjustments from mega16 to mega128 for register bits/names) then you can use functionality. So you only have to supply the one uart_putchar() function and then you can send strings, floats or whatever your heart desires.

The usual argument is that "stdio" function (putc, puts, printf, sprintf, etc) take a "considerable amount of flash". Well yeah, they cost about 2-3K. That matters in a 4K micro, it doesn't matter in a 128K micro.

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

I tried to do :

void usart_transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE)) )
;
/* Put data into buffer, sends the data */
UDR0 = data;
}



void usart_pstr(char *s) {

    // loop through entire string

    while (*s) {
        usart_transmit(*s);
        s++;
    }
}

but always get ".." in between of character, like it's late....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
H
ALLO FROM ATM
EGA128

suppose to be HALLO FROM ATMEGA128

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

Can the thing receiving the data show the actual hex codes it is receiving? Is there really a 0x0A (new line) sent after the initial 0x48 ('H') ?

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

Quote:
H
ALLO FROM ATM
EGA128
suppose to be HALLO FROM ATMEGA128
Show the complete code which do this.

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

How is the transmitted data observed? Some kind of terminal program? If so, what? And what platform?

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

Visovian wrote:
Quote:
H
ALLO FROM ATM
EGA128
suppose to be HALLO FROM ATMEGA128
Show the complete code which do this.

The code :

//Mention Clock frequency here
#define _XTAL_FREQ 8000000 
#define F_CPU 8000000UL  // 8 MHz

// Define baud rate
#define USART_BAUDRATE 9600   
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

void usart_init(unsigned int ubrr);
void usart_transmit( unsigned char data );
unsigned char usart_receive( void );
void usart_pstr(char *s);

void usart_init( unsigned int ubrr )
{
/* Set baud rate */

	UBRR0H = (unsigned char)(ubrr>>8);
	UBRR0L = (unsigned char)ubrr;
	/* Enable receiver and transmitter */
	UCSR0B = (1<<RXEN)|(1<<TXEN);
	/* Set frame format: 8data, 2stop bit */
	UCSR0C = (1<<USBS)|(3<<UCSZ0);
}

void usart_transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE)) )
;
/* Put data into buffer, sends the data */
UDR0 = data;
}



void usart_pstr(char *s) {

    // loop through entire string

    while (*s) {
        usart_transmit(*s);
        s++;
    }
}


unsigned char usart_receive( void )
{
/* Wait for data to be received */
while ( !(UCSR0A & (1<<RXC)) )
;
/* Get and return received data from buffer */
return UDR0;
}

int main(){
 
	usart_init ( BAUD_PRESCALE );
    
    
    while(1){
	  usart_pstr("HALLO FROM ATMEGA128\n");
          }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
How is the transmitted data observed? Some kind of terminal program? If so, what? And what platform?

Jim

I observer with "Access Port", Yes it's somekind of terminal program.
I'm using Windows 7 if you're asking my OS.

Thank you

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

clawson wrote:
Can the thing receiving the data show the actual hex codes it is receiving? Is there really a 0x0A (new line) sent after the initial 0x48 ('H') ?

Please have a look on the screen shot for the complete hex and ascii characters

Thanks

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

Your code works well on my board.
Check if you use right hexfile.

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

Quote:

Please have a look on the screen shot for the complete hex and ascii characters

This has got to be something at the PC end. I cannot see how the AVR using:

usart_pstr("HALLO FROM ATMEGA128\n"); 

would have the "intelligence" to not just corrupt the odd character but to actually insert additional -x-D/0x0A sequences. Those are clearly coming from something with intelligence and your AVR is not it.

If you have a second PC then connect it to this first one and send "HALLO FROM ATMEGA128" from that. I'm guessing you'll also see inserted OD/OA's there too.

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

Hello,
I'm very new to this AVR field. I'm using ATmega328 for serial communication, my problem is that I cannot send data.I've tried to debug using LED's and found out that I got stuck in while() loop in DATAWRITE function, which mean UDRE0 is not set.I'm very new to USART but I've tried my level best to solve it but I couldn't.Consider this, I'm just a beginner.

Specifications:
Programmer: AVRISP MKII
Microcontroller: ATmega328(I've tried it on ATmega16A too)
Oscillator: External 16MHz

/*
 * Serial_4.c
 *
 * Created: 5/27/2013 11:36:29 AM
 *  Author: Stephen Philip
 */ 

#define  L 100 // ERROR
#define  M 500
#define  H 1000 // working Perfectly
#define  VH 5000
#define F_CPU 14745600UL // CPU Frequency Set
#define USART_BAUDRATE 9600 // Baud Rate Set
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)


#include 
#include 
#include   
#include 

                               
// Debugging Functions
void nopower()
{
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
}
void error()
{
	PORTB = (1<<PORTB0)|(1<<PORTB1)|(1<<PORTB2);
	PORTD = (1<<PORTD7);
	_delay_ms(L);	
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(L);
	PORTB = (1<<PORTB0)|(1<<PORTB1)|(1<<PORTB2);
	PORTD = (1<<PORTD7);
	_delay_ms(L);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(L);
}
void one()
{
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (1<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void two()
{
	PORTB = (1<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);

}
void three()
{
	PORTB = (1<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (1<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void four()
{
	PORTB = (0<<PORTB0)|(1<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void five()
{
	PORTB = (0<<PORTB0)|(1<<PORTB1)|(0<<PORTB2);
	PORTD = (1<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void six()
{
	PORTB = (1<<PORTB0)|(1<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void seven()
{
	PORTB = (1<<PORTB0)|(1<<PORTB1)|(1<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void eight()
{
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(1<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void nine()
{
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(1<<PORTB2);
	PORTD = (1<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void ten()
{
	PORTB = (1<<PORTB0)|(0<<PORTB1)|(1<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void eleven()
{
	PORTB = (1<<PORTB0)|(0<<PORTB1)|(1<<PORTB2);
	PORTD = (1<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void twelve()
{
	PORTB = (0<<PORTB0)|(1<<PORTB1)|(1<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void thirteen()
{
	PORTB = (0<<PORTB0)|(1<<PORTB1)|(1<<PORTB2);
	PORTD = (1<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void fourteen()
{
	PORTB = (1<<PORTB0)|(1<<PORTB1)|(1<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void fifteen()
{
	PORTB = (1<<PORTB0)|(1<<PORTB1)|(1<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
	PORTB = (0<<PORTB0)|(0<<PORTB1)|(0<<PORTB2);
	PORTD = (0<<PORTD7);
	_delay_ms(H);
}
void USARTInit()
{
	// Setting Baud Rate 
	UBRR0H = ((BAUD_PRESCALE)>>8);
	UBRR0L = BAUD_PRESCALE;
	//Debugging Code for Baud Rate
	if ((UBRR0H == ((BAUD_PRESCALE)>>8)) && (UBRR0L = BAUD_PRESCALE))
	{
		one();	
	}
	else
	{
		error();
	}	
	//Setting Char size to 8
	UCSR0C = ((1<<UCSZ01)|(1<<UCSZ00));
	// Debugging Code for char size
	if (UCSR0C == ((1<<UCSZ01)|(1<<UCSZ00)))
	{
		three();
	}
	else
	{
		error();
	}	
	// Enabling RX and Tx Complete Interrupt Enable and RX and TX
	UCSR0B |= ((1<<TXEN0)|(1<<RXEN0));
	// Enabling TX int RX int UDR int
	UCSR0B |= (1<<TXCIE0)|(1<<RXCIE0)|(1<<UDRIE0);
	// Debugging code for Tx Tx int Rx Rx int and UDR int
	if (UCSR0B == ((1<<TXCIE0)|(1<<RXCIE0)|(1<<UDRIE0)|(1<<TXEN0)|(1<<RXEN0)))
	{
		two();
	}
	else
	{
		error();
	}
}
void UWriteData(char data)
{	
	while(!(UCSR0A & (1<<UDRE0)));	
	UDR0 = data;	
}
void UWriteString(char *str)
{
	while((*str)!='\0')
	{
		UWriteData(*str);
		str++;		
	}
}
int main(void)
{	
	DDRB = (1<<DDB0)|(1<<DDB1)|(1<<DDB2);
	DDRD = (1<<DDD7);	
		
	USARTInit();
			
    while(1)
    {		
		UWriteData('a');						
    }
}

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

That code is predicated on the fact that the CPU is running at 14.7456MHz, what have you done to confirm that is true?

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

clawson wrote:
That code is predicated on the fact that the CPU is running at 14.7456MHz, what have you done to confirm that is true?

we can define our own frequency Right, I didn't check any thing but I'm using 16MHz External oscillator. To get 0% error in baud rate I've set that frequency.

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

No you cannot define your own speed! Either the fuses of the AVR are set to use its own internal oscillator at either 1MHz or 8MHz. Or you have the fuses set to say "use external clock source" which could be a choice of crystal or clock generator. The speed the AVR then runs at is set entirely by the fundamental frequency of that device. It's then up to you as the programmer to set F_CPU to match whatever that speed is. There's no magic that says that purely by setting F_CPU to 1234567 that the chip will suddenly run at 1.234567MHz. So it sounds like you need to base your UBRR calculation on 16000000UL.

If you really want the AVR to run at 14.7456MHz then add a crystal/oscillator at that frequency then you could leave F_CPU at its current setting.

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

And you cant turn on the uart rx and tx interrupts until you have written interrupt handlers for them. Get the uart to work WITHOU the interrupts first. They just save a little cpu time when the program starts getting tight.

Imagecraft compiler user

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

You should be able to put most AVR 'designs' on the back of an envelope, or an A4 page.

You have a lot of 'similar' functions like one(), two(), ...
Surely you could have a single function that takes 1, 2, etc as an argument.

Copy-paste may be relatively simple to do in an editor. However it makes a nightmare to maintain. It is far simpler to edit a single function. And certainly easier to read a page or screen than scrolling through reams.

Oh, and if you use the honest value of F_CPU, the USART calculations will be correct.

David.