Atmega8515 avr usart, avr memory, avr журналы моделирования цикла процессора
У меня такой код на 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
Я запускаю этот код в Proteus и получаю следующие ошибки:
ПК =0x0030. [AVR USART] Ошибка четности RX. [U1]
ПК =0x0024. [ПАМЯТЬ AVR] Внешняя память Чтение, пока интерфейс не включен (SRE=0): [0x0260]. [U1]
ПК =0x0000. [ПАМЯТЬ AVR] Чтение из внешней памяти, когда интерфейс не активирован (SRE=0): [0x0261]. [U1]
ПК =0x0000. [ЦП AVR] RET-адрес = 0x0000 [U1]
ПК =0x0002. [ПАМЯТЬ AVR] Запись во внешнюю память, когда интерфейс не включен (SRE=0): [0x0261]=01. [U1]
ПК =0x0002. [ПАМЯТЬ AVR] Запись во внешнюю память, когда интерфейс не включен (SRE=0): [0x0260]=00. [U1]**
ПК =0x0024. [ПАМЯТЬ AVR] Внешняя память Чтение, пока интерфейс не включен (SRE=0): [0x0260]. [U1]**
ПК =0x0002. [ПАМЯТЬ AVR] Чтение из внешней памяти, когда интерфейс не активирован (SRE=0): [0x0261]. [U1]**
Я также включаю схему Proteus для лучшего понимания
1 ответ
Похоже, проблема в неинициализированном указателе стека.
После сброса SPH:SPL инициализируется значением 0x0000, поэтому любая запись в стек (push
, rcall
и т.д.) будет писать по адресу 0x0000 (который отображается в регистр r0), после чего указатель стека будет уменьшен и станет 0xFFFF. В ATmega8515 ячейки ОЗУ с адресом 0x0260 и выше отображаются во внешнюю память, которая, очевидно, не подключена к вашей схеме.
Добавьте инициализацию указателя стека в качестве первого действия в вашей программе, например:
ldi r16, high(RAMEND)
out SPH, r16
ldi r16, low(RAMEND)
out SPL, r16
Кроме того, в вашей программе нет цикла, а после rcall USART_send
это выйдет за рамки init_USART:
этикетка.
Наверное, вы хотите добавить rjmp main
в таком случае.
А зачем вам писать программу на ассемблере? Не проще ли написать на С?