Программа для самодельного ИК-пульта,

протокол SIRC для техники фирмы SONY (кодирование длиной импульса)

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

Естественно, прежде чем разбираться с программой, полезно разобраться с самим протоколом SIRC. Если с протоколом всё понятно - можете смело читать дальше.

Представленный вариант полностью написан на ассемблере, в конце статьи выложены сорцы (с комментариями) и прошивка. Программа написана для 15-ти битной версии протокола (она самая распространённая, но в принципе нет ничего сложного в переделывании её на 12-ти или 20-ти битную версию), частота несущей - 40 кГц.

Для начала как всегда немного текстовых пояснений. Итак, в данном случае для отсчёта времени импульса и паузы используется встроенный таймер TMR0. Для управления передачей, в алгоритме используются два специальных управляющих регистра (на самом деле это обычные регистры общего назначения, которые у нас выполняют специальную функцию, поэтому я и пишу "специальных"). Один из них - счётчик количества передаваемых импульсов и пауз, причём отсчёт начинается с паузы стартовой последовательности (нулевое значение счётчика). Соответственно, если значение счётчика нечётное - мы должны передать импульс, а если чётное - паузу. Второй регистр служит для указания позиции передаваемого бита. В начале передачи мы взводим в этом регистре младший бит и потом, после передачи каждого бита посылки, сдвигаем наш указатель влево, перебирая таким образом все позиции от младшего бита к старшему. После того, как указатель сдвинется влево 8 раз, указатель адреса передаваемого байта устанавливается на следующий предназначенный для передачи байт, а указатель позиции передаваемого бита снова позиционируется на нулевой бит.

Ну вот, вкратце идею описали, теперь перейдём к подробному алгоритму и программе.

Алгоритм:

Алгоритм реализации протокола SIRC

Итак, пусть в аппаратной части мы имеем:

входы: GP5 - кнопка SB1, GP2 - кнопка SB2, GP4 - кнопка SB3, GP1 - кнопка SB4

выходы: GP0 - вывод информации по протоколу SIRC.

MCLR внешне подтянут к питанию; используется внутренний генератор.

Программа:

;---------------------------------------------------------
 list    p = 12f629
 __config 01FE4h
;*** Переменные ******************************************
  CBLOCK 0x20  ; Начальный адрес блока пользовательской памяти
    T_Cr       ; таймер несущей
    C_imp      ; счетчик кол-ва импульсов. если 0-й бит (C_imp-1) = 0 - последним
               ; посылали единичный полубит, если единице - нулевой.
               ; биты 1-3 - № посылаемого бита. биты 4-7 - № посылаемого байта
    Nbit       ; позиция посылаемого бита
    Byte1      ; первый байт для передачи
    Byte2      ; второй байт для передачи
  ENDC
;*** Константы / Адреса регистров ************************
 P1    equ  .200        ; константа для паузы
 P2    equ  .200        ; константа для паузы
 Cr1   equ  .2          ; длительность 1 несущей
 Cr0   equ  .4          ; длительность 0 несущей
 Tl    equ  .238        ; 255-длительность низкого уровня (236)
 Th1   equ  .219        ; 255-длительность высокого уровня 1-го бита (218)
 Th0   equ  .238        ; 255-длительность высокого уровня 0-го бита (236)
 Tsl   equ  .238        ; 255-длит-ть низкого уровня в старт. последов-ти (236)
 Tsh   equ  .182        ; 255-длит-ть высокого уровня в старт. последов-ти (180)
 AL    equ  b'00000100' ; адрес 01h (заданный байт адреса)
 CMD_11       equ         10h         ; код команды 1 (младшие 8 бит)
 CMD_12       equ         0h          ; код команды 1 (старшие 2 бита)
 CMD_21       equ         11h         ; код команды 2 (младшие 8 бит)
 CMD_22       equ         0h          ; код команды 2 (старшие 2 бита)
 CMD_31       equ         12h         ; код команды 3 (младшие 8 бит)
 CMD_32       equ         0h          ; код команды 3 (старшие 2 бита)
 CMD_41       equ         13h         ; код команды 4 (младшие 8 бит)
 CMD_42       equ         0h          ; код команды 4 (старшие 2 бита)
;---------------------------------------------------------
 Status  equ     03h    ; Регистр выбора банка
 GPIO    equ     05h    ; Регистр управления защелками порта
 Cmcon   equ     19h    ; Регистр Cmcon - компаратора
 TrisIO  equ     05h    ; выбор направления работы выводов порта
 OPT_REG equ     01h    ; Настройка таймера (банк 1)
 TMR0    equ     01h    ; Регистр таймера (банк 0)
 INTCON  equ     0Bh    ; Регистр разрешения(1)/запрета(0) прерываний
 INDF    equ     0h     ; регистр косвенной адресации
 FSR     equ     04h    ; регистр адреса при косвенной адресации
 OSCCAL  equ     10h    ; Регистр хранения калибровочной константы
 F       equ     1      ; Результат направить в регистр.
