Управляющая программа для микроконтроллерного диммера светодиодных драйверов на NCP3066

В этой статье приводится пример простейшей программы управления микроконтроллером для диммера светодиодных драйверов на NCP3066. Диммер у нас сделан на микроконтроллере ATTiny13 и представляет собой генератор прямоугольных импульсов с регулируемым коэффициентом заполнения.

С представленной ниже программой наш диммер генерирует прямоугольные импульсы на частоте около 600 Гц и умеет регулировать их коэффициент заполнения в зависимости от нажатий двух кнопок: «увеличить», «уменьшить».

Алгоритм обработки нажатий кнопок сделан таким образом, что вам не нужно жать кнопку столько же раз, на сколько шагов нужно изменить коэффициент заполнения. Всё то время, пока вы держите кнопку нажатой — он изменяется. Причём изменение это реализовано с двумя скоростями — сразу после нажатия на кнопку коэффициент заполнения изменяется медленно, а при удержании кнопки дольше определённого времени — она начинает изменяться быстрее. (Пришлось сделать такую фишку, поскольку шагов много и тыкать 256 раз на кнопку или держать её 3 часа нажатой — довольно утомительно).

Управление от ИК-пульта в данной программе не реализовано, поскольку всяких ИК-интерфейсов довольно много и возиться с каждым не хотелось. Если будет нужен какой-то конкретный вариант, с которым вы сами не справитесь, — пишите на форум, — попробуем вместе допилить до нужной кондиции.

Для того, чтобы определить что нужно и чего не нужно делать программе в текущем цикле — нам понадобятся два флага, под которые мы выделим специальный регистр (flags).
Установленный нулевой бит этого регистра будет говорить о том, что мы находимся в режиме изменения, установленный первый бит — о том, что мы держим кнопку уже достаточно долго и изменения нужно производить с повышенной скоростью.

Алгоритм:

Алгоритм работы диммера для светодиодных драйверов на ncp3066

Текст программы под катом

.device ATtiny13
.include "tn13def.inc"
.list
;-- определяем свои переменные
.def   w=r16        ; это будет наш аккумулятор
.def   setup=r17    ; это задание
.def   flags=r18    ; флаги (0 - изменяем выход, 1 - slow/fast)
.def   setup_counter=r19  ; - для задержки
.def   setup_counter2=r20 ; - для задержки
.def   counter_sch=r21    ; - для отсчёта количества шагов после
                          ; которых включается режим fast
;--------------------------
.equ   slow_setup=255   ; задержка большая (slow)
.equ   fast_setup=64    ; задержка маленькая (fast)
.equ   s_maximum=255    ; начальное ограничение максимального выхода
.equ   s_minimum=1      ; начальное ограничение минимального выхода
.equ   s_setup=128      ; начальное значение выхода
;-- Используемые регистры
; SPL - указатель вершины стека
; ACSR - управление компаратором
; DDRB - направление работы ног
; PORTB - выходы порта
; PCMSK - разрешение прерываний на отдельных входах
; GIMSK - общее разрешение прерываний по входам
; GTCCR - сброс предделителя
; TCCR0B - управление таймером
; TIMSK0 - прерывания от таймера
; PB0 - выход ШИМ, PB1 - вход КН2, PB2- вход КН1, PB3 - вход ИК
;-- начало программного кода
        .cseg
        .org 0
        rjmp Init  ; переход на начало программы
;-- вектора прерываний
        reti       ; INT0
        rjmp Pch   ; Pin Change
        reti       ; Timer
        reti       ; EEPROM
        reti       ; comparator
        reti       ; timer compare match A
        reti       ; timer compare match B
        reti       ; watchdog
        reti       ; ADC
;-- начало программы
Init: ldi w,RAMEND     ; устанавливаем указатель вершины
      out SPL,w        ; стека на старший байт RAM
      sbi ACSR,7       ; выключаем компаратор
      ldi w,0b00000001 ; определяем входы/выходы порта (1-выход,0-вход)
      out DDRB,w
      ldi w,0b11111110 ; включаем подтягивающие резисторы
      out PORTB,w      ; и определяем начальное состояние выходов
      ldi setup,s_setup; ставим начальное задание для ШИМ
