Страница 1 из 1

Бегущий огонек на ATtiny2313 с переключением эффектов :)

Добавлено: Сб янв 31, 2009 21:11:19
C0oo1D
У меня возникла проблема, когда пытался адаптировать урок "Переключение между массивами. Б.О. v2.2". Ниже представил код уже полученной и глюченной программы.. выделил для работы еще 2 регистра, хотя было бы достаточно одного.. Но для начала решил сделать с двумя, лишь бы работало.
Еще думаю что код очень не оптимизирован.. Так же хочется знать, нельзя-ли писать в массивах не 8 битами а 15? (что-бы обрабатывались сразу 2 порта).. массивы специально не переводил в десятиричную систему, для удобства. Код ниже, строго не судите - я пока-что новичок и в МК и в Ассемблере :)

Ошибка, как я понял, по метке "ReadArray"
Забыл написать! Цель этой адаптации - задействовать порт D :)

Код: Выделить всё

.include "D:\Other\AVR\avrasm\APPNOTES\tn2313def.inc"

.def     Temp=R16
.def     Temp1=R17
.def     Temp2=R18
.def     Temp3=R19
.def     Temp4=R20
.def     ResCnt=R20

.cseg
.org 0


rjmp Reset
rjmp INT_0
rjmp INT_1
rjmp Timer1_capt1
rjmp Timer1_comp1
rjmp Timer1_OVF1
rjmp Timer0_OVF0
rjmp UART_RX
rjmp UART_UDRE
rjmp UART_TX
rjmp ANA_COMP

;Reset:
INT_0:
INT_1:
Timer1_capt1:
;Timer1_comp1:
Timer1_OVF1:
Timer0_OVF0:
UART_RX:
UART_UDRE:
UART_TX:
ANA_COMP:
          reti
;****************************************************************************************
;* ИНИЦИАЛИЗАЦИЯ                                                                        *
;****************************************************************************************
Reset:    ldi Temp1,0             ;Анти-дребезг
          ldi Temp2,0             ;----------
l_res:    dec Temp1               ;----------
          brne l_res              ;----------
          dec Temp2               ;----------
          brne l_res              ;----------
         
          inc ResCnt              ;инкремент счетчика сбросов

          ldi Temp,0b11111111     ;настройка портов
          out DDRB,Temp           ;----------
          ldi Temp,0b1111111      ;----------
          out DDRD,Temp           ;----------

          ldi Temp,0b01000000     ;разрешить прерывание компаратора
          out TIMSK,Temp          ;----------

          ldi Temp,0b00000010     ;тактовый сигнал = CK/8
          out TCCR1B,Temp         ;----------

          ldi Temp,0x4C           ;инициализация компаратора
          out OCR1AH,Temp         ;----------
          ldi Temp,0x4B           ;----------
          out OCR1AL,Temp         ;----------

          ldi Temp,RamEnd         ;установка указателя стека
          out SPL,Temp            ;----------

          ldi Temp1,0             ;инициализация индикатора
          ldi Temp2,0             ;----------

          ldi Temp,0              ;обнуление таймера
          out TCNT1H,Temp         ;----------
          out TCNT1L,Temp         ;----------

          sei                     ;разрешить прерывания
;****************************************************************************************
;* ОСНОВНОЙ ЦИКЛ                                                                        *
;****************************************************************************************
Inf:   rjmp Inf                    ;бесконечный цикл


;****************************************************************************************
;* ОБРАБОТЧИК ПРЕРЫВАНИЯ КОМПАРАТОРА                                                    *
;****************************************************************************************
Timer1_comp1:
         ldi Temp,0               ;обнуление таймера
         out TCNT1H,Temp          ;----------
         out TCNT1L,Temp          ;----------


SelectArray:                      ;выбор массива

         andi ResCnt,0b00000011   ;отсечка лишних разрядов сч. сбросов

         cpi ResCnt,0             ;сравнение счетчика сбросов с конст.
         brne Tst1                ;если не равно - след. проверка
         ldi ZH,High(ArrayB0*2)   ;загрузка начального адреса массива
         ldi ZL,Low(ArrayB0*2)    ;----------
         ldi YH,High(ArrayD0*2)   ;----------
         ldi YL,Low(ArrayD0*2)    ;----------
         rjmp ReadArray

