Перейти к содержанию

Проблемы Со Стеком


skef

Рекомендуемые сообщения

кто- нибудь знает что означает

"AVR Simulator: tracker stack size: 256, real stack size: 2, cleaning up. Step Out may not work."

писал программу, компилятор постоянно сообщал о переполнении стека,

(ОЗУ нигде не использовал) замучился, дописал инициализацию стека,

ошибок стало меньше, потом потом опять замучился, и в главный цикл опять написал

инициализацию стека. вот сейчас он сообщает:

AVR Simulator: tracker stack size: 256, real stack size: 2, cleaning up. Step Out may not work

кто-нибудь знает, что это означает?

P.S.

компилятор- аврстудио, проц-мега8535

НА ЛЮБОЙ ЭЛЕМЕНТ НАЙДЕТСЯ МОЩНОСТЬ, КОТОРАЯ ЕГО СОЖЖЕТ

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Чтот не так инициализируете.. И вообще настройку стека надо делать ОДИН РАЗ!!!! Приведите вашу програму. Может быть у вас просто рекурсия где получилась...

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

не бейте сильно... вот программа:

.include "C:\Program Files\Atmel\AVR Tools\AvrAssembler2\Appnotes\m8535def.inc"
rjmp RESET ; Reset Handler
nop;rjmp EXT_INT0 ; IRQ0 Handler
nop;rjmp EXT_INT1 ; IRQ1 Handler
rjmp TIM2_COMP ; Timer2 Compare Handler
nop;rjmp TIM2_OVF ; Timer2 Overflow Handler
nop;rjmp TIM1_CAPT ; Timer1 Capture Handler
rjmp TIM1_COMPA ; Timer1 CompareA Handler
rjmp TIM1_COMPB ; Timer1 CompareB Handler
nop;rjmp TIM1_OVF ; Timer1 Overflow Handler
rjmp TIM0_OVF ; Timer0 Overflow Handler
nop;rjmp SPI_STC; ; SPI Transfer Complete Handler
nop;rjmp UART_RXC ; UART RX Complete Handler
nop;rjmp UART_DRE ; UDR Empty Handler
nop;rjmp UART_TXC ; UART TX Complete Handler
nop;rjmp ADC ; ADC Conversion Complete Interrupt Handler
nop;rjmp EE_RDY ; EEPROM Ready Handler
nop;rjmp ANA_COMP ; Analog Comparator Handler

table:
.db 0b10000000	;a
.db 0b00000001	;1
.db 0b10000000	;a	
.db 0b00000010	;2
.db 0b10000000	;a
.db 0b00000100	;3
.db 0b10000000	;a
.db 0b00001000	;4
.db 0b01000000	;b
.db 0b00001000	;4
.db 0b00100000	;c
.db 0b00001000	;4
.db 0b00010000	;d
.db 0b00001000	;4
.db 0b00010000	;d
.db 0b00000100	;3
.db 0b00010000	;d
.db 0b00000010	;2
.db 0b00010000	;d
.db 0b00000001	;1
.db 0b00001000	;e
.db 0b00000001	;1
.db 0b00000100	;f
.db 0b00000001	;1

