|
|
  |
Помогите новичку с таймером на Меге16, в чем моя ошибка? |
|
|
|
Dec 1 2007, 18:52
|
Участник

Группа: Участник
Сообщений: 30
Регистрация: 22-08-07
Пользователь №: 29 972

|
Я - любитель и только начал разбираться с Мегой16. Глядя в книжки и даташит написал учебную программу, сигнализирующую переполнение таймера 1 в нормальном режиме хотя бы один раз. Ниже прилагаю код. Увы, эффекта нет((( Ломаю голову уже 16 часов, сил больше нет... Прошу помощи! В чем ошибка???
; АТМега16 ; Учебная программа работы с таймером 1 в нормальном режиме ; Первое прерывание по любому событию таймера 1 зажигает светодиод
.include "m16def.inc" ; Присоединение файла описаний .list ; Включение листинга
.def temp = r16 ; Определение главного рабочего регистра
;------------------------- Вектора прерывания rjmp RESET reti ;rjmp Прерывание 1 reti ;rjmp Прерывание 2 reti ;rjmp Прерывание 3 reti ;rjmp Прерывание 4 rjmp TIM1 ;Прерывание 5 Захват таймера-счетчика 1 rjmp TIM1 ;Прерывание 6 Совпадение А таймера-счетчика 1 rjmp TIM1 ;Прерывание 7 Совпадение В таймера-счетчика 1 rjmp TIM1 ;Прерывание 8 Переполнение таймера-счетчика 1 reti ;rjmp Прерывание 9 reti ;rjmp Прерывание 10 reti ;rjmp Прерывание 11 reti ;rjmp Прерывание 12 reti ;rjmp Прерывание 13 reti ;rjmp Прерывание 14 reti ;rjmp Прерывание 15 reti ;rjmp Прерывание 16 reti ;rjmp Прерывание 17 reti ;rjmp Прерывание 18 reti ;rjmp Прерывание 19 reti ;rjmp Прерывание 20
RESET: cli ; общий запрет прерываний
ldi temp, 0x80 ;Выключение компаратора out ACSR, temp
;-------------------------- Инициализация стека ldi temp, 0x7F ; Выбор адреса вершины стека out SPL, temp ; Запись его в регистр стека
;-------------------------- Инициализация портов ВВ ldi temp, 0xFF ; Запись числа $FF в регистр temp out DDRB, temp ; Запись этого числа в DDRB (порт PB на вывод) out PORTB, temp ; Запись то же числа в PORTB (потушить светодиод) ;--------------------------- Инициализация таймера-счетчика 1 out TIMSK, temp ;Разрешение прерываний по любому событию таймеров
ldi temp,0b00000000 out TCCR1A, temp ;Нормальный режим Таймера 1
ldi temp,0b00000011 ;Нормальный режим Таймера 1, Предделитель 1/64 out TCCR1B, temp ;---------------------------
sei ; общее разрешение прерываний
;-------------------------- Основной пустой цикл main: nop rjmp main ; К началу цикла
;-------------------------- Прерывания по таймеру 1 ; Если хотя бы раз происходит прерывание, загорается светодиод TIM1: ldi temp, 0x00 ; Записываем число $00 в регистр temp out PORTB, temp ; Записываем число 0x00 в PORTB (включить светодиод) reti
|
|
|
|
|
Dec 2 2007, 01:14
|
Частый гость
 
Группа: Свой
Сообщений: 172
Регистрация: 5-08-06
Из: Владивосток
Пользователь №: 19 343

|
Проверял в симуляторе... Прога-то работает нормально... И прерывание происходит... Вот только одного не понял, почему вдруг у меги 16 TIM1_OVF уехал на адрес 8???? Выспитесь, потом откройте ман на сабж на стр. 45. И все будет путем  P.S. и пара маленьких замечаний: 1) никогда (тем более при отладке) не разрешайте ВСЕХ прерываний - программа улетит куда-нибудь, потом не найдете; 2) если таймер работает в режиме нормала, странно от него ожидать генерации прерываний по захвату и сравнению... Успехов.
|
|
|
|
|
Dec 2 2007, 03:38
|
Частый гость
 
Группа: Свой
Сообщений: 172
Регистрация: 5-08-06
Из: Владивосток
Пользователь №: 19 343

|
Так... Все чудесатее и чудлесатее... хекс: Код :020000020000FC :1000000014C018951895189518951FC01EC01DC0CE :100010001CC0189518951895189518951895189549 :1000200018951895189518951895F89400E808B93A :100030000FE70DBF0FEF07BB08BB09BF00E00FBD07 :1000400003E00EBD78940000FECF00E008BB1895D9 :00000001FF В самом деле, здесь вроде все в порядке... Дизасм в аврстудии Код 11: rjmp RESET +00000000: C014 RJMP PC+0x0015 Relative jump 12: reti;rjmp Ïðåðûâàíèå 1 +00000001: 9518 RETI Interrupt return 13: reti;rjmp Ïðåðûâàíèå 2 +00000002: 9518 RETI Interrupt return 14: reti;rjmp Ïðåðûâàíèå 3 +00000003: 9518 RETI Interrupt return 15: reti;rjmp Ïðåðûâàíèå 4 +00000004: 9518 RETI Interrupt return 16: rjmp TIM1;Ïðåðûâàíèå 5 Çàõâàò òàéìåðà-ñ÷åò÷èêà 1 +00000005: C01F RJMP PC+0x0020 Relative jump 17: rjmp TIM1;Ïðåðûâàíèå 6 Ñîâïàäåíèå À òàéìåðà-ñ÷åò÷èêà 1 +00000006: C01E RJMP PC+0x001F Relative jump 18: rjmp TIM1;Ïðåðûâàíèå 7 Ñîâïàäåíèå  òàéìåðà-ñ÷åò÷èêà 1 +00000007: C01D RJMP PC+0x001E Relative jump 19: rjmp TIM1; прер. 8 - переп. ТС1 +00000008: C01C RJMP PC+0x001D Relative jump 20: reti;rjmp Ïðåðûâàíèå 9 +00000009: 9518 RETI Interrupt return 21: reti;rjmp Ïðåðûâàíèå 10 +0000000A: 9518 RETI Interrupt return 22: reti;rjmp Ïðåðûâàíèå 11 +0000000B: 9518 RETI Interrupt return 23: reti;rjmp Ïðåðûâàíèå 12 +0000000C: 9518 RETI Interrupt return 24: reti;rjmp Ïðåðûâàíèå 13 +0000000D: 9518 RETI Interrupt return 25: reti;rjmp Ïðåðûâàíèå 14 +0000000E: 9518 RETI Interrupt return 26: reti;rjmp Ïðåðûâàíèå 15 +0000000F: 9518 RETI Interrupt return 27: reti;rjmp Ïðåðûâàíèå 16 +00000010: 9518 RETI Interrupt return//здесь оказываемся по прерыванию 28: reti;rjmp Ïðåðûâàíèå 17 +00000011: 9518 RETI Interrupt return 29: reti;rjmp Ïðåðûâàíèå 18 +00000012: 9518 RETI Interrupt return 30: reti;rjmp Ïðåðûâàíèå 19 +00000013: 9518 RETI Interrupt return 31: reti;rjmp Ïðåðûâàíèå 20 +00000014: 9518 RETI Interrupt return Странно... Какие мысли? Кто не прав? Может, студия? Платформу назначил правильно, мега 16, версия студии 4.12.460.
|
|
|
|
|
Dec 2 2007, 07:54
|
Участник

Группа: Участник
Сообщений: 30
Регистрация: 22-08-07
Пользователь №: 29 972

|
Здравствуйте! Спасибо всем за участие!!! Я выспался Таблицу прерываний я использовал из книги Евстифеева, а там ресет нулевой, а прерывания начинаются с единицы. "1) никогда (тем более при отладке) не разрешайте ВСЕХ прерываний - программа улетит куда-нибудь, потом не найдете; 2) если таймер работает в режиме нормала, странно от него ожидать генерации прерываний по захвату и сравнению..." Как я понимаю, у меня прерывния разрешены только от таймеров. Разве остальные не замкнуты на возврат? Все события от таймера 1 я указал от отчаяния  , чтобы не прозевать чего от таймера Кстати, попутно практический вопрос - если надо использовать только одно прерывание обязательно ли воспроизводить всю таблицу, замыкая ненужные на reti? В SPH у Меги16 записать FF? "Вообще хорошо бы у автора спросить - он без всяких прерываний светодиод то зажег?" Да, зажег. При переносе кода из прерывания: ldi temp, 0x00 ; Записываем число $00 в регистр temp out PORTB, temp ; Записываем число 0x00 в PORTB (включить светодиод) перед основным циклом светодиод зажигается сразу после запуска. Мега стоит на макетке вместе с самодельным аналогом STK200. К сожалению, я пока не умею работать симуляторами, код делаю в AVR-студии... Там же и эмулировать можно?
Сообщение отредактировал DimaSPB - Dec 2 2007, 07:56
|
|
|
|
|
Dec 2 2007, 09:47
|
Участник

Группа: Участник
Сообщений: 30
Регистрация: 22-08-07
Пользователь №: 29 972

|
Оставил в таблице только прерывание OVF таймера 1 В указатель стека загружать стал два байта Увы, не помогло Есть в нете толковое русское описание AVR-студии?
|
|
|
|
|
Dec 2 2007, 22:47
|
Частый гость
 
Группа: Свой
Сообщений: 172
Регистрация: 5-08-06
Из: Владивосток
Пользователь №: 19 343

|
По поводу проблемы с неправильным позиционированием прерывания: У мег область флэша имеет длину 16 бит, аврстудия в дизассемблере показывает адреса в словах. Т.е. адрес 0x10 - это не 16 байт, а 16 слов, что я и видел. Поэтому работоспособен такой код: Код .org 0 rjmp RESET; starting .org 0x10 rjmp TIM1_OVF; go to interrupt service routine for timer 1 overflow Что касается почему стартовый код (то есть таблица прерываний) уважаемого DimaSPB не работает. Инструкция rjmp имеет длину 16 бит и укладывается в одно слово памяти программ. Чтобы такая таблица работала, после каждого ржампа надо поставить ноп, дабы занять еще одно слово. На каждый вектоп прерывания (и на ресет тоже) отводится не по 2 байта, а по два слова, чтобы туда помещался не только короткий переход (rjmp), но и длинный (jmp), занимающий 2 слова (4 байта). Смотрите AVR Instruction Set, описание вышеназванных команд. Также в даташите по меге 16 на стр. 46 есть такие вот строчки: Цитата The most typical and general program setup for Reset and Interrupt Vector Addresses in ATmega16 is: address label code comments $000 jmp RESET ; Reset Handler $002 jmp EXT_INT0 ; IRQ0 Handler $004 jmp EXT_INT1 ; IRQ1 Handler $006 jmp TIM2_COMP ; IRQ0 Handler ... Т.е. атмелы в своем типичном примере используют 4-хбайтовую команду для прыжка. Можно сделать так же. Тогда точно работать будет. Или так: Код rjmp RESET; смещение 0 слов nop; заполняем промежуток - смещение 1 слово rjmp EXT_INT0; смещение 2 слова nop; заполняем промежуток - смещение 3 слово 2 DimaSPB: под разрешением всех прерываний я имел ввиду запись FF в TIMSK при настройке. Это вредно - ведь Вы разрешаете не только то прерывание, которое хотите использовать, но и неиспользуемые. Зачем? Просто Код ldi temp, 4 out TIMSK, temp [quote]Есть в нете толковое русское описание AVR-студии?[/qoute]Лучше подучите английский. Всяко полезней будет. А описание я не встречал, кроме встроенной справки (правда, там все по-английски  )
|
|
|
|
|
Dec 4 2007, 18:05
|
Участник

Группа: Участник
Сообщений: 30
Регистрация: 22-08-07
Пользователь №: 29 972

|
Два дня не было нета Leen, Огромное спасибо за совет! Все заработало!
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|