Есть вопрос по таймеру1 в AVR. Таймер1 в режиме FastPWM, с выводов OC1A и OC1B выходят шим сигналы, с помощью OCR1A и OCR1B задаю скважность шим. Но требуется, чтобы сигналы выходили попеременно- то с OC1A, когда напряжение на нем кончится-с OC1B. Как можно такое сделать?
Нулевой бит COM0x1 задает полярность сигнала. На одном канале выставить импульсы положительной полярности, на другом отрицательной. При одинаковых значениях сравнения на обоих выводах сигнал будет идти в противофазе.
Нет,так сигналы в одно и то же время будут выходить,а нужно смещение по времени- сначала на первом выходе сигнал, сигнал кончился- появляется на втором.
Ни кто не в курсах, нужно ли что-то ещё, чтобы заставить ATmega162 заходить в прогу обработки прерывания? (Таймер 0, режим CTC - прерывание, сброс при совпадении (в единственном канале)):
* таблица векторов внесена
* метка для ухода поставлена
* число для сравнения задано
* режим и источник такта таймеру выбраны
* бит маски выбран
* глобальное разрешено
И... нефига.
Спойлер.include "m162def.inc"
.equ del = 85 ;делитель для таймера (при прескалере /8)
.cseg
.org 0 ;РАСПРЕДЕЛЕНИЕ ВЕКТОРОВ ПРЕРЫВАНИЙ mega162, РАЗМЕЩАЕТСЯ ТОЛЬКО ЗДЕСЬ! rjmp reset ;0x000 RESET, он же скакать к инициализации устройств reti;0x002 внешнее прерывание INT0 reti;0x004 внешнее прерывание INT1 reti;итд006 внешнее прерывание INT2 reti;008 внешнее прерывание по смене на электроде PCINT0 reti;00A внешнее прерывание по смене на электроде PCINT1 reti;00C таймер 3 захват reti;00E таймер 3 совпадение в канале A reti;010 таймер 3 совпадение в канале B reti;012 таймер 3 переполнение reti;014 таймер 2 совпадение (в единственном канале) reti;016 таймер 2 переполнение reti;018 таймер 1 захват reti;01A таймер 1 совпадение в канале A reti;01C таймер 1 совпадение в канале B reti;01E таймер 1 переполнение rjmp preh ;020 таймер 0 совпадение (в единственном канале) reti;022 таймер 0 переполнение reti;024 SPI, STC передача завершена reti;026 USART0 Rx (приём) завершён reti;028 USART1 Rx (приём) завершён reti;02A USART0 регистр данных пуст reti;02C USART1 регистр данных пуст reti;02E USART0 Tx (передача) завершена reti;030 USART1 Tx (передача) завершена reti;032 EEPROM готов reti;034 аналоговый компаратор reti;036 програмная память готова (всего 28 прерываний) ;037 последняя промежность ;--------------------------- RAM НА МАКСИМАЛЬНЫЙ АДРЕС СТЕКА
reset: ldi r16,high(RAMEND) out sph,r16 ldi r16,low(RAMEND) out spl,r16 ;--------------------------- УСТАНОВКА ТАЙМЕРА0 (8bit) ldi r16,0b00000001 ;маска от совпадения out timsk,r16 ;etimsk нужен только для таймера 3, не приелся ;tifr,etifr флаговые рагистры всех таймеров, не приелся ;sfior, сброс прескалеров и ещё какое-то уг, не приелся
;tcnt0 счётный регистр не приелся, счёт с нуля ldi r16,del ;задать делитель в канал совпадения out ocr0,r16 ;отправить в канал совпадения ldi r16,0b00001010 ;режим CTC, прескалер /8 [шит102] out tccr0,r16 ;ТАЙМЕР ПОШЁЛ [шит100] ;МЕЖ ПРЕРЫВАНИЯМИ 680 ТАКТОВ ;========= ГЛОБАЛЬНОЕ РАЗРЕШЕНИЕ ПРЕРЫВАНИЙ sei;set I во флаговом регистре ;--------------------------- ОСНОВНАЯ ПРОГА sbi portB,0 ;начальный уровень на порту
loop: nop nop rjmp loop ;вертеться в цикле ожидая нового прерывания
;========= ПОДПРОГРАММА ОБРАБОТКИ ПРЕРЫВАНИЯ, ТАЙМЕР 0
;В НЁМ ПРОГРАМНО ЗАДЕРЖИВАТЬ И ДЁРГАТЬ portB 0
;НА ОБРАБОТКУ 634 ТАКТА
;программно ждать, опустить строб, держать, поднять и выйти из прерывания
preh: ldi r17,110 ;задержка 553 такта
zad1: dec r17 ;отминусовать 1-цу в r17 (*1такт) cpi r17,0 ;стали ли он от этого 0? (*1такт) breq vse1 ;да уже 0 на выход (*1т/2 при переходе) rjmp zad1 ;нет отминусовывать ещё (*2такта) ;553:5=110делитель
vse1: ;< < < < < < < < < < здесь сбросить portB cbi portB,0
ldi r17,16 ;держать строб 81 такт
zad2: dec r17 ;минуснуть (*1такт) cpi r17,0 ;уже 0? (*1такт) breq vse2 ;да, на выход (*1т / 2 при переходе) rjmp zad2 ;нет, к минусовке (*2такта) ;81:5=16делитель
vse2: sbi portB,0 ;вернуть portB ;> > > > > > > > > > здесь строб подняли reti;заброать адрес выхода из стека, выйти и вернуть I
reti ;01C таймер 1 совпадение в канале B
reti ;01E таймер 1 переполнение
.org 0x0020
rjmp preh ;020 таймер 0 совпадение (в единственном канале)
reti ;022 таймер 0 переполнение
Спс! Заработало. В связи с этим ещё 4 вопроса:
1) В mega8 ждёт такое же "УГ"?
2) Если хотим ещё прерываний - .org перед каждым?
3) "Промежности" между векторами - это вторые слова адресов?
4) Если хотим "прерывание в прерывании" достаточно сразу же возобновить I, и вторую обработку не выносить за пределы первой?
Эээ... как много.
В маленьких камнях на вектор отводится по одной команде чтобы всунуть туда rjmp
В больших камнях rjmp уже не достреливает до конца памяти, поэтому там вектор занимает 2 команды чтобы всунуть jmp.
Чтобы не промахнуться:
1) ставить .ORG перед кодом обработчика
2) понаписать соотв. заглушек (jmp/rjmp), напр.
akl писал(а):Почему не выносить. Пишите обычный обработчик, в который придёт программа при наступлении события.
А, ну понят., т. е. второе случится на любом адресе первого, туда же и вернётся, первое доделается и вернётся в прогу. Адреса выходов в стеке не нарушаются. Двойные прерывания и meg-и раньше не писал / не сталкивался. У кого не "ф карме" - "фсем ф карму".
А в чём фишка, если при билде в *.hex, ассемблер не видит всех регистров связанных с таймером 3? (mega162) К примеру: out etimsk,r16
"error: Operand 1 out of range: 0x7d" А адреса всему таймеру такие: na (0x7D). В режиме совместимости с mega161 он и не должен быть доступен, но юзаю в нормальном режиме - mega162.