Help:USART Communication program in AVR Assembler

Microcontroller Topics
Post Reply
User avatar
Herath
Major
Major
Posts: 417
Joined: Thu Aug 05, 2010 7:09 pm

Help:USART Communication program in AVR Assembler

Post by Herath » Mon Aug 22, 2011 1:30 pm

I have been trying to get a little code to work on the ATMega16 so that it will echo back what I am sending to it via USART. I can do this easily with AVR C. I usually do it with interrupts. So I tried the same code in assembler, but it does not seem to work with interrupt. It works fine if i use polling.

This is my first AVR Assembler program which will do something other than turning on a LED. :)

Code: Select all

/*
 * test.asm
 *
 *  Created: 8/22/2011 1:19:51 AM
 *   Author: Harindra
 */ 
.NOLIST
.INCLUDE "m16def.inc"
.LIST
.DEVICE ATMEGA16

.def i=r16
.def temp=r17
.def buffer=r18

.CSEG

.ORG $000
rjmp main;$0
reti;$002
reti;$004
reti;$006
reti;$008
reti;$00A
reti;$00C
reti;$00E
reti;$010
reti;$012
reti;$014
rjmp USART_RXC;$016
;
;or this way?
;.ORG $016
;rjmp USART_RXC

;-------------------------------
main:
;init stack
ldi temp,HIGH(RAMEND)
out sph,temp
ldi temp,LOW(RAMEND)
out spl,temp

call INIT_USART
loop:rjmp loop;loop forever


;--------------------------------
USART_RXC:
cli
push i
in i,SREG
push i

in buffer,UDR

ready:
ldi i,(UCSRA)&(1<<UDRE)
tst i
breq ready

out UDR,buffer

pop i
out SREG,i
pop i

reti



INIT_USART:
;init usart for 4800bps baud
;F_CPU is 12MHz
;8bit data, noparity
ldi i,$0
out UBRRH,i
ldi i,$9B
out UBRRL,i

ldi i,(1<<RXCIE)|(1<<RXEN)|(1<<TXEN)
out UCSRB,i

ldi i,(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0)
out UCSRC,i
sei
ret

Edit--
It seems like i have a problem in setting up the UCSRC register. I am still working on it
User avatar
Herath
Major
Major
Posts: 417
Joined: Thu Aug 05, 2010 7:09 pm

Re: Help:USART Communication program in AVR Assembler

Post by Herath » Mon Aug 22, 2011 3:40 pm

Finally... working
the Atmega i am using is a ATMega16A. There is not much hardware difference as I understand.
changed the loop to check UDRE to

Code: Select all

ready:
sbis UCSRA,UDRE
rjmp ready
Anyway, now it is working as expected. But still I get the definitions in the m16adef.inc in my list file. Seems like i have used the .NOLIST wrong way.

Code: Select all

.NOLIST
.INCLUDE "m16adef.inc"
.LIST
.DEVICE ATMEGA16A

.def i=r16
.def temp=r18
.def buffer=r19

.cseg


.org $000
rjmp main;$0

.org URXCaddr
rjmp USART_RXC;$016

;-------------------------------
main:
;init stack
ldi temp,HIGH(RAMEND)
out sph,temp
ldi temp,LOW(RAMEND)
out spl,temp


rcall INIT_USART

loop:rjmp loop;loop forever


;--------------------------------
USART_RXC:
cli
push i
in i,SREG
push i

in i,UDR

ready:
sbis UCSRA,UDRE
rjmp ready

out UDR,i


pop i
out SREG,i
pop i
sei
reti



INIT_USART:
;init usart for 4800bps baud
;F_CPU is 12MHz
;8bit data, noparity
ldi i,$0
out UBRRH,i
ldi i,$9B
out UBRRL,i

ldi i,(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0)
out UCSRC,i


ldi i,(1<<RXCIE)|(1<<RXEN)|(1<<TXEN)
out UCSRB,i


sei
ret
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: Help:USART Communication program in AVR Assembler

Post by Neo » Mon Aug 22, 2011 4:46 pm

Hi Herath,

It is nice to see you are back on track with AVR after the last disaster :)

Here I'm adding a C code with all required settings for an interrupt driver UART with ATMega16.

Code: Select all

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

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

int main (void)
{
	UCSRB |= (1 << RXEN) | (1 << TXEN);   // Turn on the transmission and reception circuitry
	UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes

	UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
	UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register

	UCSRB |= (1 << RXCIE); // Enable the USART Recieve Complete interrupt (USART_RXC)
	sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed

	for (;;) // Loop forever
	{
		// Do nothing - echoing is handled by the ISR instead of in the main loop
	}   
}

ISR(USART_RXC_vect)
{
	char ReceivedByte;
	ReceivedByte = UDR; // Fetch the received byte value into the variable "ByteReceived"
	UDR = ReceivedByte; // Echo back the received byte back to the computer
} 
I do not see following things in your code.
  1. Enable the Global Interrupt Enable flag
  2. ISR routine to catch the interrupt
User avatar
Herath
Major
Major
Posts: 417
Joined: Thu Aug 05, 2010 7:09 pm

Re: Help:USART Communication program in AVR Assembler

Post by Herath » Mon Aug 22, 2011 5:31 pm

Neo wrote:
I do not see following things in your code.
  1. Enable the Global Interrupt Enable flag
  2. ISR routine to catch the interrupt
Thanks neo.

I am having "sei" in the ASM source inside the INIT_USART routine at line number 57. ISR for handling UART RXC at line number 34. AND ISR call,

.org URXCaddr
rjmp USART_RXC

I did this in C many times for few experiments. Just wanted to write the whole program in assembler.

Although I fixed the demo board, most of the parts are dead. :D . I can use the buzzer connected to OC2, 4 LEDs connected to PA0 to PA3. USART. I did not check anything on the TWI. I am not sure if the LCD is working too. Few pads on that port came out while i was trying flood and suck method to solder the ATMega16.

And this board is not a very good idea. I can't change the circuit when I want to try a different things. So, I am thinking about buying separate parts and building them as modules or just buying pre-built modules.

I did some experiments with USART, Timers and PWM. And going to try learning assembler as well. Can't do much other than that on this board.
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: Help:USART Communication program in AVR Assembler

Post by Neo » Mon Aug 22, 2011 9:24 pm

I am having "sei" in the ASM source inside the INIT_USART routine at line number 57. ISR for handling UART RXC at line number 34
Ohhh.. I missed them. On the first code you have used 'sei' at init routine but on ISR you simply disable all interrupts (you are not enabling again). So this is a bug. But I see you have corrected it on the 2nd code. But cli and sei isn't required to write on the ISR just becuase when you are servicing it, no other interrupt will be triggered. So only enabling at the init routine is enough.
Post Reply

Return to “Microcontrollers”