reset:
ldi r16,255				;загрузка числа 255 в рон р16
out ddra,r16			;настройка порта а на вывод
out ddrc,r16			;настройка порта с на вывод
ldi r16,(0<<pb3)+(0<<pb4)+(0<<pb5)
out ddrb,r16			;настройка pb3,pb4,pb5 на ввод (кнопки)
ldi r16,(1<<pb3)+(1<<pb4)+(1<<pb5)
out portb,r16			;и установка подтягивающих резисторов
ldi r16,(1<<pb0)+(1<<pb1)+(1<<pb2)
out ddrb,r16			;настройка pb0,pb1,pb2 на вывод (светодиоды)
ldi r16,(1<<pd5)		;pd5 - вывод OC1A
out ddrd,r16			;
ldi r16,(1<<com1a0)
out tccr1a,r16			;насторойка Т/С1: вывода OC1A на изменение уронвня 
ldi r16,(1<<cs10)+(1<<cs12);при совпадении содержимого счечика
out tccr1b,r16			;и регистра сравнения
ldi r16,(1<<ocie1a)+(1<<ocie2)+(1<<ocie1b)+(1<<TOIE0)
out timsk,r16			;разрешение прерываний: ocie1a,ocie2,ocie1b
ldi r16,high(9760)		;загрузка в регистр сравнения числа
out ocr1ah,r16			;соответствующеего 10С	
ldi r16,low(9760)		;
out ocr1al,r16			;
ldi r16,high(58560)		;загрузка в регистр сравнения числа
out ocr1bh,r16			;соответствующеего 60С	
ldi r16,low(58560)
out ocr1bl,r16
ldi ZH,High (table*2)	;загрузка в регистры адресации начала 
ldi ZL,Low (table*2)	;таблицы (для работы дисплея)
ldi r16,(1<<cs20)+(1<<cs21)+(1<<cs22);
out tccr2,r16			;настройка второго счетчика
ldi r16,81				;(он управляет дисплеем)
out ocr2,r16
ldi r16,(1<<cs00)+(1<<cs01);
out tccr0,r16	
ldi r16, high(RAMEND); Main program start
out SPH,r16
ldi r16, low(RAMEND) ;
out SPL,r16	;
sei						;разрешение всех прерываний

main:
ldi r16, high(RAMEND); Main program start
out SPH,r16
ldi r16, low(RAMEND) ;
out SPL,r16
rjmp main

najato:
ldi r18,0
sei
rjmp main



key1:					;обнуляем Р19 если хотя
in r22,pinb
cp r19,r22				;бы одна кнопка была нажата
breq najato
sei
rjmp main				;уйти в главный цикл


TIM1_COMPA:				;в этой подпрограмме содержимое старшего
					;байта регистра сравнения сравнивается с
in r16,ocr1ah			;числами, если равно - загружается следующее
cpi r16,0b00100110		;число (0-1 в 10с,30с,50с и 1-0 в 11с,31с,51с)
breq edge11s

cpi r16,0b00101001
breq edge30s

cpi r16,0b01110010
breq edge31s

cpi r16,0b01110110
breq edge50s

cpi r16,0b10111110
breq edge51s
sei
rjmp main

TIM1_COMPB:				;после 60 секунд проверить регистр р19
cpi r18,2				;если ,больше или равен 2, уйти в подрограмму led
brge led				;если равен 0 или 1,запретить прерывания и 
ldi r16,0
out porta,r16
out portc,r16
cli						;уйти в цикл с меткой enter
enter:					;бесконечный цикл
rjmp enter


led:
ldi r16,(1<<pb0)+(1<<pb1)+(1<<pb2)
out portb,r16			;зажечь светодиоды,запретить прерывания
cli						;и уйти в цикл с меткой enter
rjmp enter

edge11s:
inc r18
ldi r16,high(10736)
out ocr1ah,r16
ldi r16,low(10736)
out ocr1al,r16
sei
rjmp main

edge30s:
ldi r16,high(29280)
out ocr1ah,r16
ldi r16,low(29280)
out ocr1al,r16
sei
rjmp main

edge31s:
inc r18
ldi r16,high(30256)
out ocr1ah,r16
ldi r16,low(30256)
out ocr1al,r16
sei
rjmp main

edge50s:
ldi r16,high(48800)
out ocr1ah,r16
ldi r16,low(48800)
out ocr1al,r16
sei
rjmp main

edge51s:
inc r18
ldi r16,high(49776)
out ocr1ah,r16
ldi r16,low(49776)
out ocr1al,r16
sei
rjmp main

TIM2_COMP:
inc r20					;увеличиваем р20, сравниваем с числом 24
cpi r20,24				;если равно, уходим на метку load
breq load				;в этой подпрограмме загужается начало таблицы
sei						;разрешение всех прерываний		
inc ZL					;увеличение адреса и загрузка 
lpm						;числа по этому адресу
mov r16,r0				;пересылка в РОН r16 и далее в порт А (там сегменты)
out porta,r16		
cpi r16,0				;если 0, загрузить все снова
breq TIM2_COMP

reload:
inc ZL					;увеличение адреса и загрузка 
lpm
mov r17,r0				;пересылка в РОН r16 и далее в порт С (там ячейки)
cpi r17,0				;если 0, загрузить все снова
breq reload
out portc,r17
rjmp main

