Световые эффекты для светодиодной матрицы. Универсальная программа для программирования любых световых эффектов. + пример работы - "вращающийся крест".

светодиодная матрица

Ниже описана программа (для PIC16F628A), позволяющая легко запрограммировать любые световые эффекты для самодельной светодиодной матрицы 5х5.

Как вы, наверное, уже догадались (если читали статью про саму матрицу) основная проблема нашей матрицы в том, что на ней невозможно включить несколько произвольных светодиодов одновременно в разных строках и столбцах. Однако, в одном столбце (или строке) одновременно включить несколько произвольных светодиодов можно. Но! Если мы будем включать нужные нам светодиоды, например, построчно, при этом очень быстро меняя строки, то для глаза рисунок сольется и будет казаться точно таким же, как если бы мы произвольно включили несколько светодиодов в разных строках и столбцах.

пример фрейма

То есть, фактически, картинка показывается за пять циклов: сначала первая строка, потом вторая, потом третья и так далее до пятой строки, после чего все циклы повторяются, но, за счет очень быстрого переключения строк, мы видим один статичный кадр (фрейм).

Так как каждый фрейм у нас состоит из пяти строк, в каждой из которых по пять столбцов, то весь фрейм кодируется 5*5 битами. Для удобства будем использовать один байт на столбец (старшие три бита использовать не будем), итого получим 5 байт на фрейм.

Переключая такие псевдостатичные картинки (но уже с различимой для глаза скоростью) можно получить динамическое изображение. Шесть (к примеру) фреймов для нашей матрицы займут в памяти 5*6=30 байт. Фреймы можно хранить в памяти данных EEPROM. Она имеет размер 128 байт, то есть позволяет хранить до 25 фреймов. Посчитаем: 25*5=125 + 2 байта (для хранения информации о количестве загруженных фреймов и о скорости смены фреймов).

Если соединить контроллер с компьютером через USART, то можно будет загружать фреймы прямо с компьютера, но об этом мы поговорим позже.

Итак, контроллер управляет драйверами строк и столбцов. Чтобы подключить строки 1, 2, 3, 4, 5 к шине питания - нужно подать "1" на выходы контроллера RA2, RA3, RA1, RA7, RA6 соответственно, а для того, чтобы подключить столбцы 1, 2, 3, 4, 5 к нулевой шине (к земле) - нужно подать "0" на выходы контроллера RB3, RB4, RB5, RB6, RB7 соответственно.

Светодиод загорается в том случае, если он подключен и к питанию и к земле.

В нашем примере мы будем загружать фреймы из EEPROM в ОЗУ, причём только в нулевой банк, в котором, за вычетом всех пользовательских переменных, на фреймы остается 86 байт, то есть максимум 17 фреймов.

Для реализации динамической картинки "вращающийся крест" нам понадобится 6 фреймов:

фреймы для эфекта "вращающийся крест"

Алгоритм:

Блок-схема алгоритма управления светодиодной матрицей

Программа:

;---------------------------------------------------------
 list    p = 12f629
 __config 03F30h
;*** Переменные ******************************************
   CBLOCK 0x20  ; Начальный адрес блока пользовательской памяти
    Temp        ; обменник                         , 20h
    Adr         ; адрес фрейма в EEPROM или ОЗУ    , 21h
    T_int       ; счетчик для паузы                , 22h
    Strok       ; байт текущего состояния строк    , 23h
    Stolb       ; байт текущего состояния столбцов , 24h
    Fr_sch      ; счетчик фреймов                  , 25h
    Fr_cikl     ; счетчик показов одного фрейма    , 26h
    Fr_kol      ; количество фреймов               , 27h
    Fr_cikl_kol ; количество показов одного фрейма , 28h
;--- Свободная память ОЗУ в нулевом банке от 29h до 7Fh.
;--- Из этих 86 своб-х байт в первые 30 мы будем грузить наши фреймы
   ENDC
