Наш магазин на eBay Наш магазин на AliExpress Наш канал в telegram

Программная реализация трехканального ШИМ на микроконтроллере PIC12F629 (программа управления RGB-светодиодом)

Представленная ниже программа предназначена для управления RGB-светодиодом с помощью микроконтроллера PIC12F629. Для этого в программе реализован программный трехканальный ШИМ (ссылку на статью, в которой описана теория того, как это реализовано, можно найти в конце этой статьи). Каждый канал имеет разрядность 2 бита, позволяя таким образом сделать 22=4 различных уровня яркости свечения каждого кристалла, что в совокупности даёт возможность отобразить 4*4*4=64 различных цвета. Частота ШИМ — 100 Гц.

Алгоритм:

Алгоритм трехканального ШИМ на PIC контроллере

Поскольку для каждого канала мы используем 2 бита, то можно все три канала закодировать одним байтом (то есть каждый цвет можно кодировать одним байтом).

В данной программе переменная "skor" служит для задания скорости смены цветов. Количество импульсов ШИМ с одной и той же уставкой (то есть кличество импульсов, отображающих один и тот же цвет) равно начальному значению переменной "skor". В нашем примере начальное значение "skor"=25, то есть каждая уставка действует в течении 25 импульсов (то есть один и тот же цвет отображается 25 раз). Поскольку частота у нас 100 Гц, то 25 импульсов — это 250 мс.

Если есть желание организовать загрузку необходимых цветов с компьютера, то нужно делать аппаратный контроль передачи и, на время обработки подпрограммы прерывания от таймера, запрещать приём данных. Если этого не сделать, то пересылка данных может сбить частоту импульсов. В результате какое-то время некоторые светодиоды могут казаться максимально включенными, а другие — полностью выключенными.

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

    list p = 12f629
__config 01FC4h
;*** Переменные ******************************************
  CBLOCK 0x20  ; Начальный адрес блока
    Counter    ; счётчик (1 полный импульс = 3 отсчётам счётчика)
    Temp       ; вспомогательная переменная
    Temp2      ; ещё одна вспомогательная переменная
    Skor       ; скорость смены цветов
    RGB1       ; адрес этой переменной 24h
    RGB2       ; в этих 7-ми байтах находятся наборы уставок
    RGB3       ; для 7-ми цветов
    RGB4       ; в каждом байте первые два бита для Blue,
    RGB5       ; вторые два бита для Green, третьи для Red
    RGB6
    RGB7       ; адрес этой переменной 2Ah
  ENDC
;*** Константы / Адреса регистров ************************
T1      equ  .48  ; нач.значение аппаратн. счётчика = 255-207=48; 207*16=3328
Status  equ  03h  ; Регистр выбора банка
GPIO    equ  05h  ; управление защелками порта (банк 0)
Cmcon   equ  19h  ; Регистр компаратора (банк 0)
TrisIO  equ  05h  ; выбор направления работы выводов порта (банк 1)
INTCON  equ  0Bh  ; разрешение(1)/запрет(0) прерываний (любой банк)
OPT_REG equ  01h  ; Настройка таймера (банк 1)
TMR0    equ  01h  ; Регистр таймера (банк 0)
OSCCAL  equ  10h  ; хранение калибров-ой константы (банк 1)
INDF    equ  0h   ; Регистр косвенной адресации
FSR     equ  04h  ; Регистр адреса при косвенной адресации
;*********************************************************
; Пусть у нас GP0, GP1, GP5 - выходы управления RGB,
; остальные ноги также сконфигурируем как выходы
; GP5 - Blue, GP0 - Red, GP1 - Green
; В силу того, что у нашего RGB общий плюс, имеем:
; когда на ноге 0 - соответств-ий канал включен, когда 1 - выключен
;*********************************************************
 
   org 0
      goto   start
   org 4
;*** Подпрограмма прерывания от таймера ******************
taimer_prer
      bcf    INTCON,7    ; запрет прерываний
      movlw  T1          ; устанавлив.начальн.значение счётчика T1
      movwf  TMR0
      bsf    Status,5    ; и предделитель
      movlw  b'00000011'
      movwf  OPT_REG
      bcf    Status,5
;*** Проверяем программный счётчик ***********************
      bcf    Status,2   ; сбросить бит Z
      btfsc  Counter,2  ; если счётчик не= 4, - следующ.команда пропуск-ся
      clrf   Counter
      btfss  Status,2   ; если выполн.обнуление, пропускаем след.команду
      goto   Proverka   ; если счётчик не =0, то мы не отсчитали
                        ; целый импульс - переходим к проверкам
;*** Сюда мы попадаем после каждого целого импульса ******
;*** Проверяем указатель на текущую уставку **************
;*** (если он равен 2Bh, то делаем его равным 24h) *******
      movlw  2Bh
      xorwf  FSR,0
      btfss  Status,2   ; если FSR не = 2Bh, - следующ.команда выполн.
      goto   Next
      movlw  24h
      movwf  FSR