load:					;когда все значения в дисплее перебраны
ldi r20,0				;("змейка2 описала круг), загружается начало
ldi ZH,High (table*2)	;(следующий круг)
ldi ZL,Low (table*2)	;
rjmp main

TIM0_OVF:
in r19,pinb				;в этом цикле проверяется, не нажата ли кнопка 
sbrc r19,3				;S3,S4,S5
rjmp key1				;
sbrc r19,4
rjmp key1
sbrc r19,5
rjmp key1
sei
rjmp main

я сделал настройку стека один раз. компилятор начал указывать на переполнение стека.

модель в протеусе была. так она вообще висла намертво.

НА ЛЮБОЙ ЭЛЕМЕНТ НАЙДЕТСЯ МОЩНОСТЬ, КОТОРАЯ ЕГО СОЖЖЕТ

Ссылка на комментарий
Поделиться на другие сайты

Особенности хранения литиевых аккумуляторов и батареек

Потеря емкости аккумулятора напрямую зависит от условий хранения и эксплуатации. При неправильном хранении даже самый лучший литиевый источник тока с превосходными характеристиками может не оправдать ожиданий. Технология, основанная на рекомендациях таких известных производителей литиевых источников тока, как компании FANSO и EVE Energy, поможет организовать правильный процесс хранения батареек и аккумуляторов. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Ой, ой, ой...... Так писать нельзя.. :) щас перепишу попробую...

Уф :) Нельзя выскакивать из прерывания через RJMP !!!!!! У вас поэтому и переполнен стек!!!

Я чтото не осилил алгоритм... Опишите что вы пытаетесь сделать?

Давайте начнём вот с этого и потихоньку сюда допишем вашу програму. Тут я выполнил полную таблицу векторов и Вашу инициализацию.. Данные (таблицу) лучше всего засунуть на самый конец.

.device ATmega8535
.nolist
.include <m8535def.inc>
.list

.cseg
.org $00
rjmp RESET ; Reset Handler
.org $01
rjmp EXT_INT0 ; IRQ0 Handler
.org $02
rjmp EXT_INT1 ; IRQ1 Handler
.org $03
rjmp TIM2_COMP ; Timer2 Compare Handler
.org $04
rjmp TIM2_OVF ; Timer2 Overflow Handler
.org $05
rjmp TIM1_CAPT ; Timer1 Capture Handler
.org $06
rjmp TIM1_COMPA ; Timer1 CompareA Handler
.org $07
rjmp TIM1_COMPB ; Timer1 CompareB Handler
.org $08
rjmp TIM1_OVF ; Timer1 Overflow Handler
.org $09
rjmp TIM0_OVF ; Timer0 Overflow Handler
.org $0a
rjmp SPI_STC; ; SPI Transfer Complete Handler
.org $0b
rjmp UART_RXC ; UART RX Complete Handler
.org $0c
rjmp UART_DRE ; UDR Empty Handler
.org $0d
rjmp UART_TXC ; UART TX Complete Handler
.org $0e
rjmp ADC_C ; ADC Conversion Complete Interrupt Handler
.org $0f
rjmp EE_RDY ; EEPROM Ready Handler
.org $10
rjmp ANA_COMP ; Analog Comparator Handler
.org $11
rjmp TWI ; Two-wire Serial Interface
.org $12
rjmp EXT_INT2; External Interrupt Request 2
.org $13
rjmp TIMER0_COMP ; Timer/Counter0 Compare Match
.org $14
rjmp SPM_RDY ; Store Program Memory Ready

;

EXT_INT0:
reti;
EXT_INT1:
reti;
TIM2_COMP:
reti;
TIM2_OVF:
reti;
TIM1_CAPT:
reti;
TIM1_COMPA:
reti;
TIM1_COMPB:
reti;
TIM1_OVF:
reti;
TIM0_OVF:
reti;
SPI_STC:
reti;
UART_RXC:
reti;
UART_DRE:
reti;
UART_TXC:
reti;
ADC_C:
reti;
EE_RDY:
reti;
ANA_COMP:
reti;
TWI:
reti;
EXT_INT2:
reti;
TIMER0_COMP:
reti;
SPM_RDY:
reti;
;