Tst1:    cpi ResCnt,1
         brne Tst2
         ldi ZH,High(ArrayB1*2)
         ldi ZL,Low(ArrayB1*2)
         ldi YH,High(ArrayD1*2)
         ldi YL,Low(ArrayD1*2)
         rjmp ReadArray

Tst2:    cpi ResCnt,2
         brne Tst3
         ldi ZH,High(ArrayB2*2)
         ldi ZL,Low(ArrayB2*2)
         ldi YH,High(ArrayD2*2)
         ldi YL,Low(ArrayD2*2)
         rjmp ReadArray

Tst3:    ldi ZH,High(ArrayB3*2)
         ldi ZL,Low(ArrayB3*2)
         ldi YH,High(ArrayD3*2)
         ldi YL,Low(ArrayD3*2)
         rjmp ReadArray


ReadArray:

         ldi Temp,0               ;прибавление относит. адреса
         ldi Temp3,0              ;----------
         add ZL,Temp1             ;----------
         adc ZH,Temp              ;----------
         add YL,Temp2             ;----------
         adc YH,Temp3             ;----------

         lpm R0,Z                     ;загрузка из ПЗУ
         ld R1,Y                 ;----------

         mov Temp,R0              ;копирование в РОН
         mov Temp3,R1             ;----------
         cpi Temp,0               ;пороверка на нулевой элемент
         breq Init                ;если да - инициализация
         inc Temp1                ;увеличение относит адреса на 1
         inc Temp2
         rjmp Output              ;перейти на вывод в порт
         
         

Init:    ldi Temp1,0              ;вернутся к выбору массива
         ldi Temp2,0              ;----------
         rjmp SelectArray         ;----------

Output:  out PortB,Temp           ;вывод в порт
         out PortD,Temp3          ;----------
         
         reti                     ;выход из обработчика



ArrayB0:
.db  0b10000000,0b01000000,0b00100000,0b00010000
.db  0b00001000,0b00000100,0b00000010,0b00000001
.db  0b00000000,0b00000000,0b00000000,0b00000000
.db  0b00000000,0b00000000,0b00000000,0b00000000
.db  0,0

ArrayB1:
.db  0b00000001,0b00000010,0b00000100,0b00001000
.db  0b00010000,0b00100000,0b01000000,0b10000000
.db  0b00000000,0b00000000,0b00000000,0b00000000
.db  0b00000000,0b00000000,0b00000000,0b00000000
.db  0,0

ArrayB2:
.db  0b10000001,0b01000010,0b00100100,0b00011000
.db  0b00011000,0b00100100,0b01000010,0b10000001
.db  0b00000000,0b00000000,0b00000000,0b00000000
.db  0b00000000,0b00000000,0b00000000,0b00000000
.db  0,0

ArrayB3:
.db  0b10000000,0b01000000,0b00100000,0b00010000
.db  0b00001000,0b00000100,0b00000010,0b00000001
.db  0b00000001,0b00000010,0b00000100,0b00001000
.db  0b00010000,0b00100000,0b01000000,0b10000000
.db  0b00000000,0b00000000,0b00000000,0b00000000
.db  0b00000000,0b00000000,0b00000000,0b00000000
.db  0b00000000,0b00000000,0b00000000,0b00000000
.db  0b00000000,0b00000000
.db  0,0
ArrayD0:
.db  0b0000000,0b0000000,0b0000000,0b0000000
.db  0b0000000,0b0000000,0b0000000,0b0000000
.db  0b1000000,0b0100000,0b0010000,0b0001000
.db  0b0000100,0b0000010,0b0000001,0b0000000
.db  0,0

ArrayD1:
.db  0b0000000,0b0000000,0b0000000,0b0000000
.db  0b0000000,0b0000000,0b0000000,0b0000000
.db  0b0000001,0b0000010,0b0000100,0b0001000
.db  0b0010000,0b0100000,0b1000000,0b0000000
.db  0,0