;*** Уменьшаем Skor, если равна нулю, загружаем **********
;*** новую уставку и выставляем начальное значение *******
Next  clrf   GPIO       ; зажигаем все светодиоды
      decfsz Skor,1     ; если Skor = 0, - пропускаем следующую команду
      goto   Proverka
;-----------------------------
      movf   INDF,0     ; читаем уставку по адресу, указанному в FSR
      movwf  Temp       ; загружаем его в Temp
      incf   FSR,1      ; переводим указатель на следующую уставку
      movlw  .25        ; значение скорости
      movwf  Skor
;*** Сравниваем все значения с уставками, и переключаем если надо
Proverka
      swapf  Temp,0      ; после этого уст-ка Red будет в первых 2-х битах W
      andlw  b'00000011' ; выделяем уставку Red
      xorwf  Counter,0   ; если счётчик=уставке, то установится флаг Z
      btfsc  Status,2    ; если Z=0, пропустить следующую команду
      bsf    GPIO,0      ; погасить Red
;---------------------------------------
      movf   Temp,0
      movwf  Temp2       ; загружаем Temp в Temp2
      rrf    Temp2,1
      rrf    Temp2,0     ; сдвигаем на 2 бита вправо и записываем в W
      andlw  b'00000011' ; выделяем уставку Green
      xorwf  Counter,0   ; если счётчик=уставке, то установится флаг Z
      btfsc  Status,2    ; если Z=0, пропустить следующую команду
      bsf    GPIO,1      ; погасить Green
;---------------------------------------
      movf   Temp,0
      andlw  b'00000011' ; выделяем уставку Blue
      xorwf  Counter,0   ; если счётчик=уставке, то установится флаг Z
      btfsc  Status,2    ; если Z=0, пропустить следующую команду
      bsf    GPIO,5      ; погасить Blue
;*** Выход ***********************************************
      incf   Counter,1   ; увеличиваем программный счётчик
      bcf    INTCON,2    ; сбросить флаг прерывания от таймера
      bsf    INTCON,7    ; разрешить прерывания
      retfie             ; выход
;*********************************************************
;*** КОНФИГУРИРОВАНИЕ КОНТРОЛЛЕРА ************************
;*** Калибровка Генератора *******************************
start bsf    Status,5
      Call   3FFh        ; Загрузить калибровочную константу в w
      movwf  OSCCAL
;*** Установка направления работы и инициализация ног ****
      bcf    Status,5    ; перейти в банк 0
      movlw  .255        ; 00111111 - все выходы равны 1
      movwf  GPIO        ; инициализация защелок
      movlw  .7          ; биты 0..2 поднять
      movwf  Cmcon       ; компаратор выключен
      bsf    Status,5    ; Перейти в 1-й банк
      clrf   TrisIO      ; все ноги сконфигурированы как выходы
;*** Конфигурируем таймер и включаем предделитель ********
      clrwdt
      movlw  b'00000011' ; предделитель =16,
      movwf  OPT_REG     ; TMR0 работает от внутр.тактового сигнала
      bcf    Status,5    ; переходим в банк 0
;*** Конфигурируем начальные значения переменных *********
      clrf   Temp
      movlw  .1
      movwf  Skor      ; чтобы в первом цикле попасть на загрузку уставок
      movlw  .4
      movwf  Counter   ; начальное значение счётчика равно 4
      movlw  24h
      movwf  FSR       ; указатель на первую уставку
;*** Записываем уставки **********************************
      movlw  b'00110000'  ; Красный
      movwf  RGB1
      movlw  b'00110100'  ; Оранжевый
      movwf  RGB2
      movlw  b'00111100'  ; Желтый
      movwf  RGB3
      movlw  b'00001000'  ; Зеленый
      movwf  RGB4
      movlw  b'00001011'  ; Голубой
      movwf  RGB5
      movlw  b'00000011'  ; Синий
      movwf  RGB6
      movlw  b'00100010'  ; Фиолетовый
      movwf  RGB7
;*** Разрешаем прерывания от таймера *********************
      clrf   INTCON       ; запретить все прерывания
      bsf    INTCON,5     ; Разрешить прерывания от таймера
      bsf    INTCON,7     ; Разрешить немаскированные прерывания
;*** РАБОЧАЯ ЧАСТЬ ***************************************
;*** Сканирование наличия принятой информации ************
Wait  nop                 ; здесь проц может поделать что-то полезное,
      goto   Wait         ; пока не придёт прерывание от таймера
   end

[свернуть]

Теория, как сделать программный n-канальный ШИМ

Схема подключения RGB-светодиодов к контроллеру и результаты работы программы

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

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