RESET: ; Reset Handler

ldi r16, high(RAMEND); Main program start and set ramend
out SPH,r16;
ldi r16, low(RAMEND);
out SPL,r16;

ldi r16,255; Port INIT
out ddra,r16;
out ddrc,r16;
ldi r16,(0<<pb3)+(0<<pb4)+(0<<pb5);
out ddrb,r16;
ldi r16,(1<<pb3)+(1<<pb4)+(1<<pb5);
out portb,r16;
ldi r16,(1<<pb0)+(1<<pb1)+(1<<pb2);
out ddrb,r16;
ldi r16,(1<<pd5);
out ddrd,r16;
ldi r16,(1<<com1a0);
out tccr1a,r16;
ldi r16,(1<<cs10)+(1<<cs12);
out tccr1b,r16;
ldi r16,(1<<ocie1a)+(1<<ocie2)+(1<<ocie1b)+(1<<TOIE0);
out timsk,r16;
ldi r16,high(9760);
out ocr1ah,r16;
ldi r16,low(9760);
out ocr1al,r16;
ldi r16,high(58560);
out ocr1bh,r16;
ldi r16,low(58560);
out ocr1bl,r16;
ldi ZH,High (table*2);
ldi ZL,Low (table*2);
ldi r16,(1<<cs20)+(1<<cs21)+(1<<cs22);
out tccr2,r16;
ldi r16,81;
out ocr2,r16;
ldi r16,(1<<cs00)+(1<<cs01);
out tccr0,r16;
sei;

MAIN:
rjmp MAIN;



.dseg
table:
.db 0b10000000 ;a
.db 0b00000001 ;1
.db 0b10000000 ;a
.db 0b00000010 ;2
.db 0b10000000 ;a
.db 0b00000100 ;3
.db 0b10000000 ;a
.db 0b00001000 ;4
.db 0b01000000 ;b
.db 0b00001000 ;4
.db 0b00100000 ;c
.db 0b00001000 ;4
.db 0b00010000 ;d
.db 0b00001000 ;4
.db 0b00010000 ;d
.db 0b00000100 ;3
.db 0b00010000 ;d
.db 0b00000010 ;2
.db 0b00010000 ;d
.db 0b00000001 ;1
.db 0b00001000 ;e
.db 0b00000001 ;1
.db 0b00000100 ;f
.db 0b00000001 ;1

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

я старался вылезать их прерывания командой RETI, но счетчик команд после этого вел себя непредсказуемо...(уходил в таблицу векторов прерывания)

т.з. (курсовая работа) (не моя)

устройство делает 3 звуковых сигнала, после каждого сигнала пользователь нажимает кнопку

если не нажимает- сигнал пропущен. если пропущено 2 и более сигналов, через 60 с загораются светодиоды. параллельно со всем этим есть дисплей (4 семисегментных индикатора), по нему змейка дожна бегать (для этого собственно и таблица), а черех 60с гаснуть.

НА ЛЮБОЙ ЭЛЕМЕНТ НАЙДЕТСЯ МОЩНОСТЬ, КОТОРАЯ ЕГО СОЖЖЕТ

Ссылка на комментарий
Поделиться на другие сайты

Правильно что вёл себя непредсказуемо!!! Вы то ведь перед этим неправильно инитили стек и если используете правильный МК для компиляции и правильный для проверки!! У некоторых МК конец памяти может быть другой!! Поэтому и попадаете не туда!!! Командой RJMP вы выскакиваетет из прерывания и оно НЕ ЗАКАНЧИВАЕТСЯ!!!! с каждым прерыванием у вас откладывается на стеку два байта!!! И после переполнения стек как бы вернётся на начало.. так как вы не выскакиваете ваша програма как бы и работает :) Но всё это не правильно.

Давайте уточниме задание:

1. частота каждого звукового сигнала, и их длительность.

2. как они должны звучать? случайно? по очереди?

3. как сязан дисплей и то что на нём показывается с звукамии нажатием кнопок???

Ссылка на комментарий
Поделиться на другие сайты

неправильно инитили стек - как? что неверно?

насколько я помню границы стека определятся границей озу, она для разных процов разная, но они все определяются в inc - файле.

