I have such code for atmega8515
.nolist
.include "m8515def.inc"
.list
.equ fCK = 8000000
.equ BAUD = 9600
.equ UBRR_value = (fCK/(BAUD*16))-1
.cseg
.org 0
main:
rcall init_USART
LDI R16, 0xFF
OUT DDRC, R16
rcall USART_recieve
OUT PORTC, R16
LDI R16, 0x00
OUT DDRA, R16
in R16, PINA
OUT PORTC, R16
rcall USART_send
init_USART:
ldi R16, high(UBRR_value)
out UBRRH, R16
ldi R16, low(UBRR_value)
out UBRRL, R16
ldi R16, (1<<RXEN)|(1<<TXEN)|(0<<RXCIE)|(0<<TXCIE)|(0<<UDRIE)
out UCSRB, R16
ldi R16, (1<< URSEL)|(1<<UPM1)|(1<<UPM0)|(1<< UCSZ1)|(1<< UCSZ0)
out UCSRC, R16
ret
USART_send:
out UDR, R16
sending:
sbis UCSRA, TXC
rjmp sending
ret
USART_recieve:
sbis UCSRA, RXC
rjmp USART_recieve
in R16, UDR
ret
I run this code in proteus and get the following errors cycled
PC=0x0030. [AVR USART] RX Parity Error. [U1]
PC=0x0024. [AVR MEMORY] External Memory Read while interface is not enabled (SRE=0): [0x0260]. [U1]
PC=0x0000. [AVR MEMORY] External Memory Read while interface is not enabled (SRE=0): [0x0261]. [U1]
PC=0x0000. [AVR CPU] RET address = 0x0000 [U1]
PC=0x0002. [AVR MEMORY] External Memory Write while interface is not enabled (SRE=0): [0x0261]=01. [U1]
PC=0x0002. [AVR MEMORY] External Memory Write while interface is not enabled (SRE=0): [0x0260]=00. [U1]**
PC=0x0024. [AVR MEMORY] External Memory Read while interface is not enabled (SRE=0): [0x0260]. [U1]**
PC=0x0002. [AVR MEMORY] External Memory Read while interface is not enabled (SRE=0): [0x0261]. [U1]**
I also include proteus schema for better understanding
Looks like the problem is in uninitialized stack pointer.
After the reset, SPH:SPL is initialized to 0x0000, therefore any writing to the stack (by push
, rcall
etc.) will write to address 0x0000 (which is mapped to register r0) after which the stack pointer will be decreased and become 0xFFFF. In ATmega8515 RAM locations at 0x0260 and above are mapped to the external memory, which is obviously is not connected in your schematics.
Add stack pointer initialization as the first action in your program, e.g.:
ldi r16, high(RAMEND)
out SPH, r16
ldi r16, low(RAMEND)
out SPL, r16
Also, there is no loop in your program, and after rcall USART_send
it will go beyond init_USART:
label.
Probably you want to add rjmp main
at that point.
And why you need to write the program in assembler? Isn't it simpler to write it in C?