Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

STK600 : Using USART Tx and Rx Interrupt

USART Tutorial :

In the last tutorial we saw timers in ATmega2560 with overflow and output compare match Interrupt. In this tutorial we will see Usart in ATmega2560.

ATmega2560 has 4 USARTs, USART0 ,USART1, USART2, USART3. It operates in full duplex mode. It has separate registers for Receive and Transmit. USART in ATmega2560 has 3 interrupts

  1. Transmit complete interrupt
  2. Receive complete interrupt
  3. Data register empty interrupt

Both asynchronous and synchronous operations are possible with USART. It supports serial frames with 5, 6, 7, 8 or 9 data bits and 1 or 2 stop bits.

In this tutorial we will see USART1 transmit Complete Interrupt first and then USART1 receive complete interrupt example.

USART Initialization :

As mentioned above for both examples USART initialization will be almost same, only in both the examples we need to enable corresponding interrupts.

UCSR1A :

This register contains flags which are set on occurrence of corresponding event, just like RXC1 flag is set when receive buffer is empty i.e. there is no unread data in receive buffer and TXC1 flag which is set when entire frame in transmit shift register is shifted out and currently no data available in transmit buffer. We are using USART in asynchronous mode but not with double transmission speed. Hence,

UCSR1A=0x00;

UCSR1B :

This register contains interrupt enable bits for all three interrupt s mentioned above. First we will see USART1 transmit example, hence enable Transmit Complete Interrupt here. Also we need to enable receiver and transmitter in order to receive and transmit data. UCSZ12 will be zero as we are going to use 8-bit data.

UCSR1B|=(1<<TXCIE1)|(1<<RXEN1)|(1<<TXEN1);

Also

SREG|=0x80;      //set global interrupt enable bit

UCSR1C :

This register contains mode selection bits of operation of USART which is asynchronous in our case therefore these bits will be 0. Other bits are to select parity, stop bits, character size and clock polarity of USART. In our case it will be disabled parity, 1 stop bit, 8-bit character size and clock polarity bit will be 0 as we are using asynchronous mode.

UCSR1C|=(1<<UCSZ11)|(1<<UCSZ10);

UBRR1 :

UBRR1 register is used to write the baud rate for USART communication. As system clock is 1 MHz I will set UBRR1 register with value 0x0c which is for baud rate 4800 and the % error for 4800 is 0.2 % which is under + / – 2 %. The baud rate and error calculation formula are given in the datasheet.                                                                                                                                                                                                          Note : The % error in baud rate has to be under + / – 2 %.

UBRR1=0x0c;

UDR1 :

UDR1 register is used to transmit and receive data in serial communication. The USART transmit data buffer and receive data buffer share same I/O address.

This finishes our USART initialization.

In transmit complete interrupt we will transmit text “This is USART Tx complete interrupt”. The complete code for USART Tx  complete interrupt is shown below.

#include <avr/io.h>
#include <avr/interrupt.h>


unsigned char message[35]="This is USART Tx complete interrupt",count=0;


void usart_init(void);
void usart_tx(unsigned char msg);


int main(void)
{
 usart_init();
 
 usart_tx(message[count++]);		      //increment count after transmission of first character

 while(1); 
}


void usart_init()
{
 SREG|=0x80;				      //set global interrupt enable bit
 
 UBRR1=0x0c;				      //baud rate 4800, % error 0.2 %

 UCSR1B|=(1<<TXCIE1)|(1<<TXEN1)|(1<<RXEN1);   //enable transmitter, receiver, enable transmit complete interrupt

 UCSR1C|=(1<<UCSZ11)|(1<<UCSZ10);	      //8-bit data, 1 stop bit, parity disabled, asynchronous operation
}


void usart_tx(unsigned char msg)
{
 while(!(UCSR1A & (1<<UDRE1)));               //wait until transmit buffer becomes empty 
 
 UDR1=msg;				      //transmit first character by polling	
}


ISR(USART1_TX_vect)
{
 if(count<35)
 {
	UDR1=message[count++];		      //increment count after first transmission
 }
}

Output of code on Docklight Terminal is shown below.

Now let’s move to USART receive complete interrupt. USART initialization will be same as that of transmit complete example. Only instead of transmit complete interrupt we will enable receive complete interrupt here. So

UCSR1B|=(1<<RXCIE1)|(1<<RXEN1)|(1<<TXEN1);

Also

SREG|=0x80;      //set global interrupt enable bit

In receive complete example we will transmit same characters which are entered using keyboard.

In this example after reception of first character immediately receive complete interrupt fires and before transmission of first received character via polling next character is received through ISR.

To avoid this we will use two different variables to receive data. i.e. <strong>buff</strong> to receive data in polling and <strong>data </strong>to receive data in ISR. Also we will use one flag <strong>rd_data_flg </strong>which will be set after transmission of first character which is received by polling. The complete code for USART Rx complete interrupt is shown below.

#include <avr/io.h>
#include <avr/interrupt.h>


volatile unsigned char rx_complete_flg;	      //clear when data is transmitted and set when data is received 	
unsigned char rd_data_flg;                    //avoids char reception in ISR until first char in polling is transmitted
unsigned char buff;                           //stores char to be transmitted by polling
unsigned char data;			      //stores further received char from ISR


void usart_init(void);
void usart_tx(unsigned char msg);
unsigned char usart_rx(void);


int main(void)
{
 usart_init();
 
 buff=usart_rx();
 
 usart_tx(buff);
 
 while(1)
 {
  if(rx_complete_flg)
  {
	  rx_complete_flg=0;
	  
	  usart_tx(data);
  }
 }
}


void usart_init()
{
 SREG|=0x80;					  //set global interrupt enable bit
	
 UBRR1=0x0c;	                                  //baud rate 4800, % error 0.2 %

 UCSR1B|=(1<<RXCIE1)|(1<<TXEN1)|(1<<RXEN1);	  //enable transmitter, receiver, enable receive complete interrupt

 UCSR1C|=(1<<UCSZ11)|(1<<UCSZ10);	          //8-bit data, 1 stop bit, parity disabled, asynchronous operation
}


void usart_tx(unsigned char msg)
{
 while(!(UCSR1A & (1<<UDRE1)));			  //wait until transmit buffer becomes empty 
	
 UDR1=msg;
}


unsigned char usart_rx()
{
 while(!(UCSR1A & (1<<RXC1)));			  //wait until reception is completed
 
 return UDR1;	                                  //receive first character by polling
}


ISR(USART1_RX_vect)
{
 rx_complete_flg=1;
 
 if(rd_data_flg)			          //avoid data in ISR before transmission of first char in polling
 
	data=UDR1;
	
 else
 
	rd_data_flg=1;	 			  //set flag to start reading data from ISR
}

Output of code on Docklight Terminal is shown below.

Thanks for reading. Don’t forget to share your views and questions as comments below.




This post first appeared on Embedded Tutorials, please read the originial post: here

Share the post

STK600 : Using USART Tx and Rx Interrupt

×

Subscribe to Embedded Tutorials

Get updates delivered right to your inbox!

Thank you for your subscription

×