перед RJMP - SEI - разрешаем прерывания и идем дальше. - вот это полный идиотизм !!!!

а RETI вроде тоже самое делает, только RETI должно идти где было. - RETI ещё выталкивает из стека садрес возврата и содежимое флагов!!!

и еще вопрос. если озу нигде не используется, может ли это помешать ходу программы? - я бы это ненавал програмой...

частота каждого звукового сигнала, и их длительность

-за минуту должно быть 3, сигнал не совсем звуковой, проименительно к процессору это установление еденицы на вывод. длительность - у меня 1сек, импульсы идут: 10с, 30с, 50с

дисплей с кнопками и звуком не связан. - а зачем тогда нужен вообще? Только для того чтобы чтото там крутилось??

НА ЛЮБОЙ ЭЛЕМЕНТ НАЙДЕТСЯ МОЩНОСТЬ, КОТОРАЯ ЕГО СОЖЖЕТ

Ссылка на комментарий
Поделиться на другие сайты

Вы абсолютно неправильно понимаете работу некоторых команд МК !!! Для начала сядьте и изучите ПОДРОБНО что делает каждая команда!!!! Потом ИЗУЧИТЕ директивы асемблера!!! То что вы делал - это полное харакири... Вызов прерывания укладывает в стек адрес возврата. А при возврате из прерывания - продолжает програма с того места где её прервали!!! Нужно вашу програму розделить на части которые будут работать отдельно от всего остального. Плюс незабывайте что при входе в прерывание в регистрах могут быть данные которые ещё не обработались!!! И как только начнёте в прерывании копировать в регистр - то теряеете его содержимое перед прерыванием!!!

То что вы уточнил - уточнением не является... Приведите ПОЛНОЕ задание... Для меня это лично не задание вообще... Вы всё ещё больше запутал. Приведите алгоритм работы устройства. И ещё раз вам советую - сядьте и ИЗУЧИТЕ сначала каботу МК. Вы не понимаете как оно работает и поэтому городите такое вот ..........

Ссылка на комментарий
Поделиться на другие сайты

куча справедливых замечаний... даже возразить нечего.

а если не секрет, чем грозит переполнение стека? процессор сбросится?

вот эту работу сегодня сдавали (ЭТИМ прошили реальный контроллер в реальном стенде). звук звучал, дисплей мигал... а через минуту дисплей потух, звук зазвучал непрерывно, дисплей погас, светодиоды не засветились...

а можно как-нибудь сделать чтобы стек не заполнялся?

НА ЛЮБОЙ ЭЛЕМЕНТ НАЙДЕТСЯ МОЩНОСТЬ, КОТОРАЯ ЕГО СОЖЖЕТ

Ссылка на комментарий
Поделиться на другие сайты

Стек заполняется сверху вниз!!! Регистры тоже можно адресовать как память. вот и получается что у вам прерывания начали с вехней части памяти заполнять памято мусором. как дошло од 0 то то в ваших регистрах уже давно НЕ ТЕ ДАННЫЕ которые вы туда записывал!!!! Там везде мусор!!! А чтобы стек не заполнялся - надо правильно возвращаться из прерываний и подпрограм а то приказами iret и ret.

:) В вашем случае конешно ещё может помочь команды PUSH /POP :) но это крайний случай чтобы вытолкнуть с стека ненужный адрес... НЕДЕЛАЙТЕ ТАК!!!

Ссылка на комментарий
Поделиться на другие сайты

вот... вроде переписал. стек не заполняется, и вроде все работает и эмулируется:

.include "C:\Program Files\Atmel\AVR Tools\AvrAssembler2\Appnotes\m8535def.inc"

rjmp RESET ; Reset Handler

nop;rjmp EXT_INT0 ; IRQ0 Handler

nop;rjmp EXT_INT1 ; IRQ1 Handler

rjmp TIM2_COMP ; Timer2 Compare Handler

nop;rjmp TIM2_OVF ; Timer2 Overflow Handler

nop;rjmp TIM1_CAPT ; Timer1 Capture Handler

rjmp TIM1_COMPA ; Timer1 CompareA Handler

rjmp TIM1_COMPB ; Timer1 CompareB Handler

