atmega328A UART - everything working, but not as expected

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

Hello, I am trying to get UART working via the atmega328A. I want to enter a character, and get that character to be printed out. However, when my code is run this is what happens.

  1. I enter one character, that character is printed out.
  2. I enter a second character, and the character is printed out,But then the first character is printed out continuously, forever.

 

for example, the output from the console. 

<user input a 5><5 is printed><system waits for input><user enter a 3><three is printed><system prints 5 repeatedly(for ever)>  

 

the code. 

 
 #include <avr/io.h>
 #include <util/delay.h>
 #include <stdlib.h>
                                                      // include LCD library
  #define F_CPU 8000000UL       
 #define BAUD 9600                                                       // define baud
 #define BAUDRATE ((F_CPU)/(BAUD*16UL)-1)        // set baudrate value for UBRR
 

                                 // set the CPU clock

 
 // function to initialize UART
 void uart_init (void)
 {
	 UBRR0H=(BAUDRATE>>8);
	 UBRR0L=BAUDRATE;                                                 //set baud rate
	 UCSR0B|=(1<<TXEN0)|(1<<RXEN0);                     //enable receiver and transmitter
	 UCSR0C|=(1<<UCSZ00)|(1<<UCSZ01);// 8bit data format
 }
 
 // function to send data - NOT REQUIRED FOR THIS PROGRAM IMPLEMENTATION
 void uart_transmit (unsigned char data)
 {
	 while (!( UCSR0A & (1<<UDRE0)));                  // wait while register is free
	 UDR0 = data;                                                     // load data in the register
 }
 
 // function to receive data
 unsigned char uart_recieve (void)
 {
	 while(!(UCSR0A) & (1<<RXC0));                     // wait while data is being received
	 return UDR0;                                                     // return 8-bit data
 }
 
 // main function: entry point of program
 int main (void)
 {
	 unsigned char a;
	 char buffer[10];
	 
	 uart_init();                                                    // initialize UART
	 
	 while(1)
	 {
		                                      
		 uart_transmit( uart_recieve());                               
		                     
		 _delay_ms(100);                                         
	 }
	 
	 return 0;
 }

thanks

daniel

This topic has a solution.
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your program looks as if it should run ok.    But only through luck.

 

1.   choose a more intuitive name than "BAUDRATE" e.g. UBRR_VALUE

      after all,    it is a register value and not a rate like 9600

2.   use = and not |= when you initialise special function registers.

      in your case,   the SFRs have known values at reset,   but it is easier and safer to set all the bits in one go.

3.   most importantly,   use your [SPACE] key.   It makes your code easier for you to read.

4.   place F_CPU before you #include <delay.h>

 

It is trivial points like these that make your program work first time.

 

Once you start understanding them,   you will find AVR or any embedded programming easy.

 

Ah-ha.    Re-reading your post,   I see that you have a problem with '3'.

I suspect that your 8000000 is not accurate.   Even so,   it would need to be very far wrong to 'create an extra START bit' and hence another character for the USART to read.    

 

David.

Last Edited: Sat. Oct 11, 2014 - 07:00 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you have a misplaced parenthesis in  uart_recieve().

 

 

while(!(UCSR0A) & (1<<RXC0));     // This is what you have

 

while( !(UCSR0A & (1<<RXC0) ) );  // This is what you should have

 

 

 

 

Last Edited: Sat. Oct 11, 2014 - 09:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chuck99 wrote:

I think you have a misplaced parenthesis in  uart_recieve().

 

 

while(!(UCSR0A) & (1<<RXC0));     // This is what you have

 

while( !(UCSR0A & (1<<RXC0) ) );  // This is what you should have

 

 

 

 

 

I saw that too.

 

Also, consider, as a newbie, using Arduino's libraries to avoid most of this sort of bare metal work.