;-- включаем ШИМ на выходе PB0 (OC0A)
      ldi w,s_setup    ; записываем начальный коэффициент заполнения
      out OCR0A,w
      ldi w,0b10000011 ; fastPWM, set at TOP, clear at compare
      out TCCR0A,w
      ldi w,0b00000011 ; fastPWM, prescale 1:64
      out TCCR0B,w
;-- разрешить прерывание от входов
      ldi w,0b00100000
      out GIMSK,w      ; разрешаем прерывание от входов
;-- разрешить прерывания на входах PB1, PB2, PB3
Start: ldi w,0b00100000
       out GIFR,w      ; сбросить флаг прерываний от входов
       ldi w,0b00001110
       out PCMSK,w     ; разрешаем прерывания на входах PB2, PB1. (PB3)
       sei             ; разрешить глобальные прерывания
;----------------------------------------------------------------------
Scan: sbrc flags,0     ; если флаг сброшен - пропускаем команду
      rcall Setup_update
      rjmp Scan
 
;--- Меняем задание и выход ---
Setup_update:
      sbis PINB,3      ; если нет приёма от ИК-пульта - пропустить
      rjmp IR_control
      dec  setup_counter
      brne End_chs     ; если не отсчитали нужный интервал - прыгаем
      ldi  setup_counter,255
      dec  setup_counter2
      brne End_chs     ; если не отсчитали нужный интервал - прыгаем
Setup_change:
      sbis PINB,1      ; если первая кнопка не нажата - пропустить
      rjmp Dec_setup
      sbis PINB,2      ; если вторая кнопка не нажата - пропустить
      rjmp Inc_setup
      clr  flags       ; если ни одна кнопка не нажата
      rjmp End_chs
Dec_setup:
      dec  setup
      cpi  setup,s_minimum
      brlo SetMin      ; если новое задание меньше минимума - прыгаем
      rjmp ExitSetup
SetMin:
      ldi setup,s_minimum ; ставим задание равным минимуму
      rjmp ExitSetup
Inc_Setup:
      inc setup
      cpi setup,s_maximum
      brsh SetMax      ; если максимум меньше нового задания - прыгаем
      rjmp ExitSetup
SetMax:
      ldi setup,s_maximum ; ставим задание равным максимуму
      rjmp ExitSetup
IR_Control:
    ; -- сюда можно вставить обработчик для приёма ИК-сигнала
ExitSetup:
      sbrc flags,1     ; если флаг поднят - fast режим
      rjmp Fast_change
Slow_change:
      ldi  setup_counter2, slow_setup
      inc  counter_sch      ; увеличиваем счётчик изменений задания
      sbrc counter_sch,2    ; если 2-й бит поднят
      sbr  flags,0b00000010 ; переключаемся в режим fast change
      rjmp End_chs
Fast_change:
      ldi  setup_counter2, fast_setup
End_chs:
      out OCR0A,setup       ; устанавливаем заданное значение выхода
      ret
 
;-- ОБРАБОТЧИК ПРЕРЫВАНИЯ ПО ВХОДУ
Pch: sbr  flags,0b00000001   ; ставим флаг изменения выхода
     ldi  setup_counter,255
     ldi  setup_counter2,slow_setup ; задаём задержку
     clr  counter_sch        ; обнуляем счётчик изменений
     ldi  flags,0b00000001   ; режим slow change, нужно изменять выход
     reti                    ; и выходим

[свернуть]

Вот и вся программа. Чтобы всё корректно работало — в контроллере должны быть «запрограммированы» фьюзы SPIEN, SUT0 и CKSEL0 (то есть в PonyProg напротив них должны стоять галочки).

Скачать одним архивом алгоритм, исходники и прошивку

Добавить комментарий