nop;rjmp TIM1_OVF ; Timer1 Overflow Handler

rjmp TIM0_OVF ; Timer0 Overflow Handler

nop;rjmp SPI_STC; ; SPI Transfer Complete Handler

nop;rjmp UART_RXC ; UART RX Complete Handler

reti;rjmp UART_DRE ; UDR Empty Handler

nop;rjmp UART_TXC ; UART TX Complete Handler

nop;rjmp ADC ; ADC Conversion Complete Interrupt Handler

nop;rjmp EE_RDY ; EEPROM Ready Handler

nop;rjmp ANA_COMP ; Analog Comparator Handler

reset:

ldi r16,255

out ddra,r16

out ddrc,r16

ldi r16,(0<<pb3)+(0<<pb4)+(0<<pb5)

out ddrb,r16

ldi r16,(1<<pb3)+(1<<pb4)+(1<<pb5)

out portb,r16

ldi r16,(1<<pb0)+(1<<pb1)+(1<<pb2)

out ddrb,r16

ldi r16,(1<<pd5)

out ddrd,r16

ldi r16,(1<<com1a0)

out tccr1a,r16

ldi r16,(1<<cs10)+(1<<cs12)

out tccr1b,r16

ldi r16,(1<<ocie1a)+(1<<ocie1b)+(1<<TOIE0)+(1<<ocie2)

out timsk,r16

ldi r16,high(9760)

out ocr1ah,r16

ldi r16,low(9760)

out ocr1al,r16

ldi r16,high(58560)

out ocr1bh,r16

ldi r16,low(58560)

out ocr1bl,r16

ldi r16,(1<<cs20)+(1<<cs21)+(1<<cs22);

out tccr2,r16

ldi ZH,High (table*2)

ldi ZL,Low (table*2)

ldi r16,81

out ocr2,r16

ldi r16,(1<<cs00)+(1<<cs01);

out tccr0,r16

ldi r16, high(RAMEND)

out SPH,r16

ldi r16, low(RAMEND)

out SPL,r16

sei

main:

rjmp main

najato:

ldi r18,0

sei

rjmp main

key1:

in r22,pinb

cp r19,r22

breq najato

reti

TIM1_COMPA:

cli

in r16,ocr1ah

cpi r16,0b00100110

breq edge11s

cpi r16,0b00101001

breq edge30s

cpi r16,0b01110010

breq edge31s

cpi r16,0b01110110

breq edge50s

cpi r16,0b10111110

breq edge51s

reti

TIM1_COMPB:

ldi r16,0

out porta,r16

out portc,r16

cpi r18,2

brge led

reti

enter:

rjmp enter

led:

ldi r16,(1<<pb0)+(1<<pb1)+(1<<pb2)

out portb,r16

rjmp enter

edge11s:

inc r18

ldi r16,high(10736)

out ocr1ah,r16

ldi r16,low(10736)

out ocr1al,r16

reti

edge30s:

ldi r16,high(29280)

out ocr1ah,r16

ldi r16,low(29280)

out ocr1al,r16

reti

edge31s:

inc r18

ldi r16,high(30256)

out ocr1ah,r16

ldi r16,low(30256)

out ocr1al,r16

reti

edge50s:

ldi r16,high(48800)

out ocr1ah,r16

ldi r16,low(48800)

out ocr1al,r16

reti

edge51s:

inc r18

ldi r16,high(49776)

out ocr1ah,r16

ldi r16,low(49776)

out ocr1al,r16

reti

TIM0_OVF:

cli

in r19,pinb

sbrc r19,3

rjmp key1

sbrc r19,4

rjmp key1

sbrc r19,5

rjmp key1

reti

TIM2_COMP:

ldi r16,0

out tcnt2,r16

inc r20 ;увеличиваем р20, сравниваем с числом 24

cpi r20,24 ;если равно, уходим на метку load

breq load ;в этой подпрограмме загужается начало таблицы

;reti;sei ;разрешение всех прерываний

inc ZL ;увеличение адреса и загрузка

lpm ;числа по этому адресу

mov r16,r0 ;пересылка в РОН r16 и далее в порт А (там сегменты)

out porta,r16

cpi r16,0 ;если 0, загрузить все снова