;**** Константы / Адреса регистров ************************
Status equ  03h    ; выбор банка
TrisA  equ  05h    ; выбор направления работы выводов порта А
TrisB  equ  06h    ; выбор направления работы выводов порта В
PortA  equ  05h    ; управление защелками порта А
PortB  equ  06h    ; управленип защелками порта В
Cmcon  equ  1Fh    ; вкл/выкл компараторов
F      equ  1      ; результат направить в регистр.
FSR    equ  04h    ; адрес при косвенной адресации
INDF   equ  0h     ; регистр косвенной адресации
Cr     equ  .50    ; значение счетчика для паузы
EEADR  equ  1Bh    ; адрес EEPROM
EECON1 equ  1Ch    ; регистр для работы c EEPROM
EEDATA equ  1Ah    ; регистр данных из/в EEPROM
;*********************************************************
; Итак, у нас RA1, RA2, RA3, RA6, RA7 - строки
;             RB3, RB4, RB5, RB6, RB7 - столбцы
;*********************************************************

          org 0
start movlw  .7
      movwf  Cmcon    ; выключить компараторы
      clrf   PortA    ; инициализация защелок порта А
      movlw  .248     ; 11111000
      movwf  PortB    ; инициализация защелок порта В
      bsf    Status,5 ; перейти в 1-й банк
      movlw  .49      ; конфигурация порта A: .49=00110001
      movwf  TrisA    ; загрузить конфигурацию порта А
      movlw  .7       ; конфигурация порта В: .7=00000111
      movwf  TrisB    ; загрузить конфигурацию порта B
      bcf    Status,0 ; Сбросить флаг переноса (С)
;*** Загрузка данных для фреймов из EEPROM в ОЗУ
;--- Сначала читаем 1-й байт, узнаем - сколько фреймов надо считывать
      movlw  .0       ; банк менять не надо, мы уже в первом банке
      movwf  EEADR    ; установить адрес для чтения из EEPROM
      bsf    EECON1,0 ; чтение
      movf   EEDATA,0 ; запись прочитанного байта в аккумулятор
      bcf    Status,5 ; перейти в 0-й банк
      movwf  Fr_kol   ; сохранение прочитанного байта в Fr_kol
;--- Fr_kol*5+1 - узнаём, сколько байт надо считать
      rlf    Fr_kol,0 ; умножаем на 2
      movwf  Temp
      rlf    Temp,0   ; еще на 2 (после этой команды в аккум-ре Fr_kol*4)
      addwf  Fr_kol,0 ; после этого в аккумуляторе Fr_kol*5
      movwf  Temp     ; сохраняем это значение в Temp
      incf   Temp,1   ; теперь Temp=Fr_kol*5+1
;--- Считываем Fr_kol*5+1 байт
      movlw  28h      ; считанные данные сохр.начиная с этого адреса
      movwf  FSR      ; адрес для косвенной адресации
      movlw  .1       ; начинаем читать EEPROM
      movwf  Adr      ; с адреса 1
zagruzka
      bsf    Status,5 ; перейти в первый банк
      movwf  EEADR    ; загружаем из аккум-ра адрес для чтения из EEPROM
      bsf    EECON1,0 ; чтение
      movf   EEDATA,0 ; запись прочитанного байта в аккумулятор
      bcf    Status,5 ; перейти в 0-й банк
      movwf  INDF     ; сохр.считанный байт по адресу, записанному в FSR
      incf   FSR,1    ; увеличиваем адрес ОЗУ
      incf   Adr,1    ; увеличиваем адрес EEPROM
      movf   Adr,0    ; загружаем адрес EEPROM в аккумулятор
      decfsz Temp,1   ; если считали все байты - след.команда пропуск-ся
      goto   zagruzka
;*********************************************************
;*** Основная прога **************************************
effect movlw  29h      ; загруж.адрес начала первого фрейма в ОЗУ (29h)
       movwf  Adr      ;  в переменную Adr
       movf   Fr_kol,0 ; загружаем кол-во фреймов
       movwf  Fr_sch   ; в счетчик фреймов
