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

Собственно вопрос вот в чем....

 

Тело вектора прерывания:

 

.org ovf0addr

rjmp Timer0

 

 

Timer0:

cli

 

ldi r16, 0x94 ; 148

out TCNT0, r16

 

sei

 

reti

 

Почему после того как выполнилось все тело прерывания по команде "reti" щетчик переходит по нулевому адресу?

 

И почему после следующих операций:

 

ldi r16, 0x94 ; 148

out TCNT0, r16

 

Число 0x94 не заносится в регистр TCNT0?

Поделиться сообщением


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

Почему после того как выполнилось все тело прерывания по команде "reti" щетчик переходит по нулевому адресу?

Смахивает на переполнение стека.

Поделиться сообщением


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

Смахивает на переполнение стека.

 

Что значит переполнение стека?

 

Может я не правильно выполняю следующую операцию?

 

.cseg

.org 300

 

???

Поделиться сообщением


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

На самом деле даже в приведенном коде много что не правильно.

 

 

Во первых - при переходе на вектор прерывания запрещать/разрешать оные не надо. На досуге посмотрите разницу между командами ret и reti. (Ладно, скажу reti = ret+sei).

 

Также вы от нас кое что утаиваете - какой контроллер, чему равно ovf0addr (судя по всему оно равно у вас 0, а это вектор RESET), и где в коде у вас .org 300?

 

Вопросами стека можете пока не забивать себе голову, главное, чтобы он был проинициализирован.

 

А вообще любая программа на asm должна начинаться примерно так:

 

 

;*************************************************
.cseg    
;*************************************************
rjmp     RESET         ; Reset Handler
reti;    rjmp EXT_INT0 ; IRQ0 Handler
reti;    rjmp EXT_INT1 ; IRQ1 Handler
reti;    rjmp PCINT0 ; PCINT0 Handler
reti;    rjmp PCINT1 ; PCINT1 Handler
reti;    rjmp PCINT2 ; PCINT2 Handler
reti;    rjmp WDT     ; Watchdog Timer Handler
        rjmp TIM2_COMPA; Timer2 CompareA Handler
reti;    rjmp TIM2_COMPB; Timer2 CompareB Handler
reti;    rjmp TIM2_OVF ; Timer2 Overflow Handler
reti;    rjmp TIM1_CAPT ; Timer1 Capture Handler
        rjmp TIM1_COMPA; Timer1 CompareA Handler
reti;    rjmp TIM1_COMPB; Timer1 CompareB Handler
reti;    rjmp TIM1_OVF ; Timer1 Overflow Handler
reti;    rjmp TIM0_COMPA; Timer0 CompareA Handler
reti;    rjmp TIM0_COMPB; Timer0 CompareB Handler
reti;    rjmp TIM0_OVF ; Timer0 Overflow Handler
reti;    rjmp SPI_STC ; SPI Transfer Complete Handler
reti;    rjmp USART_RXC ; USART RX Complete Handler
reti;    rjmp USART_UDRE; UDR Empty Handler
reti;    rjmp USART_TXC ; USART TX Complete Handler    
reti;    rjmp ADC_Conv; ADC Conversion Complete Handler
reti;    rjmp EE_RDY ; EEPROM Ready Handler
reti;    rjmp ANA_COMP ; Analog Comparator Handler
reti;    rjmp TWSI     ; Two-wire Serial Interface Handler
reti;    rjmp SPM_RDY ; Store Program Memory Ready Handler
;----------------------------------------------------------------------------------------------------------------------------

;----------------------------------------------------------------------------------------------------------------------------
RESET: 
    ldi     tmp,    high(RAMEND) ; Main program start
    out     SPH,    tmp         ; Set Stack Pointer to top of RAM
    ldi     tmp,    low(RAMEND)
    out     SPL,    tmp

 

 

Этот код берется прямиком из даташит, он приведен в разделе Interrupts.

Поделиться сообщением


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

Вот код всей прогаммы:

 

.include "m128def.inc"

 

.cseg

.org 300

 

.org 0

rjmp RESET

 

.org ovf0addr

rjmp Timer0

 

 

Timer0:

 

ldi r16, 0x94 ; 148

out TCNT0, r16

 

nop

nop

nop

 

reti

 

RESET:

cli

 

;Настройка таймера 0