;*********************************************************
; Пусть у нас GP0 - выход на транзистор управления ИК-диода,
; GP1, GP2, GP4, GP5 - входы
;*********************************************************

              org 0
;*** НАЧАЛЬНАЯ НАСТРОЙКА КОНТРОЛЛЕРА *********************
;*** Калибровка Генератора *******************************
      bsf    Status,5
      Call   3FFh       ; Загрузить калибровочную константу в w
      movwf  OSCCAL
      goto   start
;*********************************************************
;*** ПОДПРОГРАММА ПРЕРЫВАНИЯ *****************************
      bcf    GPIO,0     ; выключить выход, если он был включен
      bcf    INTCON,2   ; сбросить флаг переполнения TMR0
;--------------------
      movf   C_imp,1    ; проверяем счётчик импульсов на ноль
      btfsc  Status,2   ; если счётчик равен 0 - переход на Send_Start0
      goto   Send_Start0
;--------------------
      btfss  C_imp,0    ; проверяем 0-й бит счётчика, если 
                        ; он = 0 - посылаем низкий уровень,
      goto   Send_LL    ; который у нас всегда одинаковой длины
;--- если передали 30 имп-сов (т.е. должны перед. 31-й) - передача окончена
      movlw  .31
      xorwf  C_imp,0
      btfss  Status,2   ; если флаг Z установился - пропускаем переход
                        ; к передаче высокого уровня и завершаем передачу
      goto   Send_HH
;-------------------
Send_end
      clrf   INTCON     ; сбрасываем все прерывания и флаги
      call   Pause      ; выдерживаем паузу
      goto   Scan       ; переходим к сканированию клавиш
;--- посылаем высокий уровень ---
Send_HH
      movf   INDF,0     ; читаем передаваемый байт
      andwf  Nbit,0     ; "И" передаваемого байта с указ.передаваем. бита
      btfss  Status,2   ; если Z=1 - в передаваемом байте, в поз.Nbit у нас 0
      goto   Send_H1
;--- загружаем длит-ть высокого уровня, соответствующую нулевому биту ---
Send_H0
      movlw  Th0
      movwf  TMR0       ; загружаем Th0 в TMR0
      goto   Next
;--- загружаем длит-ть низкого уровня, соответствующую единичному биту ---
Send_H1
      movlw  Th1
      movwf  TMR0       ; загружаем Th1 в TMR0
Next  incf   C_imp,1    ; увеличить счётчик импульсов
      bsf    INTCON,7   ; разрешить немаскированные прерывания
      goto   Hlevel
;--------------------
Send_LL
      movlw  Tl
      movwf  TMR0       ; загрузить Th в TMR0
      incf   C_imp,1    ; увеличить счётчик импульсов
      bcf    Status,0   ; сбросить флаг переноса
      rlf    Nbit,1     ; сдвинуть указатель передаваемого бита
      btfss  Status,0   ; если С=1 - ещё раз сдв.влево указ.бита и увелич.FSR
      goto   Next2
      rlf    Nbit,1
      incf   FSR,1
Next2 bsf    INTCON,7   ; разрешить немаскированные прерывания
      goto   Llevel
;--------------------
Send_Start0
      clrf   Nbit       ; очищаем указатель позиции передаваемого бита
      bsf    Nbit,0     ; поднимаем в указателе 0-й бит
      movlw  Byte1
      movwf  FSR        ; адрес косвенной адресации ставим на первый байт
      movlw  Tsl
      movwf  TMR0       ; загрузить Tsl в TMR0
      incf   C_imp,1    ; увеличить счётчик импульсов
      bsf    INTCON,7   ; разрешить немаскированные прерывания
      goto Llevel
;*** КОНЕЦ ПРЕРЫВАНИЯ ************************************

;*** ПРОДОЛЖЕНИЕ НАЧАЛЬНОЙ НАСТРОЙКИ *********************
start bcf    Status,5   ; перейти в банк 0
      clrf   GPIO       ; инициализация защелок (нули на всех защелках)
      movlw  .7         ; биты 0..2 поднять
      movwf  Cmcon      ; компаратор выключен, GP0, GP1, GP2 - цифровые вх/вых
      bsf    Status,5   ; Перейти в 1-й банк
      movlw  .62        ; Записать конфигурацию GPIO в аккумулятор (W)
                        ; .62=00 111110 GP0 - выход, остальные - входы
      movwf  TrisIO     ; Скопировать конфигурацию GPIO из W в регистр TrisIO.
;--- Настраиваем предделитель таймера ---
      movlw  b'00000100'; настройка предделителя 1:32, 32*256=8,192 мс
      movwf  OPT_REG
      bcf    Status,5   ; Перейти в 0-й банк
;*** КОНЕЦ НАЧАЛЬНОЙ НАСТРОЙКИ ***************************