show   movf   Fr_cikl_kol,0 ; загружаем кол-во показов одного фрейма
       movwf  Fr_cikl       ; в счетчик показов фрейма
povtor call   show_frame    ; показываем один фрейм Fr_cikl кол-во раз
       decfsz Fr_cikl,1
       goto   povtor
       movlw  .5            ; перех. к следующ. фрейму (сдвигаем Adr на 5)
       addwf  Adr,1
       decfsz Fr_sch,1      ; уменьшаем кол-во фреймов для показа
       goto   show          ; если не все наборы показаны, - перех. к след-му
       goto   effect        ; если все, то начинаем сначала
;*********************************************************
;*** Процедура показа одного фрейма **********************
show_frame
      movf   Adr,0       ; загружаем в FSR адрес начала фрейма
      movwf  FSR                 
      movlw  b'00000001' ; начинаем с первой строки
      movwf  Strok
show_next
      movf   INDF,0      ; загружаем набор столбцов для выбранной строки
      movwf  Stolb       ; аккумулятор в stolb
      call   in_ports
      call   pause
      call   erase
      incf   FSR,1       ; следующий набор строк
      rlf    Strok,1     ; переходим на следующую строку
      btfss  Strok,5     ; если 5-й бит strok = 1, - след.команда пропуск-ся
      goto   show_next
      return
;*** Процедура включ-я строк и столбцов в соотв-вии с байтами Strok и Stolb
in_ports  
      btfsc Stolb,0   ; если 0-й бит stolb = 0, то след. команда пропуск-ся
      bcf   PortB,3   ; RB3=0 - вкл.1 столбец
      btfss Stolb,0   ; если 0-й бит stolb =1, то след. команда пропуск-ся
      bsf   PortB,3   ; RB3=1 - выкл. 1 столбец
;--------------------------------------        
      btfsc Stolb,1   ; если 1-й бит stolb = 0, то след. команда пропуск-ся
      bcf   PortB,4   ; RB4=0 - вкл. 2 столбец
      btfss Stolb,1   ; если 1-й бит stolb =1, то след. команда пропуск-ся
      bsf   PortB,4   ; RB4=1 - выкл. 2 столбец
;--------------------------------------        
      btfsc Stolb,2   ; если 2-й бит stolb = 0, то след. команда пропуск-ся
      bcf   PortB,5   ; RB5=0 - вкл. 3 столбец
      btfss Stolb,2   ; если 2-й бит stolb =1, то след. команда пропуск-ся
      bsf   PortB,5   ; RB5=1 - выкл. 3 столбец
;--------------------------------------        
      btfsc Stolb,3   ; если 3-й бит stolb = 0, то след. команда пропуск-ся
      bcf   PortB,6   ; RB6=0 - вкл. 4 столбец
      btfss Stolb,3   ; если 3-й бит stolb =1, то след. команда пропуск-ся
      bsf   PortB,6   ; RB6=1 - выкл. 4 столбец
;--------------------------------------        
      btfsc Stolb,4   ; если 4-й бит stolb = 0, то след. команда пропуск-ся
      bcf   PortB,7   ; RB7=0 - вкл. 5 столбец
      btfss Stolb,4   ; если 4-й бит stolb =1, то след. команда пропуск-ся
      bsf   PortB,7   ; RB7=1 - выкл. 5 столбец
;-------- Строки ----------------------
      btfsc Strok,0   ; если 0-й бит strok = 0, то след. команда пропуск-ся
      bsf   PortA,2   ; RA2=1 - вкл.1 строку
      btfss Strok,0   ; если 0-й бит strok =1, то след. команда пропуск-ся
      bcf   PortA,2   ; RA2=0 - выкл.1 строку
