Программа, рассмотренная в этой статье, разработана специально для самодельного ИК-пульта дистанционного управления на контроллере ATtiny13. Если вы измените аппаратную часть (например, будете использовать другой порядок ног, повесите внешний генератор), то программу также нужно будет переделать.
Прежде чем разбираться с программой, наверное, каждому будет полезно посмотреть описание протокола RC-5.
Алгоритм:
Итак, пусть в аппаратной части мы имеем:
входы: PB4 — кнопка SB1, PB2 — кнопка SB2, PB0 — кнопка SB3, PB1 — кнопка SB4
выходы: PB3 — вывод информации по протоколу RC-5.
RESET внешне подтянут к питанию; используется внутренний генератор на 9,6 МГц.
Пусть мы планируем управлять светом, то есть номер системы будет 29.
.device ATtiny13 .include "tn13def.inc" .list ;--- определяем свои переменные .def w=r16 ; это будет наш аккумулятор .def T_Cr=r17 ; таймер несущей .def T_NC=r18 ; счётчик кол-ва импульсов в пакете .def T_0=r19 ; таймер интервала между пакетами .def LBC=r20 ; младший байт посылки .def MBC=r21 ; старший байт посылки ;-- определяем константы .equ Cr1=22 ; длительность 1 несущей .equ Cr0=64 ; длительность 0 несущей .equ NCr=32 ; кол-во импульсов несущей в одном пакете .equ Sys=29 ; номер системы .equ CMD_1=1 ; код команды 1 .equ CMD_2=2 ; код команды 2 .equ CMD_3=3 ; код команды 3 .equ CMD_4=4 ; код команды 4 ;--------------------------------------------------------- .cseg .org 0 ;--- начало программы ------------------------------------ Init: ldi w,RAMEND ; устанавливаем указатель вершины out SPL,w ; стека на старший байт RAM sbi ACSR,7 ; выключаем компаратор ldi w,0b00001000 ; определяем входы и выходы порта out DDRB,w ldi w,0b11110111 ; включаем подтягивающие резисторы out PORTB,w ; и определяем начальное состояние выходов ;-- формирование старшего байта пакета ldi MBC,Sys ; записываем в старший байт номер системы sbr MBC,0b11000000 ; устанавливаем старт-биты Scan: sbis PINB,4 ; если на входе PB4 низкий уровень - нажата КН1 rjmp Tx_CMD1 sbis PINB,2 ; если на входе PB2 низкий уровень - нажата КН2 rjmp Tx_CMD2 sbis PINB,0 ; если на входе PB0 низкий уровень - нажата КН3 rjmp Tx_CMD3 sbis PINB,1 ; если на входе PB1 низкий уровень - нажата КН4 rjmp Tx_CMD4 sbr MBC,0b00100000 ; установить toggle bit в 1 (первое нажатие) rjmp Scan ;--- формирование младшего байта пакета ------------------ Tx_CMD1: ldi LBC,CMD_1 ; записываем в младший байт номер команды 1 rjmp TxRC Tx_CMD2: ldi LBC,CMD_2 ; записываем в младший байт номер команды 2 rjmp TxRC Tx_CMD3: ldi LBC,CMD_3 ; записываем в младший байт номер команды 3 rjmp TxRC Tx_CMD4: ldi LBC,CMD_4 ; записываем в младший байт номер команды 4 rjmp TxRC ;--- Передача пакета RC-5--------------------------------- TxRC: sbrc MBC,7 ; Startbit 1. Если бит равен 1 - выполняется rcall Tx_1 ; Tx_1, если бит равен 0 - выполняется Tx_0 sbrs MBC,7 rcall Tx_0 ;------------ sbrc MBC,6 ; Startbit 2 rcall Tx_1 sbrs MBC,6 rcall Tx_0 ;------------ sbrc MBC,5 ; Toggle bit rcall Tx_1 sbrs MBC,5 rcall Tx_0 ;------------ sbrc MBC,4 ; System bit 4 rcall Tx_1 sbrs MBC,4 rcall Tx_0 ;------------ sbrc MBC,3 ; System bit 3 rcall Tx_1 sbrs MBC,3 rcall Tx_0 ;------------ sbrc MBC,2 ; System bit 2 rcall Tx_1 sbrs MBC,2 rcall Tx_0 ;------------ sbrc MBC,1 ; System bit 1 rcall Tx_1 sbrs MBC,1 rcall Tx_0 ;------------ sbrc MBC,0 ; System bit 0 rcall Tx_1 sbrs MBC,0 rcall Tx_0 ;------------ sbrc LBC,5 ; Command bit 5 rcall Tx_1 sbrs LBC,5 rcall Tx_0 ;------------ sbrc LBC,4 ; Command bit 4 rcall Tx_1 sbrs LBC,4 rcall Tx_0 ;------------ sbrc LBC,3 ; Command bit 3 rcall Tx_1 sbrs LBC,3 rcall Tx_0 ;------------ sbrc LBC,2 ; Command bit 2 rcall Tx_1 sbrs LBC,2 rcall Tx_0 ;------------ sbrc LBC,1 ; Command bit 1 rcall Tx_1 sbrs LBC,1 rcall Tx_0 ;------------ sbrc LBC,0 ; Command bit 0 rcall Tx_1 sbrs LBC,0 rcall Tx_0 ;------------ cbr MBC,0b00100000 ; сбрасываем toggle bit (повторное нажатие) ;--------------------------------------------------------- ;--- пауза, равная межпакетному интервалу (50 бит), т.е. надо послать ;--- 100 нулевых полубитов (RCN) ------------------------- ldi T_0,99 pause: rcall RCN dec T_0 brne pause rjmp Scan ;--- КОНЕЦ ОСНОВНОЙ ПРОГРАММЫ ---------------------------- ;--- ПОДПРОГРАММЫ ПЕРЕДАЧИ НУЛЯ И ЕДИНИЦЫ ---------------- ;--- передача нуля манчестерским кодом ------------------- Tx_0: rcall RCY ; первые полбита единица rcall RCN ; вторые полбита ноль ret ;--- передача единицы манчестерским кодом ---------------- Tx_1: rcall RCN ; первые полбита ноль rcall RCY ; вторые полбита единица ret ;--------------------------------------------------------- ;--- ПОДПРОГРАММЫ ФОРМИРОВАНИЯ СОСТОЯНИЙ "ON" И "OFF" ---- ;--- передача единичного полубита ("ON") ----------------- RCY: ldi T_NC,NCr ; загрузить кол-во импульсов Y_001: ldi T_Cr,Cr1 ; загрузить длительность импульса sbi PORTB,3 ; установить 1 на выходе Cr1_Y: dec T_Cr brne Cr1_Y ; для точной подстройки частоты несущей cbi PORTB,3 ; установить 0 на выходе ldi T_Cr,Cr0 ; длительность паузы в импульсе Cr0_Y: dec T_Cr brne Cr0_Y ; для точной подстройки частоты несущей dec T_NC brne Y_001 ret ;--- передача нулевого полубита ("OFF") ------------------ RCN: ldi T_NC,NCr ; подпрограмма передачи нулевого полубита имеет N_001: ldi T_Cr,Cr1 ; туже структуру, что и подпрограмма передачи nop ; единичного полубита только для того, чтобы Cr1_N: dec T_Cr ; было легче регулировать их длительности brne Cr1_N ; единственное отличие - команды sbi, cbi nop ; заменены на nop ldi T_Cr,Cr0 Cr0_N: dec T_Cr brne Cr0_N dec T_NC brne N_001 ret ;--------------------------------------------------------- |
Скачать готовую прошивку и asm-файл
Кроме этого должны быть запрограммированы следующие фьюзы: SPIEN, SUT0, CKSEL0. Запрограммированы — то есть сброшены в ноль, то есть в Pony Prog, например, напротив них должны стоять галочки.
Если интересно — можете посмотреть для сравнения такую же программу для PIC12F629 (алгоритм точно такой же, отличается только порядок ног).