Программа, рассмотренная в этой статье, разработана специально для самодельного ИК-приемника сигналов дистанционного управления на контроллере 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) Если записывать все четные полубиты, начиная со второго, то мы восстановим исходную посылку.
То есть мы принимаем все полубиты, но! Четные — записываем и используем для проверки на соответствие манчестерскому алгоритму, нечетные — используем только для проверки.
Алгоритм:
![]() ![]() |
Итак, пусть в аппаратной части мы имеем:
входы: 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-файл
Внимание. Во избежание затирания калибровочных констант — алгоритм заливки этой прошивки в контроллер следующий:
- Считываем текущую конфигурацию контроллера.
- Записываем значение битов калибровки схемы BOR (12-й, 13-й биты слова конфигурации, они же bandgap)
- Записываем значение последнего слова программного кода (слово по адресу 03FF) — биты калибровки генератора.
- Открываем нашу прошивку в программе программатора, и меняем в ней биты калибровки схемы BOR и генератора на считанные и записанные значения.
- Всё, теперь эту (исправленную для конкретного экземпляра PIC12) прошивку можно заливать в контроллер.
Привет. Админ, у вас ошибка в строчке bsf GPIO,1
;*** Погасить все, зажечь желтый ************************
nocom movlw b’11101100′
andwf GPIO,1 ; погасить 1-й красный, 2-й красный и зелёный
nop
bsf GPIO, 1 ; зажечь желтый светодиод
нужно исправить на bsf GPIO,2 , чтобы третий светодиод загорался.
Спасибо, исправил.