реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Вопрос по AVRstudio, Это баг или я чего-то незнаю?
Potter
сообщение Feb 21 2007, 21:08
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 27-05-06
Из: Харьков
Пользователь №: 17 508



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

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

.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?
Go to the top of the page
 
+Quote Post
beer_warrior
сообщение Feb 21 2007, 21:18
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380



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

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


--------------------
Вони шукають те, чого нема,
Щоб довести, що його не існує.
Go to the top of the page
 
+Quote Post
Potter
сообщение Feb 21 2007, 21:24
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 27-05-06
Из: Харьков
Пользователь №: 17 508



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


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

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

.cseg
.org 300

???
Go to the top of the page
 
+Quote Post
Potter
сообщение Feb 21 2007, 21:44
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 27-05-06
Из: Харьков
Пользователь №: 17 508



Блин... Ну подскажите... Я в тупике....
Go to the top of the page
 
+Quote Post
Dopler
сообщение Feb 21 2007, 21:45
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 437
Регистрация: 23-04-05
Из: Таганрог
Пользователь №: 4 425



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


Во первых - при переходе на вектор прерывания запрещать/разрешать оные не надо. На досуге посмотрите разницу между командами 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.
Go to the top of the page
 
+Quote Post
Potter
сообщение Feb 21 2007, 21:54
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 27-05-06
Из: Харьков
Пользователь №: 17 508



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

.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
Go to the top of the page
 
+Quote Post
beer_warrior
сообщение Feb 21 2007, 21:58
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380



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

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


--------------------
Вони шукають те, чого нема,
Щоб довести, що його не існує.
Go to the top of the page
 
+Quote Post
Dopler
сообщение Feb 21 2007, 22:04
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 437
Регистрация: 23-04-05
Из: Таганрог
Пользователь №: 4 425



Цитата(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
Go to the top of the page
 
+Quote Post
Potter
сообщение Feb 21 2007, 22:23
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 27-05-06
Из: Харьков
Пользователь №: 17 508



Dopler... Будьте добры... Пожалуйста прокоментируйте хоть в кратце этот код........
Go to the top of the page
 
+Quote Post
Dopler
сообщение Feb 21 2007, 22:42
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 437
Регистрация: 23-04-05
Из: Таганрог
Пользователь №: 4 425



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

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.
Go to the top of the page
 
+Quote Post
Potter
сообщение Feb 21 2007, 23:58
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 27-05-06
Из: Харьков
Пользователь №: 17 508



Спасибо... ведь не обязательно в программе писать все адреса прерываний если они не испорльзуються? И еще :<< Это просто в РОН устанавливается единица по номеру бита в определенном байте так....
Go to the top of the page
 
+Quote Post
beer_warrior
сообщение Feb 22 2007, 00:04
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380



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

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


--------------------
Вони шукають те, чого нема,
Щоб довести, що його не існує.
Go to the top of the page
 
+Quote Post
Qwertty
сообщение Feb 22 2007, 00:25
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



Цитата(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 зачем???
Go to the top of the page
 
+Quote Post
Potter
сообщение Feb 22 2007, 00:47
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 27-05-06
Из: Харьков
Пользователь №: 17 508



И последнее... почему все таки у меня не получается записывать в щетный регистр TCNT0 командой out? Может нужно использовать sts? Но разве этот регистр находится не в регистровом пространстве?
Go to the top of the page
 
+Quote Post
beer_warrior
сообщение Feb 22 2007, 00:55
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380



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

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

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


--------------------
Вони шукають те, чого нема,
Щоб довести, що його не існує.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th June 2025 - 21:54
Рейтинг@Mail.ru


Страница сгенерированна за 0.01515 секунд с 7
ELECTRONIX ©2004-2016