Страница 1 из 1

в эмуляторах не работает стек ATmega16 что яделаю не так?

Добавлено: Пн фев 16, 2009 16:17:44
Qwq
Здравствуйте!
Почему-то из подпрограммы не возвращает, а отправляет в начало исполняемого сегмента.
что я сделал не так?
В железе не пробывал ибо пока не на чем.
код ниже.
Длинные коды оформляйте вложением. Паятель.

Re: в эмуляторах не работает стек ATmega16 что яделаю не так

Добавлено: Пн фев 16, 2009 18:38:20
smac
Qwq писал(а):Здравствуйте!
Почему-то из подпрограммы не возвращает, а отправляет в начало исполняемого сегмента.
что я сделал не так?
Вот смотрите здесь

Код: Выделить всё

brne sensorinuse 	;то обрабатываем это самое чегонибудь
Вы переходите на метку sensorinuse, где есть такой код

Код: Выделить всё

	cpi sensor,1 	; если считали 1
	brne s1			; тогда обрабатываем функцией S1
	cpi sensor,2	; Если считали 2
	brne s2			; тогда обрабатываем функчией S2
где s1 и s2 фактически подпрограммы.
По выходу из s1 иди s2 выполняетс ret, которая вынимает из стка адрес возврата, поскольку в стеке у вас ничего нет, то адрес возврата неизвестен, и возврат может быть куда угодно.
Т. е. s1 и s2 Вы вызывете некорректно, а сдедовательно дальнейшие действия уже смысла не имеют. Корретктный вызов подпрограмм делается так:

Код: Выделить всё

rcall s1 
; или
rcall s2
Вообще на мой взгляд програма бездумно написана, на самом деле чтобы заработа править много надо.

Добавлено: Пн фев 16, 2009 18:46:39
Caturday
Таблица обработки прерываний неправильна - раз, стек по-моему надо инитить так:

Код: Выделить всё

ldi Temp,low(RamEnd*2)        
out SPL,temp 
ldi Temp,high(RamEnd*2) 
out SPH,temp
два

Добавлено: Пн фев 16, 2009 20:01:37
Pooher
Таблица обработки прерываний неправильна - раз, стек по-моему надо инитить так:
Код:
ldi Temp,low(RamEnd*2)
out SPL,temp
ldi Temp,high(RamEnd*2)
out SPH,temp
Чушь полная :o

Код: Выделить всё

MAIN замкнутая функция в которой мы все делаем 
main: 
   in sensor,PinB      ;проверяем сенсоры 
   clr temp, 0           ; обнуляем temp
   cpse sensor, temp     ;если sensor =0, то пропускаем следующую     команду 
   RCALL sensorinuse   ;то ВЫЗЫВАЕМ ПОДПРОГРАММУ sensorinuse

rjmp main
И здесь тоже подправить:

Код: Выделить всё

   sensorinuse: 
   cpi sensor,1    ; если считали 1 
   breq s1         ; тогда обрабатываем функцией S1 
   cpi sensor,2   ; Если считали 2 
   breq s2         ; тогда обрабатываем функчией S2 
        ret   
      
      s1: 
      ldi temp, 0b00000110 ; оба мотора вперед 
       rcall usemotor 
      ret 
       
      s2: 
      ldi temp, 0b00001001 ; оба мотора назад 
      rcall usemotor 
      ret 
В данном случае ret в s1 и s2 осуществляют выход из подпрограммы sensorinuse.

Добавлено: Вт фев 17, 2009 14:17:15
Qwq
Всем обгромное спасибо. сам бы я очень долго пытался понять что не так...