ldi r16, 0x01

out TCCR0, r16

 

ldi r16, 0x94

out TCNT0, r16

 

ldi r16,0x01

out TIMSK, r16

 

sei

 

MAIN:

nop

nop

nop

nop

rjmp main

Поделиться сообщением


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

Что значит переполнение стека?

при вызове прерывания/подпрограммы адрес возврата сохраняеться в стеке, по ret(i) возвращается в РС. Если указатель стека указывает куда-то не туда адрес возврата слетает. Обычно в 0.

Поделиться сообщением


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

 

Ну понятный хрен, стек не проинициализирован.

.org 300 можете удалять, она просто игнорируется

то такое ovf0adr так и не известно

 

Для 128меги команда rjmp не существует.

 

вот, возьмите это код вместо вашего добра:

 

;*************************************************
.include "m128def.inc"
;*************************************************

    .def    zero    =    r15
    .def    tmp    =     r16
        

;*************************************************
.cseg    
;*************************************************
.org $0000 
    jmp RESET; Reset Handler

.org $0002
    reti  
;    jmp EXT_INT0; IRQ0 Handler

.org $0004
    reti  
;    jmp EXT_INT1; IRQ1 Handler

.org $0006
    reti  
;    jmp psDataFail; IRQ2 Handler

.org $0008 
    reti
;    jmp kbClockFall; IRQ3 Handler

.org $000A
    reti  
;    jmp EXT_INT4; IRQ4 Handler

.org $000C
    reti  
;    jmp EXT_INT5; IRQ5 Handler

.org $000E 
    reti 
;    jmp EXT_INT6; IRQ6 Handler

.org $0010
    reti  
;    jmp EXT_INT7; IRQ7 Handler

.org $0012
    reti  
;    jmp TIM2_COMP; Timer2 Compare Handler

.org $0014
    reti  
;    jmp TIM2_OVF; Timer2 Overflow Handler

.org $0016 
    reti 
;    jmp TIM1_CAPT; Timer1 Capture Handler

.org $0018
    reti  
;    jmp TIM1_COMPA; Timer1 CompareA Handler

.org $001A
    reti  
;    jmp TIM1_COMPB; Timer1 CompareB Handler

.org $001C 
    reti 
;    jmp TIM1_OVF; Timer1 Overflow Handler

.org $001E
;    reti  
    jmp TIM0_COMP; Timer0 Compare Handler

.org $0020
    reti  
;    rjmp TIM0_OVF; Timer0 Overflow Handler

.org $0022
    reti  
;    jmp SPI_STC; SPI Transfer Complete Handler

.org $0024
    reti  
;    jmp USART0_RXC; USART0 RX Complete Handler

.org $0026
    reti  
;    jmp USART0_DRE; USART0,UDR Empty Handler

.org $0028 
    reti 
;    jmp USART0_TXC; USART0 TX Complete Handler

.org $002A 
    reti
;jmp ADC; ADC Conversion Complete Handler

.org $002C
    reti 
;    jmp EE_RDY; EEPROM Ready Handler

.org $002E
    reti 
;    jmp ANA_COMP; Analog Comparator Handler

.org $0030
    reti 
;    jmp TIM1_COMPC; Timer1 CompareC Handler

.org $0032 
    reti 
;    jmp TIM3_CAPT; Timer3 Capture Handler

.org $0034 
    reti 
;    jmp TIM3_COMPA; Timer3 CompareA Handler

.org $0036
    reti  
;    jmp TIM3_COMPB; Timer3 CompareB Handler

.org $0038
    reti  
;    jmp TIM3_COMPC; Timer3 CompareC Handler

.org $003A 
    reti 
;    jmp TIM3_OVF; Timer3 Overflow Handler

.org $003C
    reti  
;    jmp USART1_RXC; USART1 RX Complete Handler

.org $003E
    reti  
;    jmp USART1_DRE; USART1,UDR Empty Handler

.org $0040
    reti 
;jmp USART1_TXC; USART1 TX Complete Handler

.org $0042
    reti
;jmp TWI; Two-wire Serial Interface Interrupt Handler

.org $0044 
    reti
;jmp SPM_RDY; SPM Ready Handler




TIM0_COMP:
    ldi        tmp,    0xFB
    out        udr0,    tmp    
reti



