First post with USART question

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

Hello!

It's my first post here, so I want to say hello to everyone and give thanks for this awesome forum.

I just begin a few weeks ago with avr's. I have an Arduino ONE with an atmega328.

After reading tutorials (Dean' was a good one) and datasheet of atmega I'm trying to make a simple "echo" program with USART.

I took the AVR306 Note and adapted the code to my mcu but I have the problem that I'm able to send from computer to mcu but mcu don't return the char.

Someone can help me?? :oops:

I'm using AVR Studio 4 with GCC.

#include "avr/io.h"
#include "avr/interrupt.h"
#include "USART2.h"

int main(void)
{

	PORTD = 0xF0;
	DDRD  = 0x04; //Governement of MAX485 in/out data

	USART0_Init(103);
	sei();
	
	unsigned char data=0;

	while(1){
	
		data=USART0_Receive();
		
		PORTD |= (1<<2); //MAX485 on for transmission
		USART0_Transmit(data);
		PORTD &= ~(1<<2); //MAX485 on for reception
				
	}
}

USART lib form AVR306 Note (adapted)
USART2.h


/* Prototypes */
void USART0_Init( unsigned int baudrate );
unsigned char USART0_Receive( void );
void USART0_Transmit( unsigned char data );

USART2.c


// AVR306: Using the AVR UART in C
// Routines for interrupt controlled USART
// Last modified: 02-06-21
// Modified by: AR

/* Includes */
#include 
#include 
#include 
#include "USART2.h"

/* UART Buffer Defines */
#define USART_RX_BUFFER_SIZE 32     /* 2,4,8,16,32,64,128 or 256 bytes */
#define USART_TX_BUFFER_SIZE 32     /* 2,4,8,16,32,64,128 or 256 bytes */
#define USART_RX_BUFFER_MASK ( USART_RX_BUFFER_SIZE - 1 )
#define USART_TX_BUFFER_MASK ( USART_TX_BUFFER_SIZE - 1 )
#if ( USART_RX_BUFFER_SIZE & USART_RX_BUFFER_MASK )
	#error RX buffer size is not a power of 2
#endif
#if ( USART_TX_BUFFER_SIZE & USART_TX_BUFFER_MASK )
	#error TX buffer size is not a power of 2
#endif

/* Static Variables */
static unsigned char USART_RxBuf[USART_RX_BUFFER_SIZE];
static volatile unsigned char USART_RxHead;
static volatile unsigned char USART_RxTail;
static unsigned char USART_TxBuf[USART_TX_BUFFER_SIZE];
static volatile unsigned char USART_TxHead;
static volatile unsigned char USART_TxTail;

/* Initialize USART */
void USART0_Init(unsigned int baudrate)
{
	unsigned char x;

	/* Set the baud rate */
	UBRR0H = (unsigned char) (baudrate>>8);                  
	UBRR0L = (unsigned char) baudrate;
	
	/* Enable UART receiver and transmitter */
	UCSR0B = ( ( 1 << RXCIE0 ) | ( 1 << RXEN0 ) | ( 1 << TXEN0 ) ); 
	
	/* Set frame format: 8 data 1stop */
	UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);              //For devices with Extended IO
	//UCSR0C = (1<<URSEL)|(1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);   //For devices without Extended IO
	
	/* Flush receive buffer */
	x = 0; 			    

	USART_RxTail = x;
	USART_RxHead = x;
	USART_TxTail = x;
	USART_TxHead = x;
}

/* Interrupt handlers */
ISR(USART_RX_vect)
{
	unsigned char data;
	unsigned char tmphead;

	/* Read the received data */
	data = UDR0;                 
	/* Calculate buffer index */
	tmphead = ( USART_RxHead + 1 ) & USART_RX_BUFFER_MASK;
	USART_RxHead = tmphead;      /* Store new index */

	if ( tmphead == USART_RxTail )
	{
		/* ERROR! Receive buffer overflow */
	}
	
	USART_RxBuf[tmphead] = data; /* Store received data in buffer */
}

ISR(USART_UDRE_vect)
{
	unsigned char tmptail;

	/* Check if all data is transmitted */
	if ( USART_TxHead != USART_TxTail )
	{
		/* Calculate buffer index */
		tmptail = ( USART_TxTail + 1 ) & USART_TX_BUFFER_MASK;
		USART_TxTail = tmptail;      /* Store new index */
	
		UDR0 = USART_TxBuf[tmptail];  /* Start transmition */
	}
	else
	{
		UCSR0B &= ~(1<<UDRIE0);         /* Disable UDRE interrupt */
	}
}

/* Read and write functions */
unsigned char USART0_Receive( void )
{
	unsigned char tmptail;
	
	while ( USART_RxHead == USART_RxTail )  /* Wait for incomming data */
		;
	tmptail = ( USART_RxTail + 1 ) & USART_RX_BUFFER_MASK;/* Calculate buffer index */
	
	USART_RxTail = tmptail;                /* Store new index */
	
	return USART_RxBuf[tmptail];           /* Return data */
}

void USART0_Transmit( unsigned char data )
{
	unsigned char tmphead;
	/* Calculate buffer index */
	tmphead = ( USART_TxHead + 1 ) & USART_TX_BUFFER_MASK; /* Wait for free space in buffer */
	while ( tmphead == USART_TxTail );

	USART_TxBuf[tmphead] = data;           /* Store data in buffer */
	USART_TxHead = tmphead;                /* Store new index */

	UCSR0B |= (1<<UDRIE0);                    /* Enable UDRE interrupt */
}

unsigned char DataInReceiveBuffer( void )
{
	return ( USART_RxHead != USART_RxTail ); /* Return 0 (FALSE) if the receive buffer is empty */
}

I undestand the code but I don't get the reason why is not working... :cry:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
      USART0_Transmit(data);
      PORTD &= ~(1<<2); //MAX485 on for reception 

USART0_Transmit does not wait for the transmission being complete, therefore you switch the MAX485 during the ongoing transmission.

Stefan Ernst

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

Hello sternst!
Thank you very much!! To be honest I didn't expect a so fast answer :D
So I have to wait until the transmission is finished.
Could it be a good way with a flag inside the ISR(USART_UDRE_vect) and manage it from the main with get & set???

Thanks once again

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

Use TXC not UDRE. In fact this is the likely raison d'etre for TXC.

UDRE just means that it's OK to load the next character but the current one may stil be in the process of being shifted down the line. TXc, on the otehr hand, means the last bit has left the shift register.

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

Ok!
Now it's working. Clawson you're right it's a better way with TXC.

Thanks!!