Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопрос по AVRstudio
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Potter
Собственно вопрос вот в чем....

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

.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?
beer_warrior
Цитата
Почему после того как выполнилось все тело прерывания по команде "reti" щетчик переходит по нулевому адресу?

Смахивает на переполнение стека.
Potter
Цитата(beer_warrior @ Feb 21 2007, 22:18) *
Смахивает на переполнение стека.


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

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

.cseg
.org 300

???
Potter
Блин... Ну подскажите... Я в тупике....
Dopler
На самом деле даже в приведенном коде много что не правильно.


Во первых - при переходе на вектор прерывания запрещать/разрешать оные не надо. На досуге посмотрите разницу между командами 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.
Potter
Вот код всей прогаммы:

.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
beer_warrior
Цитата
Что значит переполнение стека?

при вызове прерывания/подпрограммы адрес возврата сохраняеться в стеке, по ret(i) возвращается в РС. Если указатель стека указывает куда-то не туда адрес возврата слетает. Обычно в 0.
Dopler
Цитата(Potter @ Feb 21 2007, 21:54) *


Ну понятный хрен, стек не проинициализирован.
.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
Potter
Dopler... Будьте добры... Пожалуйста прокоментируйте хоть в кратце этот код........
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.
Potter
Спасибо... ведь не обязательно в программе писать все адреса прерываний если они не испорльзуються? И еще :<< Это просто в РОН устанавливается единица по номеру бита в определенном байте так....
beer_warrior
Цитата
ведь не обязательно в программе писать все адреса прерываний если они не испорльзуються?

В принципе нет. И умные С компиляторы зачастую это обходят. Но ради десятка байт заниматься половыми извращениями ИМХО не стоит.
Тем более всегда стоит иметь ввиду будущие модернизации кода, поэтому значительно лучше оставлять заглушки.
Qwertty
Цитата(Dopler @ Feb 21 2007, 22:42) *
Мой код, это тоже самое, что и у вас.
...
4. У меги 128 нет команды rjmp, так как она не перекрывает все адресное пространство. Используется команда jmp.

Правильнее наверно так - векторы прерывания рассчитаны на команду JMP. RJMP у меги тоже есть, и ее можно применять и в этом случае, если определять векторы через их имена - .org OVF0addr
Цитата(Dopler @ Feb 21 2007, 22:42) *
ldi tmp, (1<<WGM01)|(0b111<<CS00)

Честно говоря загадочная конструкция. Точнее вот эта часть - (0b111<<CS00)
Не подскажите, что она значит? Понятно, что работать будет, но <<CS00 зачем???
Potter
И последнее... почему все таки у меня не получается записывать в щетный регистр TCNT0 командой out? Может нужно использовать sts? Но разве этот регистр находится не в регистровом пространстве?
beer_warrior
Цитата
Не подскажите, что она значит? Понятно, что работать будет, но <<CS00 зачем???

Чтобы не думать о совместимости. Сдвинули на позицию N и неважно 5 -й это бит или 0-й.
Цитата
почему все таки у меня не получается записывать в щетный регистр TCNT0 командой out?

А как это выглядит? Обращение выше пространства IO ассемблер не пропустит - выдаст ошибку.
SasaVitebsk
Цитата(Potter @ Feb 22 2007, 01:47) *
И последнее... почему все таки у меня не получается записывать в щетный регистр TCNT0 командой out? Может нужно использовать sts? Но разве этот регистр находится не в регистровом пространстве?


Должно выводить. И в AVR STUDIO вы должны это видеть следующим тактом.
Qwertty
Цитата(beer_warrior @ Feb 22 2007, 00:55) *
Цитата
Не подскажите, что она значит? Понятно, что работать будет, но <<CS00 зачем???

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

Бывают кристаллы у которых CS00!=0 ? А если думать о будущих, то необязательно CS02..CS00 будут распологаться последовательно, их могут раскидать как WGMxx - даже по регистрам.
Dopler
Цитата(Qwertty @ Feb 22 2007, 01:18) *
Цитата(beer_warrior @ Feb 22 2007, 00:55) *

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

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

Бывают кристаллы у которых CS00!=0 ? А если думать о будущих, то необязательно CS02..CS00 будут распологаться последовательно, их могут раскидать как WGMxx - даже по регистрам.


Я пишу так для сохранения общего стиля вывода битов, т.е. не для каких битов стараюсь имя не опускать. Объединяю несколько битов и одну запиь исключительня для сокращения длины. Вот для меги 48 (действительно, WGM22 выкинули в другой регистр) делаю так:

Код
    ldi        tmp,    (0b00<<COM2A0)|(0b10<<COM2B0)|(0b11<<WGM20)        sts        TCCR2A,    tmp
    
    ldi        tmp,    (0<<FOC2A)|(0<<FOC2B)|(0<<WGM22)|(0b001<<CS20)
    sts        TCCR2B,    tmp
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.