ArrayD2:
.db  0b0000000,0b0000000,0b0000000,0b0000000
.db  0b0000000,0b0000000,0b0000000,0b0000000
.db  0b1000001,0b0100010,0b0010100,0b0001000
.db  0b0001000,0b0010100,0b0100010,0b1000001
.db  0,0

ArrayD3:
.db  0b0000000,0b0000000,0b0000000,0b0000000
.db  0b0000000,0b0000000,0b0000000,0b0000000
.db  0b0000000,0b0000000,0b0000000,0b0000000
.db  0b0000000,0b0000000,0b0000000,0b0000000
.db  0b1000000,0b0100000,0b0010000,0b0001000
.db  0b0000100,0b0000010,0b0000001,0b0000001
.db  0b0000010,0b0000100,0b0001000,0b0010000
.db  0b0100000,0b1000000
.db  0,0

Спасибо заранее :)

Добавлено: Вс фев 01, 2009 16:30:03
C0oo1D
Что, никто не может ответить на этот вопрос??? По-моему он далеко не сложный.. На форуме задают гораздо сложнее как я посмотрю...

Добавлено: Вс фев 01, 2009 17:58:44
Cat_CooLeR
Непонял. Какой именно вопрос.. тут я его не увидел, то ли не понял, хотя на этот вопрос отвечу:
Так же хочется знать, нельзя-ли писать в массивах не 8 битами а 15?

Нет, так как "Порт – это пачка однобитных каналов" (в обучалке и написано). Если в порту 8 каналов, туда не пошлешь 15... Его нужно отдельно.

Re: Как применить массив к двум портам?

Добавлено: Вс фев 01, 2009 19:21:41
C0oo1D
ну, в общем, если проще - хотел сделать бегущую дорожку на 15 светодиодов, с использованием массивов. Но не до конца разобрался.. В уроке было описание только для одного порта, а вот как сделать для двух портов - не знаю.. представил выше код до чего я дошел, но там есть ошибка, наверное не одна. По этому хочу узнать кто что думает насчет того, как мне эту идею воплотить в реальность :)

Cat_CooLeR писал(а):Нет, так как "Порт – это пачка однобитных каналов" (в обучалке и написано). Если в порту 8 каналов, туда не пошлешь 15... Его нужно отдельно.

Просто я думал что как-то можно сделать так, что-бы код отличал данные в массиве, чтото типо:
"если данный бит больше 8 то вывод в порт D, иначе - в порт B"

Добавлено: Вс фев 01, 2009 19:37:11
Cat_CooLeR
Легче будет на С написать, в CodeVisionAVR к примеру.

Добавлено: Вс фев 01, 2009 19:47:50
C0oo1D
Cat_CooLeR писал(а):Легче будет на С написать, в CodeVisionAVR к примеру.

мм.. а идей на ассемблере нету? потому как я си не знаю..

Добавлено: Вс фев 01, 2009 20:10:21
Cat_CooLeR
Ну есть немного идей, а так нужно сесть и написать, попробую.

Добавлено: Вс фев 01, 2009 20:11:33
C0oo1D
Cat_CooLeR писал(а):Ну есть немного идей, а так нужно сесть и написать, попробую.

Чем код выше - не похож на пробную?) я даже написал в каком месте там ошибка) но не знаю как исправить..

Добавлено: Пн фев 02, 2009 22:05:27
C0oo1D
Есть еще идейки насчет этого кроме Си?

Добавлено: Ср фев 04, 2009 16:27:49
C0oo1D
Ладно, понятно.. изменил название темы.. теперь идеи появились?? :))

Добавлено: Ср фев 04, 2009 18:58:19
YurkaM
Ну например так:

Код: Выделить всё

.................................
.........Здесь без изменений....
.................................
.................................

        rcall SelectArray   ;сходим, выберем массив
        sei         ;разрешаем прерывания глобально

;***************************************************
;* Основная программа
;**************************************************
Loop:
        rjmp Loop    ;бесконечный цикл


;************************************************
;* Обработчик прерывания Таймера1 по совпадению A
;************************************************
Timer1_comp1:
        ldi Temp,0               ;обнуление таймера
        out TCNT1H,Temp          ;----------
        out TCNT1L,Temp          ;----------