;--------------------------------------        
      btfsc Strok,1   ; если 1-й бит strok = 0, то след. команда пропуск-ся
      bsf   PortA,3   ; RA3=1 - вкл.2 строку
      btfss Strok,1   ; если 1-й бит strok =1, то след. команда пропуск-ся
      bcf   PortA,3   ; RA3=0 - выкл.2 строку
;--------------------------------------        
      btfsc Strok,2   ; если 2-й бит strok = 0, то след. команда пропуск-ся
      bsf   PortA,1   ; RA1=1 - вкл.3 строку
      btfss Strok,2   ; если 2-й бит strok =1, то след. команда пропуск-ся
      bcf   PortA,1   ; RA1=0 - выкл.3 строку
;--------------------------------------        
      btfsc Strok,3   ; если 3-й бит strok = 0, то след. команда пропуск-ся
      bsf   PortA,7   ; RA7=1 - вкл.4 строку
      btfss Strok,3   ; если 3-й бит strok =1, то след. команда пропуск-ся
      bcf   PortA,7   ; RA7=0 - выкл.4 столбец
;--------------------------------------        
      btfsc Strok,4   ; если 4-й бит strok = 0, то след. команда пропуск-ся
      bsf   PortA,6   ; RA6=1 - вкл.5 строку
      btfss Strok,4   ; если 4-й бит strok =1, то след. команда пропуск-ся
      bcf   PortA,6   ; RA6=0 - выкл.5 строку
      return
;*** Пауза ***********************************************
pause movlw  Cr 
      movwf  T_int    ; загрузить кол-во циклов задержки
cikl3 decfsz T_int,1  ; если T_int = 0, следующая команда пропускается 
      goto   cikl3    ; внутренний цикл 
      return
;*** Гашение всех светодиодов ****************************
erase movf   Strok,0
      movwf  Temp
      movlw  .0
      movwf  Stolb
      movwf  Strok
      call   in_ports
      movf   Temp,0
      movwf  Strok
      return
;*********************************************************
  org 2100h         ; EEPROM память
 de .6, .40         ; кол-во фреймов и кол-во показов одного фрейма (скорость)
 de b'00000100', b'00000100', b'00011111', b'00000100', b'00000100' ; 1-й фрейм
 de b'00001000', b'00000101', b'00001110', b'00010100', b'00000010' ; 2-й фрейм
 de b'00001000', b'00001011', b'00000100', b'00011010', b'00000010' ; 3-й фрейм
 de b'00010001', b'00001010', b'00000100', b'00001010', b'00010001' ; 4-й фрейм
 de b'00000010', b'00011010', b'00000100', b'00001011', b'00001000' ; 5-й фрейм
 de b'00000010', b'00010100', b'00001110', b'00000101', b'00001000' ; 6-й фрейм
 end
;---------------------------------------------------------

Скачать готовую прошивку и asm-файл

Можно запрограммировать в каждый фрейм по букве и динамически (по буквам) выводить какую-нибудь надпись. Получится что-то типа матрицы со знакогенератором. Попробуйте, например, залить в EEPROM такую прошивку:

 de .8,  .255  ; кол-во фреймов и показов одного фрейма (скорость)
 de 11h, 19h, 15h, 13h, 11h   ; первый фрейм
 de 0Eh, 0Ah, 0Ah, 1Fh, 11h   ; второй фрейм
 de 11h, 19h, 15h, 13h, 11h   ; третий фрейм
 de 0Fh, 09h, 1Fh, 11h, 1Fh   ; четвертый фрейм
 de 15h, 0Eh, 04h, 0Eh, 15h   ; пятый фрейм
 de 1Fh, 11h, 11h, 11h, 1Fh   ; шестой фрейм
 de 1Fh, 11h, 11h, 11h, 11h   ; седьмой фрейм
 de 12h, 12h, 0Сh, 08h, 06h   ; восьмой фрейм

radiohlam.ruпрограммированиесвет и световые эффекты

Понравилась статья? Поделись с друзьями!

Обсудить эту статью на форуме

 
Rambler's Top100 © 2009 - Материалы сайта охраняются законом об авторском праве