;*** СКАНИРОВАНИЕ КЛАВИАТУРЫ *****************************
Scan  btfss  GPIO,5     ; если на входе GP5 низкий уровень - нажата клавиша 1
      goto   Tx_CMD1
      btfss  GPIO,2     ; если на входе GP2 низкий уровень - нажата клавиша 2
      goto   Tx_CMD2
      btfss  GPIO,4     ; если на входе GP4 низкий уровень - нажата клавиша 3
      goto   Tx_CMD3
      btfss  GPIO,1     ; если на входе GP1 низкий уровень - нажата клавиша 4
      goto   Tx_CMD4
      goto   Scan
;*** КОНЕЦ СКАНИРОВАНИЯ **********************************


;*** ПОДГОТОВКА К НАЧАЛУ ПЕРЕДАЧИ ************************
Tx_CMD1
      movlw  CMD_11     ; в первый байт для передачи
      movwf  Byte1      ; пишем младшие 8 бит команды 
      movlw  CMD_12     ; пишем в аккумулятор старшие 2 бита команды
      goto   Form_Com
;------------------------
Tx_CMD2
      movlw  CMD_21     ; в первый байт для передачи
      movwf  Byte1      ; пишем младшие 8 бит команды
      movlw  CMD_22     ; пишем в аккумулятор старшие 2 бита команды
      goto   Form_Com
;------------------------
Tx_CMD3
      movlw  CMD_31     ; в первый байт для передачи
      movwf  Byte1      ; пишем младшие 8 бит команды
      movlw  CMD_32     ; пишем в аккумулятор старшие 2 бита команды
      goto   Form_Com
;------------------------
Tx_CMD4
      movlw  CMD_41     ; в первый байт для передачи
      movwf  Byte1      ; пишем младшие 8 бит команды
      movlw  CMD_42     ; пишем в аккумулятор старшие 2 бита команды
Form_Com
      movwf  Byte2
      movlw  AL         ; перед старшими битами команды дописываем 5
      iorwf  Byte2,1    ; бит адреса - получаем второй байт для передачи
;--- Сбрасываем счётчик импульсов, загружаем в таймер время передачи
;--- высокого уровня стартовой послед-ти и включаем прерывания от таймера
      clrf   C_imp      ; сбросить счётчик импульсов
      movlw  Tsh
      movwf  TMR0       ; загрузить Tsh в таймер
      bcf    INTCON,2   ; сбросить флаг переполнения таймера
      bsf    INTCON,5   ; разрешить прерывание от таймера
      bsf    INTCON,7   ; разрешить немаскированные прерывания
;--- goto Hlevel - эту команду не пишем, переход и так происходит на Hlevel
;*** КОНЕЦ ПОДГОТОВКИ ************************************


;*** ПРОЦЕДУРЫ ПЕРЕДАЧИ ВЫСОКОГО И НИЗКОГО УРОВНЯ СИГНАЛА
;*** Передача высокого уровня ***
Hlevel
      movlw  Cr1        ; поместить константу Cr1 в аккумулятор
      movwf  T_Cr       ; скопир-ть аккум-р в регистр T_Cr (таймер несущей)
      bsf    GPIO,0     ; установить на выходе GP0 единицу
Cr1_Y decfsz T_Cr,F     ; декремент содержимого регистра T_Cr с ветвлением
      goto   Cr1_Y      ; переход на метку Cr1_Y
      nop               ; для точной подстройки времени высокого уровня
                        ; (и соответственно частоты и скважности)
      bcf    GPIO,0     ; Установить на выходе GP0 ноль
      movlw  Cr0        ; поместить константу Cr0 в аккумулятор
      movwf  T_Cr       ; скопировать содержимое аккум-ра в регистр T_Cr
Cr0_Y decfsz T_Cr,F
      goto   Cr0_Y
      nop               ; для точной подстройки времени низкого уровня
      nop               ; для точной подстройки времени низкого уровня
      goto   Hlevel
;*** Передача низкого уровня ***
Llevel
      nop
      goto  Llevel
;*** КОНЕЦ ПРОЦЕДУР ПЕРЕДАЧИ *****************************

;*** ПОДПРОГРАММА ПАУЗЫ **********************************
Pause movlw  P1
      movwf  T_Cr
cikl2 movlw  P2
      movwf  C_imp
cikl1 nop
      decfsz C_imp,1
      goto   cikl1
      decfsz T_Cr,1
      goto   cikl2
      return
;*********************************************************
end
;---------------------------------------------------------

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

Внимание. Во избежание затирания калибровочных констант - алгоритм заливки этой прошивки в контроллер следующий:

1. Считываем текущую конфигурацию контроллера.

2. Записываем значение битов калибровки схемы BOR (12-й, 13-й биты слова конфигурации, они же bandgap).

3. Записываем значение последнего слова программного кода (слово по адресу 03FF) - биты калибровки генератора.

4. Открываем нашу прошивку в программе программатора, и меняем в ней биты калибровки схемы BOR и генератора на считанные и записанные значения.

5. Всё, теперь эту (исправленную для конкретного экземпляра PIC12) прошивку можно заливать в контроллер.

radiohlam.ruпрограммированиеинтерфейсы / протоколы / ИК-управление

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

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

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