breq TIM2_COMP

reload:

inc ZL ;увеличение адреса и загрузка

lpm

mov r17,r0 ;пересылка в РОН r16 и далее в порт С (там ячейки)

cpi r17,0 ;если 0, загрузить все снова

breq reload

out portc,r17

reti

load: ;когда все значения в дисплее перебраны

ldi r20,0 ;("змейка2 описала круг), загружается начало

ldi ZH,High (table*2) ;(следующий круг)

ldi ZL,Low (table*2) ;

reti

table:

.db 0b10000000 ;a

.db 0b00000001 ;1

.db 0b10000000 ;a

.db 0b00000010 ;2

.db 0b10000000 ;a

.db 0b00000100 ;3

.db 0b10000000 ;a

.db 0b00001000 ;4

.db 0b01000000 ;b

.db 0b00001000 ;4

.db 0b00100000 ;c

.db 0b00001000 ;4

.db 0b00010000 ;d

.db 0b00001000 ;4

.db 0b00010000 ;d

.db 0b00000100 ;3

.db 0b00010000 ;d

.db 0b00000010 ;2

.db 0b00010000 ;d

.db 0b00000001 ;1

.db 0b00001000 ;e

.db 0b00000001 ;1

.db 0b00000100 ;f

.db 0b00000001 ;1

НА ЛЮБОЙ ЭЛЕМЕНТ НАЙДЕТСЯ МОЩНОСТЬ, КОТОРАЯ ЕГО СОЖЖЕТ

Ссылка на комментарий
Поделиться на другие сайты

Позвольте и мне внести некоторые замечания по программе.

Вроде и эмулируется - не показатели нормальной работы программы.

Начнем с таблицы векторов прерываний. Нельзя ставить NOP в таблице, если вектор (прерывание) не используется. Если программа попадет на такой код (все-таки произойдет вызов данного прерывания по стечению обстоятельств), то она не вернется "на место" получив отказ в процедуре обработки прерывания, а будет "скользить" вниз по таблице (nop, nop, nop...), пока не "наткнется " на "рабочий" вектор другого прерывания и выполнит его.

Поэтому вместо:                       Надо писАть:

rjmp RESET                               rjmp RESET

nop                                         reti

nop                                         reti

rjmp TIM2_COMP                       rjmp TIM2_COMP

И так всю таблицу векторов прерываний. В таком варианте программа сразу выйдет из неиспользуемого прерывания, прямо из таблицы векторов.

Следующее. Инициализацию стека лучше выполнить первыми шагами, сразу после метки RESET, а потом уже "заниматься" периферией.

Далее по организации прерываний. Прерывание должно представлять из себя единый блок кода, завершающийся командой RETI. Даже если в коде есть условные переходы, то ими лучше пользоваться ВНУТРИ блока прерывания, обходя код, не подходящий под конкретное условие. Если же без вызова подпрограмм из самого прерывания трудно создавать алгоритм, то возвращаться нужно ОБРАТНО В ПРЕРЫВАНИЕ (можно "на выходе" создать метку, туда и возвращаться) и выходить из него обычным путем, а не перепрыгивать в main, игнорируя работу счетчика команд и оставляя мусор в стеке. Беспорядочное разбрасывание RETI в концах подпрограмм - тоже плохой вариант, а вдруг данную подпрограмму (не в этом примере, но на будущее...) понадобится вызвать не из прерывания, тогда опять глюк получится.

Изменено пользователем Геннадий
Ссылка на комментарий
Поделиться на другие сайты

кто как думает, можно быть уверенным что этот код заработает в реальном МК?

НА ЛЮБОЙ ЭЛЕМЕНТ НАЙДЕТСЯ МОЩНОСТЬ, КОТОРАЯ ЕГО СОЖЖЕТ

Ссылка на комментарий
Поделиться на другие сайты

... - RETI ещё выталкивает из стека садрес возврата и содежимое флагов!!!...

Здравствуйте. Еще маленькое замечание, которое следует из этого.

Команда RETI контроллеров AVR не восстанавливает содержимое SREG.

Изменено пользователем akl
Ссылка на комментарий
Поделиться на другие сайты

Чем больше читаю листинг, тем больше "дух захватывает". :)

