Без понятия, что у него описано. Да, ловим факт срабатывания, а в прерывании щупаем вторую ногу. Если там 1 - значит крутили тудым, если 0 - сюдым. Не затратно по ресурсам, не загружает контроллер постоянным опросом, и работает очень четко. Главное флаг прерывания сбрасывать, дабы от дребезга защититься, и конденсаторы на ноги повесить, чтобы совсем хорошо было.
_________________ "Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Угу, задержка антидребезга. Это уж как Вам комфортнее. Без конденсаторов 0,1 на каналах нужна обязательно.
_________________ "Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
А штука, тем временем, очень недурственная. Хоть и диктует условия по разводке плат...
_________________ "Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Ну если только один модуль RGB && таймеры больше не нужны, то это лучший вариант. Ну а если каналов ШИМ требуется 10-20-30..., то тут уже программный BAM (не Вам, а Bit Angle Modulation) в помосчь.
_________________ "Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Да. Именно несколько каналов требуются. Вот сейчас пытаю ВАМ с 12 RGB ледами с ОК. Катоды попарно(0+6, 1+7...) сунуты на один из портов и переключаются динамически, в момент 0х80 в регистре сравнения. Аноды по 6 штук соединены по цветам и тоже на порт. ВАМ на высоких частотах нивелирует яркости и цвета, соответственно. Приходится делить клок таймера: цвета-то "красивеют", но линейка мерцает, подобно обычному программному шиму. А если использовать ВАМовскую плюшку одновременного включения(катодов, в моем случае) по маске, то придется добавлять буферные каскады, т.к. тинька ток уже не потянет, чего не хотелось бы.
Туплю дальше... Настроил все таймеры, т.е. один Т0 полностью и половину Т1 на аппаратный ШИМ. Все работает прекрасно. Режим ФастШИМ 8 бит. И даже энкодер работает, только с дребезгом. Решил запрещать прерывания, а разрешать, только когда таймер дотикает до нужного значения. И уперся в конфигурацию таймера Т1В... Как? если он уже на ШИМ настроен??? Т.е биты в WGM во всех регистрах выставлены. А мне надо СТС или какой другой режим... Простите. Буду рад, если ткнете носом.
З.Ы. И зачем там сброс флага прерывания? Если их можно запретить? Или я как-то не так делаю?
ldi temp, (0<<INT1)|(0<<INT0) ; прерывание выключить out GIMSK, temp
sbis PIND, 3 rjmp rty
subi VOLUME, -10 out OCR0A, VOLUME out OCR0B, VOLUME out OCR1AL, VOLUME
rjmp ghj
rty: subi VOLUME, 10 out OCR0A, VOLUME out OCR0B, VOLUME out OCR1AL, VOLUME
ghj:
reti
; ************************************************************************************************** ; ИНИЦИАЛИЗАЦИЯ МК (логическое начало основной программы) ****************************************** ; **************************************************************************************************
; --------- конфигурация портов ----------
Reset: ldi temp, 0b00001100 ; Конфигурируем порт B (направление порта) out DDRB, temp ldi temp, 0b00000011 ; Конфигурируем порт A (направление порта) out DDRA, temp ldi temp, 0b00100000 ; Конфигурируем порт D (направление порта) out DDRD, temp
ldi temp, 0b00000000 ; Конфигурируем порт В (выводы порта) out PORTB, temp ldi temp, 0b00000000 ; Конфигурируем порт A (выводы порта) out PORTA, temp ldi temp, 0b00000000 ; Конфигурируем порт D (выводы порта) out PORTD, temp
ldi temp, (0<<INT1)|(1<<INT0) ; прерывание out GIMSK, temp
ldi temp, (1<<ISC01)|(1<<ISC00) ; по восходящему фронту out MCUCR, temp
ldi temp, 0xFF ; Сбросить флаги внешних прерываний out EIFR, temp
ldi temp, RAMEND ; Загрузка указателя стека out SPL, temp
; lditemp, 10 ; outEEAR, temp ; загружаем адрес нужной ячейки ; sbiEECR, EERE ; Выставляем бит чтения ; inZUUM, EEDR ; Забираем из регистра данных результат ; ; ---------- разрешение прерываний ---------- lditemp, 255 ldiR20, 0
sei ; Разрешаем прерывания
; ******************************************************************************************************************* ; ОСНОВНАЯ ПРОГРАММА (основной цикл) ******************************************************************************** ; *******************************************************************************************************************
Start: // cpiR20, 1 /* brneTTT ; перейти если равно или больше
; EEWrite: ; sbicEECR, EEPE ; Ждем готовности памяти к записи. Крутимся в цикле ; rjmpEEWrite ; до тех пор пока не очистится флаг EEWE ; ; cli ; Затем запрещаем прерывания. ; ; lditemp, 10 ; outEEAR, temp ; Загружаем адрес нужной ячейки ; ; outEEDR,ZUUM ; и сами данные, которые нам нужно загрузить ; ; sbiEECR,EEMPE ; взводим предохранитель ; sbiEECR,EEPE ; записываем байт (не более 4х таков ожидание) ; ; sei ; разрешаем прерывания ; ; ldiRAZ4, 10 ; Возвращаем 4 разряд перед выходом ; ldiFLAG, 0b00000000 ; ldierror, 0 ; ; ret
DELAY: ; Веся задержка будет равна примерно 50 мкс
pushtemp ; Положим перменную в стек, может она еще где-то используется intemp, SREG ; Закидываем в стек СРЕГ pushtemp
poptemp ; Вытаскиваем из стека СРЕГ outSREG, temp ; Возвращаем занчение обратно из стека poptemp ; Вытаскиваем переменную из стека
ret
З.З.Ы. Простите. кое-чего добился используя тупые задержки. И даже работает. Еще другой вопрос теперь всплывает... Яркость светодиодов регулируется не линейно... Т.е. сначала она растет, а потом после некоторого придела почти не меняется, а крутить до самого максимального значения можно долго. Также убавляешь, а она не меняется, а потом начинает падать... Как сделать, чтобы этого избежать тоже?
З.З.З.Ы. И еще энкодер какой-то интересный выдрал откуда-то... У него все изменения ловит за два щелчка при повороте.
Аппаратный ШИМ, в большинстве случаев, в прерываниях не нуждается. Он для того и придуман, чтобы разгрузить ядро. Разработчики позаботились о том, чтобы не возникало никаких коллизий. Для этого ввели специальный буфер.
Запись регистров 16 разрядной периферии должна быть строго определенная - старшая часть - младшая часть. Чтение наоборот. Спойлер
Код:
.include "tn2313def.inc"
; ============ ; ТИП МИКРОКОНТРОЛЛЕРА (.device) ; ============
.device ATtiny2313
; ================= ; ОБЪЯВЛЕНИЯ И КОНСТАНТЫ (.def, .equ) ; =================
.def temp = R16 .def VOLUME = R17 ; Переменная ошибки ; .def DATA = R18 ; Данные между датчиком температуры и МК ; .def temp1 = R19
; .equ DQDDR = DDRB ; Указать регистр напраавления порта, к которому подключен вывод DQ ; .equ DQPIN = PINB ; Указать регистр чтения порта, к которому подключен вывод DQ ; .equ DQ =7 ; Указать номер бита порта, к которому подключен DQ
SUB VOLUME,R16 out OCR0A, VOLUME out OCR0B, VOLUME OUT OCR1AH,ZH ; !!!!!!!!!!!!!!!! out OCR1AL,VOLUME
reti
; ************************************************************************************************** ; ИНИЦИАЛИЗАЦИЯ МК (логическое начало основной программы) ****************************************** ; **************************************************************************************************
; --------- конфигурация портов ----------
Reset: CLR ZH
ldi temp, 0b00001100 ; Конфигурируем порт B (направление порта) out DDRB, temp
ldi temp, 0b00000011 ; Конфигурируем порт A (направление порта) out DDRA, temp ldi temp, 0b00100000 ; Конфигурируем порт D (направление порта) out DDRD, temp
; ldi temp, 0b00000000 ; Конфигурируем порт В (выводы порта) out PORTB,ZH ldi temp, 0b00000000 ; Конфигурируем порт A (выводы порта) out PORTA,ZH ldi temp, 0b00000000 ; Конфигурируем порт D (выводы порта) out PORTD,ZH
ldi temp, (0<<INT1)|(1<<INT0) ; прерывание out GIMSK,temp out EIFR, temp
ldi temp, (1<<ISC01)|(1<<ISC00) ; по восходящему фронту out MCUCR, temp
; ldi temp, 0xFF ; Сбросить флаги внешних прерываний ; out EIFR, temp
ldi temp, RAMEND ; Загрузка указателя стека out SPL, temp
; Закидываем в счетчик изначальное значение out TCNT0,ZH out TCNT1H,ZH out TCNT1L,ZH
ldi temp, (1<<COM1A1)|(0<<COM1A0)|(0<<COM1B1)|(0<<COM1B0)|(0<<WGM11)|(1<<WGM10) out TCCR1A, temp
ldi temp, (1<<COM0A1)|(0<<COM0A0)|(1<<COM0B1)|(0<<COM0B0)|(1<<WGM01)|(1<<WGM00) out TCCR0A, temp
ldi temp, (0<<ICNC1)|(0<<ICES1)|(0<<WGM13)|(1<<WGM12)|(0<<CS12)|(0<<CS11)|(1<<CS10) out TCCR1B, temp
ldi temp, (0<<WGM02)|(0<<CS02)|(0<<CS01)|(1<<CS00) out TCCR0B, temp
; ldi temp, (1<<OCIE1A)|(0<<OCIE1B)|(1<<OCIE0B)|(1<<OCIE0A) ; три вывода на аппаратный ШИМ ; out TIMSK, temp ; OUT TIFR,TEMP
; ldi temp, 10 ; out EEAR, temp ; загружаем адрес нужной ячейки ; sbi EECR, EERE ; Выставляем бит чтения ; in ZUUM, EEDR ; Забираем из регистра данных результат ; ; ---------- разрешение прерываний ---------- ldi temp, 255 ldi R20, 0
sei ; Разрешаем прерывания
; ******************************************************************************************************************* ; ОСНОВНАЯ ПРОГРАММА (основной цикл) ******************************************************************************** ; *******************************************************************************************************************
Start: // cpi R20, 1 /* brne TTT ; перейти если равно или больше
; EEWrite: ; sbic EECR, EEPE ; Ждем готовности памяти к записи. Крутимся в цикле ; rjmp EEWrite ; до тех пор пока не очистится флаг EEWE ; ; cli ; Затем запрещаем прерывания. ; ; ldi temp, 10 ; out EEAR, temp ; Загружаем адрес нужной ячейки ; ; out EEDR,ZUUM ; и сами данные, которые нам нужно загрузить ; ; sbi EECR,EEMPE ; взводим предохранитель ; sbi EECR,EEPE ; записываем байт (не более 4х таков ожидание) ; ; sei ; разрешаем прерывания ; ; ldi RAZ4, 10 ; Возвращаем 4 разряд перед выходом ; ldi FLAG, 0b00000000 ; ldi error, 0 ; ; ret
DELAY: ; Вся задержка будет равна примерно 50 мкс in R0, SREG ; Закидываем в R0
Абалдеть! Сейчас попробую все это устранить. Мне еще осознать надо...
З.Ы. Изначально думал, раз таймер (ШИМ) 8 битный, то зачем старший загружать? потому и проигнорил его. (а про последовательность записи/чтения много где видел, спасибо).
З.З.Ы. И еще, обязательно адреса писать, где прерывания? Мне всегда думалось, что МК сам их по порядочку раскидывает.... А все. Дошло. Вы просто вырезали всю таблицу прерываний...
_________________ Станислав
Последний раз редактировалось СКАЗОЧНИК Сб фев 06, 2016 07:07:55, всего редактировалось 2 раз(а).
)) Так я другие и не использую... И еще небольшой вопросик. Там в инициализации прописано прерывание включить по ИНТ0 и флаги сбросить. У меня по файлу Register summary из даташита в регистре флагов другие названия у этих прерываний... INTF1 и INTF0.
И другой еще вопросик. Будет ли работать эта конструкция (проверю, конечно, еще до конца не все рассмотрел)
Код:
INT_0:
LDI R16,-10 sbis PIND,3 LDI R16,10
А то по прерыванию сразу скидываем -10, потом смотрим куда крутим, а там получится, что прибавляем. По следующему опять скинем, потом прибавим. И так будем висеть в одном месте? Или я не правильно понимаю? Простите за дотошность...
А вот эта конструкция, просто в восторг меня привела!!!! Круто! Блин, как же мне еще далеко до совершенства.
Код:
SBI ACSR,ACD
Такс... ладно. Все попробовал. все работает. Пара вопросов:
Как работает вышеуказанная конструкция в прерывании? И как работают выводы ШИМ без этого:
Код:
; ldi temp, (1<<OCIE1A)|(0<<OCIE1B)|(1<<OCIE0B)|(1<<OCIE0A) ; три вывода на аппаратный ШИМ ; out TIMSK, temp
? Что-то я где-то упускаю... И куда девался дребезг?
Не получается сделать, чтобы за приделы диапазона не вылазило.. Крутишь энкодер, а он убавляет до минимума и снова в максимум уходит...
Код:
INT_0:
LDI R16, 10 sbis PIND, 3 LDI R16, -10
SUB VOLUME, R16
cpi VOLUME, 0 breq MIN cpi VOLUME, 250 breq MAX
rjmp G
MIN: LDI VOLUME, 0 rjmp G MAX: ldi VOLUME, 250
G: out OCR0A, VOLUME out OCR0B, VOLUME OUT OCR1AH, ZH out OCR1AL, VOLUME
reti
Все. понял где ошибка.
Код:
MIN: LDI VOLUME, 10 rjmp G MAX: ldi VOLUME, 240
Не оставил возможности для дальнейших шагов... Хорошо. Встал вопрос в другом. Яркость не линейная. (((((( Если делать по 10, то быстро все, но до конца не убавляет. А если делать по 2, то долго крутить приходится.
Елки, как у вас получается все время компактнее, чем у меня написать?! Моя конструкция тоже работает теперь.
Я тут сижу вообще думаю, что надо сравнивать до какого-то числа, а потом менять коэффициент прибавления/убавления. Чтобы в конце (уменьшения) диапазона яркость плавненько менялась, а в максимальных значениях более резко, т.к. там совсем не заметно изменений.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 13
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения