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

Программа для самодельного ИК-приемника, протокол RC-5 (манчестерское кодирование)

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

Программа реализует следующие функции:

1) Подпрограмма обработки прерывания проверяет принимаемый код на соответствие манчестерскому алгоритму, декодирует принятый код и записывает его в 2 байта:

MBC — 7,6 биты — стартовые; 5 — управляющий бит; 4…0 — номер системы

LBC — 7…2 биты — номер команды; 1,0 биты — не используются

если принимаемый код не манчестерский — загорается первый светодиод.

2) В рабочей части программы реализуется управление тремя оставшимися светодиодами: если номер системы в принятом коде не тот, который мы ждали, — загорается второй светодиод, если номер системы совпадает с ожидаемым, но номер команды не совпадает с ожидаемым — загорается третий светодиод, и, наконец, если и номер системы и номер команды совпадают с ожидаемыми — загорается четвертый светодиод.

Прежде чем разбираться с программой, советую посмотреть описание протокола RC-5.

Основные идеи алгоритма:

1) Выход ILMS1836 — инвертированный, т.е. когда принимается "1" — на выходе фотоприемника "0" (низкий уровень), когда приема нет или принимается "0" — на выходе фотоприемника "1"(высокий уровень).

2) Стартовый бит манчестерским кодом передается как последовательность "01", но первый полубит ("0") мы не отличим от отсутствия сигнала, т.е. фактически прием начинается со второго полубита.

3) В процессе работы программа считывает значение на входе контроллера каждые 889 мкс и считает это значение — значением принятого полубита.

4) Программа уходит в прерывание очень быстро — за несколько микросекунд, поэтому, чтобы читать значения подальше от границы полубитов, перед приемом первого полубита вводится пауза, примерно равная половине полубита.

5) Для проверки на соответствие манчестерскому алгоритму используется следующее его свойство: никакие три последовательных полубита не могут быть одновременно нулями или единицами.

6) Если записывать все четные полубиты, начиная со второго, то мы восстановим исходную посылку.

То есть мы принимаем все полубиты, но! Четные — записываем и используем для проверки на соответствие манчестерскому алгоритму, нечетные — используем только для проверки.

Алгоритм:

Алгоритм работы самодельного ИК-приёмника (протокол RC5)
Алгоритм работы самодельного ИК-приёмника (протокол RC5)

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

входы: GP5 — вход ИК-приемника

выходы: GP0, GP1, GP2, GP4 — выходы на транзисторы управления светодиодами.

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

Пусть мы ожидаем команду 2 от пульта системы управления светом (номер системы 29).

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

 list    p = 12f629
 __config 01FE4h
;*** Переменные ******************************************
  CBLOCK 0x20  ; Начальный адрес блока пользовательской памяти
    MBC        ; старший байт посылки (полбита - 889uS)
    LBC        ; младший байт посылки
    Schetchik  ; счетчик принятых бит
    Prov_reg   ; для проверки на манчестер (сюда пишем 3 послед. принятых бита)
    Adrbit     ; адрес бита для записи
    Counter    ; счетчик для паузы
  ENDC
;*** Константы / Адреса регистров ************************
T1     equ  .205 ; задержка 1
T2     equ  .204 ; задержка 2
TP     equ  .250 ; задержка чтобы дождаться окончания последнего полубита
TN     equ  .125 ; начальная задержка, чтобы попасть на середину полубита
Sys    equ  .29  ; номер системы
CMD_1  equ  .8   ; код команды 000010 00, последние 2 бита не 
                 ; используются, т.е. команда = 2
INDF   equ  0h   ; регистр косвенной адресации
Status equ  03h  ; выбор банка
FSR    equ  04h  ; регистр адреса при косвенной адресации
GPIO   equ  05h  ; Регистр управления защелками порта.
Cmcon  equ  19h  ; Регистр Cmcon - компаратора
TrisIO equ  05h  ; Регистр выбора направления работы выводов порта.
INTCON equ  0Bh  ; Регистр разрешения(1)/запрета(0) прерываний
IOCB   equ  16h  ; регистр разрешения прерываний по GP0...GP5
OSCCAL equ  10h  ; Регистр хранения калибровочной константы
F      equ  1    ; Результат направить в регистр.
;********************************************************
; Пусть у нас GP0 (1-й кр),  GP1(2-й кр), GP2(жел), GP4(зел) - выходы на
; транзисторы управления светодиодов, GP5 - вход ИК-приемника
;********************************************************
   org 0
      goto   start
   org 4
;*** ПРЕРЫВАНИЕ *****************************************
      btfsc  GPIO,5    ; если вход не = 0, то это не начало приема
      goto   exit
;*** Установить счетчик принятых бит ********************
      movlw  .1        ; 3-й бит счётчика определяет куда пишем,
      movwf  Schetchik ; если 1, то в MBC, если 0, то в LBC
;*** Установить адрес бита для записи = 7 (поднять 7-й бит)
      movlw  .128
      movwf  Adrbit
;*** Заполняем три младших бита проверочного регистра нулями
      clrf   Prov_reg
;*** Установить адрес регистра для косвенной адресации (сначала пишем в MBC)
      movlw  MBC       ; записываем адрес MBC в регистр косвенной адресации
      movwf  FSR
;*** Начальная задержка *********************************
      movlw  TN
      movwf  Counter
nach_zad
      nop
      decfsz Counter,1
      goto   nach_zad
;*** ЗАПИСЬ БАЙТА ***************************************
;*** Второй полубит n-го бита ***************************
;*** Проверить вход и записать принятый полубит**********
zapis btfss  GPIO,5    ; если на входе GP5 низкий уровень - пишем единицу
      goto   zapis1
zapis0
      comf   Adrbit,0   ; записываем позицию бита, которую будем менять
      andwf  INDF,1     ; побитное "и", - ставим 0 в позиции, указанной в Adrbit
      bcf    Status,0   ; очищаем флаг переноса
      rlf    Prov_reg,1 ; сдвигаем биты в проверочном регистре влево
      movlw  .7         ; .7 = 00000111 
      andwf  Prov_reg,1 ; сбрасываем все биты кроме первых трех
      bcf    Prov_reg,0 ; в нулевой бит проверочного регистра пишем ноль 
      goto   sdvig
zapis1
      movf   Adrbit,0
      iorwf  INDF,1     ; побитное "или", - ставим 1 в позиц., указанной в Adrbit
      bcf    Status,0   ; очищаем флаг переноса
      rlf    Prov_reg,1 ; сдвигаем биты в проверочном регистре влево
      movlw  .7         ; .7 = 00000111 
      andwf  Prov_reg,1 ; сбрасываем все биты кроме первых трех
      bsf    Prov_reg,0 ; в нулевой бит проверочного регистра пишем единицу
;*** меняем адрес записи бита ***************************
sdvig bcf    Status,0   ; очищаем флаг С
      rrf    Adrbit,1   ; циклич. сдвиг вправо через перенос (смещаем позицию)
      btfsc  Status,0   ; если флаг С = 0, пропускаем следующую команду
      bsf    Adrbit,7   ; поднимаем 7-й бит (ставим адрес на 7-й бит)
;*** Проверяем на манчестер *****************************
      movlw  .0
      xorwf  Prov_reg,0 ; проверка - равен ли нулю проверочный регистр
      btfsc  Status,2   ; если флаг Z = 0, пропускаем следующую команду
      goto   not_manch
      movlw  .7
      xorwf  Prov_reg,0 ; проверка - равен ли 00000111 проверочный регистр
      btfsc  Status,2   ; если флаг Z = 0, пропускаем следующую команду
      goto   not_manch
;*** Задержка 1, чтобы общая длительность от метки zapis до
;*** окончания задержки равнялась 889 мкс ***************
      movlw  T1
      movwf  Counter    ; загружаем в Counter таймер T1
Count1
      nop
      decfsz Counter,1
      goto   Count1 
      nop
;*** первый полубит n+1-го бита (писать не надо, но для *
;*** проверки на манчестер использовать надо) ***********
      btfss  GPIO,5     ; если на входе GP5 низкий уровень - пишем единицу
      goto   zapis12
zapis02
      bcf    Status,0   ; очищаем флаг переноса
      rlf    Prov_reg,1 ; сдвигаем биты в проверочном регистре влево
      movlw  .7         ; .7 = 00000111 
      andwf  Prov_reg,1 ; сбрасываем все биты кроме первых трех
      bcf    Prov_reg,0 ; в нулевой бит проверочного регистра пишем ноль 
      goto   proverka
zapis12
      bcf    Status,0   ; очищаем флаг переноса
      rlf    Prov_reg,1 ; сдвигаем биты в проверочном регистре влево
      movlw  .7         ; .7 = 00000111 
      andwf  Prov_reg,1 ; сбрасываем все биты кроме первых трех
      bsf    Prov_reg,0 ; в нулевой бит проверочного регистра пишем единицу
;*** Проверяем на манчестер *****************************
proverka
      movlw  .0
      xorwf  Prov_reg,0 ; проверка - равен ли нулю проверочный регистр
      btfsc  Status,2   ; если флаг Z = 0, то проверочный регистр не равен 0,
                        ; пропускаем следующую команду
      goto   not_manch
      movlw  .7
      xorwf  Prov_reg,0 ; проверка - равен ли 00000111 проверочный регистр
      btfsc  Status,2   ; если флаг Z = 0, пропускаем следующую команду
      goto   not_manch
;*** Задержка 2, чтобы общая длительность от чтения этого
;*** полубита до чтения следующего равнялась 889 мкс ****
      movlw  T2
      movwf  Counter    ; загружаем в Counter таймер T2
Count2
      nop
      decfsz Counter,1 
      goto   Count2
      nop
;*** Сколько бит записали? ******************************
      movlw  .14
      xorwf  Schetchik,0; счетчик = 14?
      btfsc  Status,2   ; если флаг Z = 0, пропускаем следующую команду
      return            ; выходим без разрешения прерываний
;*** Если бит 3 счетчика = 1, то мы уже записали 8 бит и
;*** следующие надо писать в LBC ************************
      btfss  Schetchik,3; если третий бит счетчика равен единице,
                        ; то следующая инструкция пропускается
      goto   zap_MBC
zap_LBC
      movlw  LBC        ; записываем адрес LBC в регистр косвенной адресации
      movwf  FSR
      goto   next 
zap_MBC
      movlw  MBC        ; записываем адрес MBC в регистр косвенной адресации
      movwf  FSR
;*** Увеличить счетчик **********************************
next  incf   Schetchik,1; увеличиваем счетчик
      goto   zapis
;*** Погасить все, зажечь первый красный ****************
not_manch
      movlw  b'11101001'
      andwf  GPIO,1     ; погасить 2-й красный, жёлтый и зелёный
      nop
      bsf    GPIO, 0    ; зажечь первый красный светодиод
;*** Сбросить признак принятия посылки ******************
      bcf    MBC,7
;*** Сбросить флаг прерываний и выйти *******************
exit  bcf    INTCON,0
      retfie
 
;*** КОНФИГУРИРОВАНИЕ КОНТРОЛЛЕРА ***********************
;*** Калибровка Генератора ******************************
start bsf    Status,5
      Call   3FFh       ; Загрузить калибровочную константу в w
      movwf  OSCCAL
;*** Установка направления работы ног *******************
      bcf    Status,5   ; перейти в банк 0
      clrf   GPIO       ; инициализация защелок (0 на всех, кроме GP5)
      movlw  .7         ; биты 0..2 поднять
      movwf  Cmcon      ; компаратор выкл., GP0, GP1, GP2 - цифровые вх/вых
      clrf   LBC
      clrf   MBC
      bsf    Status,5   ; Перейти в 1-й банк
      movlw  .40        ; Пишем конф-ю GPIO в аккум.
      movwf  TrisIO     ; Скопировать конфигурацию GPIO из W в TrisIO
;*** Разрешить прерывания на входе GP5 ******************
      movlw  .32        ; .32 = 00100000
      movwf  IOCB       ; разреш. прерывание на вх.GP5, на остальных - нет
      bcf    Status,5   ; Перейти в 0-й банк
      movlw  .8         ; .8 = 00001000 
      movwf  INTCON     ; разрешить прерывание от GPIO
      bsf    INTCON,7   ; разрешить прерывания
      nop
;*** Сканирование наличия принятой информации ***********
Scan  btfsc  MBC,7      ; если start бит (7-й) в регистре MBC = 1,
                        ; то была принята информация (первый старт бит = 1)
      goto   rab_chast
      goto   Scan
 
;*** РАБОЧАЯ ЧАСТЬ **************************************
;*** Проверка номера системы ****************************
rab_chast
      movf   MBC,0
      andlw  .31        ; "И" с 00011111 - отрезаем стартов. и управл. биты
      xorlw  Sys
      btfss  Status,2   ; если Z=1, то следующая инстр-я не выполняется 
                        ; (номер совпадает с заданным)
      goto   nosys
;*** Проверка номера команды ****************************
      movlw  CMD_1
      xorwf  LBC,0
      btfss  Status,2   ; если Z=1, то следующая инструкция не выполняется
      goto   nocom
;*** Погасить все, зажечь зеленый ***********************
      movlw  b'11111000'
      andwf  GPIO,1     ; погасить 1-й красный, 2-й красный и жёлтый
      nop
      bsf    GPIO, 4    ; зажечь зелёный светодиод
      goto   out
;*** Погасить все, зажечь второй красный ****************
nosys movlw  b'11101010'
      andwf  GPIO,1     ; погасить 1-й красный, жёлтый и зелёный
      nop
      bsf    GPIO, 1    ; зажечь второй красный светодиод
      goto   out
;*** Погасить все, зажечь желтый ************************
nocom movlw  b'11101100'
      andwf  GPIO,1     ; погасить 1-й красный, 2-й красный и зелёный
      nop
      bsf    GPIO, 2    ; зажечь желтый светодиод
;*** Сбросить признак принятия посылки и флаг прерывания
out   bcf    MBC,7      ; сбрасываем признак принятия посылки
      bcf    INTCON,0   ; сбрасываем флаг прерывания
;*** Пауза **********************************************
      movlw  TP
      movwf  Counter
pause nop
      decfsz Counter,1
      goto   pause
;*** Разрешить прерывания *******************************
      bsf    INTCON,7
      nop
      goto   Scan
 end

[свернуть]

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

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

  1. Считываем текущую конфигурацию контроллера.
  2. Записываем значение битов калибровки схемы BOR (12-й, 13-й биты слова конфигурации, они же bandgap)
  3. Записываем значение последнего слова программного кода (слово по адресу 03FF) — биты калибровки генератора.
  4. Открываем нашу прошивку в программе программатора, и меняем в ней биты калибровки схемы BOR и генератора на считанные и записанные значения.
  5. Всё, теперь эту (исправленную для конкретного экземпляра PIC12) прошивку можно заливать в контроллер.

Комментарии 2

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