skef, давай первое что срабатывает разберем. А именно прерывание по переполнению таймера0 - TIM0_OVF.

TIM0_OVF:

cli                  запрещаешь прерывания

in r19,pinb       состояние порта в регистр 

sbrc r19,3       третий пин = 1 (без нажатия, а значит идем на key1) 

rjmp key1

sbrc r19,4

rjmp key1

sbrc r19,5

rjmp key1

reti

key1:

in r22,pinb       опять состояние порта в регистр (не думаю, что оно изменилось с момента вызова прерывания)

cp r19,r22       теперь сравним два одинаковых значения 

breq najato      они равны, поэтому следующий шаг в najato

reti

najato:

ldi r18,0           раз так, обнуляем r18

sei                  разрешим прерывания

rjmp main         и нарушаем правило (RETI), вылезая из прерывания в main

Мало того, если r19 и r22 (ХЗ почему) окажутся не равны в key1, выход из прерывания пусть и будет допустим, но кто разрешит прерывания снова, ведь в начале обработки они были запрещены (cli). Еще, в обработчике прерывания (TIM0_OVF) невозможно будет проверить состояния 4 и 5 пинов порта, т.к. до них будет не добраться пока не опустишь 3-й пин в ноль.

И так у тебя по всей программе. А ты говоришь "работает, эмулирует". Давай-ка разбирайся.

Ссылка на комментарий
Поделиться на другие сайты

согласен. коряво. в общем-то это антидребезговый алгоритм, если значения совпадают, команда выполняется.

на PB3, PB4, PB5 кнопки, подтяжку я подключил, при замыкании на землю - 0.

НА ЛЮБОЙ ЭЛЕМЕНТ НАЙДЕТСЯ МОЩНОСТЬ, КОТОРАЯ ЕГО СОЖЖЕТ

Ссылка на комментарий
Поделиться на другие сайты

вот... переделал:

TIM0_OVF:

cli

in r19,pinb

sbrc r19,3

rjmp key1

sbrc r19,4

rjmp key1

sbrc r19,5

rjmp key1 если нажата хотя бы одна кнопка, идем в key1

reti

key1:

in r19, pinb считываем порт,

sbrc r23,0 пропускаем, если бит очищен

rjmp key2 если бит установлен, идем на key2

ldi r23,1 устонавливаем этот бит

reti

key2:

ldi r23,0 сбрасываем этот бит

in r22,pinb

cbr r23,0

cp r19,r22

breq najato

reti

так лучше?

НА ЛЮБОЙ ЭЛЕМЕНТ НАЙДЕТСЯ МОЩНОСТЬ, КОТОРАЯ ЕГО СОЖЖЕТ

Ссылка на комментарий
Поделиться на другие сайты

вот... переделал:

TIM0_OVF:

              cli

              in r19,pinb  

              sbrc r19,3  

              rjmp key1  

              sbrc r19,4

              rjmp key1

              sbrc r19,5

              rjmp key1 если нажата хотя бы одна кнопка, идем в key1

TIM0_OVF_QUIT:

sei

              reti

key1:

              in r19, pinb считываем порт, 

              sbrc r23,0 пропускаем, если бит очищен

              rjmp key2 если бит установлен, идем на key2

              ldi r23,1 устонавливаем этот бит

key1_quit:              

              rjmp TIM0_OVF_QUIT

key2:

              ldi r23,0 сбрасываем этот бит

              in r22,pinb

              cbr r23,0

              cp r19,r22

              breq najato

key2_quit:              

              rjmp TIM0_OVF_QUIT; также возможен вариант (rjmp key1_quit)

так лучше?

Подправил. Так лучше. Не стестняйся ставить метки В ЛЮБОМ МЕСТЕ кода, а не только в начале блока (процедуры, функции). Тогда можешь легко переходить по всей программе (относительно). Для удобочитаемости (понятия) алгоритма возвращаться нужно в конец блока, из которого была вызвана данная функция (процедура). Тогда не запутаешься, "закрывая за собой все открытые ранее двери". Кстати в najato нужно сделать так же. Обрати внимание, что при таком раскладе, ты всегда выйдешь через reti из прерывания. Удачи.

Изменено пользователем Геннадий
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...