ReadArray:
        lpm Temp1,Z+   ;грузим из массива байт для порта В и увеличиваем Z на 1
        lpm Temp2,Z+   ;грузим из массива байт для порта D и увеличиваем Z на 1
        cpi Temp2,0b11111111 ;проверяем не конец-ли? (код конца - 0b11111111)
        brne Output   ;если не конец, то переходим на вывод в порты
        rcall SelectArray ;идём на выбор массива (установка начальных ZH и ZL)и возвращаемся сюда
        rjmp   ReadArray

Output:
        out PortB,Temp1
        out PortD,Temp2
        reti
;*********************************************************************


;*********************************************************************
;* Подпрограмма выбора массива.
;* На входе - номер массива в ResCnt, на выходе - адрес начала массива в Z.
;*********************************************************************
SelectArray:
        andi ResCnt,0b00000011   ;отсечка лишних разрядов сч. сбросов

        cpi ResCnt,0             ;сравнение счетчика сбросов с конст.
        brne Tst1                ;если не равно - след. проверка
        ldi ZH,High(Array0*2)   ;загрузка начального адреса массива
        ldi ZL,Low(Array0*2)    ;----------
        rjmp Sel_end
Tst1:
        cpi ResCnt,1
        brne Tst2
        ldi ZH,High(Array1*2)
        rjmp Sel_end
Tst2:
        cpi ResCnt,2
        brne Tst3
        ldi ZH,High(Array2*2)
        ldi ZL,Low(Array2*2) 
        rjmp Sel_end
Tst3:
        ldi ZH,High(Array3*2)
        ldi ZL,Low(Array3*2)
Sel_end:
        ret
;*********************************************************************

;*********************************************************************
;* Массивы. Первый бат для порта B, второй - для D. Признак конца - байт 0b11111111 для порта D.
;*********************************************************************
Array0:
.db  0b10000000,0b0000000
.db  0b01000000,0b0000000
.db  0b00100000,0b0000000
.db  0b00010000,0b0000000
.db  0b00001000,0b0000000
.db  0b00000100,0b0000000
.db  0b00000010,0b0000000
.db  0b00000001,0b0000000
.db  0b00000000,0b1000000
.db  0b00000000,0b0100000
.db  0b00000000,0b0010000
.db  0b00000000,0b0001000
.db  0b00000000,0b0000100
.db  0b00000000,0b0000010
.db  0b00000000,0b0000001
.db  0b11111111,0b11111111


И не называй компаратором совпадение таймера. Это разные вещи.
Еще по-хорошему в обработчиках прерываний надо сохранять SREG при входе и восстанавливать его при выходе. В твоём случае можно без этого (прога очень проста и порча флагов ни на что не влияет).

Добавлено: Ср фев 04, 2009 20:14:19
C0oo1D
2 YurkaM
Спасибище огромное!!! Я знал что не надо городить тот огород и можно сделать намного проще!!! Но не знал как))))) *берет в свои лапы тактику построения кода, рисуя на морде ехидную улыбку*

З.Ы. Вопрос снят, тему можно закрывать :)

Добавлено: Ср фев 04, 2009 20:21:56
YurkaM
Ещё можно убрать эти строки, если в начале настроить таймер в режим обнуления при совпадении (CTC, кажется называется - кури даташит..)

Код: Выделить всё

        ldi Temp,0               ;обнуление таймера 
        out TCNT1H,Temp          ;----------
        out TCNT1L,Temp          ;----------


ps: я если честно, свой код не проверял, возможны мелкие ошибки/опечатки.. Но главное - общую идею показал, а дальше САМ!

Добавлено: Ср фев 04, 2009 20:38:19
C0oo1D
была только одна ошибка, но она совсем не серьезная :)) (нехватало 1 строки)
Tst1:
cpi ResCnt,1
brne Tst2
ldi ZH,High(Array1*2)
ldi ZL,Low(Array1*2)
rjmp Sel_end




Ещё можно убрать эти строки, если в начале настроить таймер в режим обнуления при совпадении (CTC, кажется называется - кури даташит..)

Пока не мешает, но спасибо за совет)