RESET:

    ldi     tmp,    high(RAMEND); Main program start
    out     SPH,    tmp; Set stack pointer to top of RAM
    ldi     tmp,    low(RAMEND)
    out     SPL,    tmp

    clr        zero

    
    ldi        tmp,    (1<<WGM01)|(0b111<<CS00)    
    out        TCCR0,    tmp

    ldi        tmp,    144
    out        OCR0,    tmp

    ldi        tmp,    (1<<OCIE0)
    out        TIMSK,    tmp


    sei

    
begin:

rjmp begin

Поделиться сообщением


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

Dopler... Будьте добры... Пожалуйста прокоментируйте хоть в кратце этот код........

Поделиться сообщением


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

Мой код, это тоже самое, что и у вас.

 

1. Подключаем файл mega128

2. Даем регистрам имена, под которым они будут использоваться в программе ( с помошью .equ )

3. Директива .org говорит по какому адресу размещать код .org 0 - размещать с нуля

3. Дальше идем в даташит на страницу 61, раздел Interrupts и видим все вектора прерываний и инициализацию стека, как это рекомендует Atmel (видим код). Т.е. видим список всех прерываний меги128.

4. У меги 128 нет команды rjmp, так как она не перекрывает все адресное пространство. Используется команда jmp.

5. В прерываниях, которые нам нужны, раскоментирован jmp, которые не нужны - reti (если вдруг в программе по недосмотру нежелательное прерывание произойдет, то ничего страшного не случится, так как будет сразу reti ). Необходимо помнить, что команда jmp занимает в памяти программ два слова (4 байта), поэтому .org наращивается на 4.

6. После сброса программа прыгает на 0, там видит jmp и переходит на RESET. Программа начинается с инициализации стека. Т.е. в регистр стека SPH:SPL записывается последняя ячейка ОЗУ меги, так как стек у AVR растет сверху вниз.

7. Дальше инициализируется таймер на прерывание по сравнению, вы можете поменять это место на свою инициализацию таймера (лучше не меняйте, а разберитесь с мнемоникой <<).

8. Разрешаются прерывания.

9. Главный бесконечный цикл.

10. При срабатывании прерывания, программа прыгает на вектор 001E, видит там jmp и переходит на обработчик.

11. В обработчике может написать любой тестовый код вместо моего (мой выводит байт в UART, смысла для вас не имеет), например inc tmp.

Поделиться сообщением


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

Спасибо... ведь не обязательно в программе писать все адреса прерываний если они не испорльзуються? И еще :<< Это просто в РОН устанавливается единица по номеру бита в определенном байте так....

Поделиться сообщением


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

ведь не обязательно в программе писать все адреса прерываний если они не испорльзуються?

В принципе нет. И умные С компиляторы зачастую это обходят. Но ради десятка байт заниматься половыми извращениями ИМХО не стоит.

Тем более всегда стоит иметь ввиду будущие модернизации кода, поэтому значительно лучше оставлять заглушки.

Поделиться сообщением


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

Мой код, это тоже самое, что и у вас.

...

4. У меги 128 нет команды rjmp, так как она не перекрывает все адресное пространство. Используется команда jmp.

Правильнее наверно так - векторы прерывания рассчитаны на команду JMP. RJMP у меги тоже есть, и ее можно применять и в этом случае, если определять векторы через их имена - .org OVF0addr

ldi tmp, (1<<WGM01)|(0b111<<CS00)

Честно говоря загадочная конструкция. Точнее вот эта часть - (0b111<<CS00)

Не подскажите, что она значит? Понятно, что работать будет, но <<CS00 зачем???

Поделиться сообщением


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

И последнее... почему все таки у меня не получается записывать в щетный регистр TCNT0 командой out? Может нужно использовать sts? Но разве этот регистр находится не в регистровом пространстве?

Поделиться сообщением


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

Не подскажите, что она значит? Понятно, что работать будет, но <<CS00 зачем???

Чтобы не думать о совместимости. Сдвинули на позицию N и неважно 5 -й это бит или 0-й.

почему все таки у меня не получается записывать в щетный регистр TCNT0 командой out?

А как это выглядит? Обращение выше пространства IO ассемблер не пропустит - выдаст ошибку.

Поделиться сообщением


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

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

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

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

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

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

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

×
×
  • Создать...