Мабуть, багато хто з тих, хто захоплюється розробкою на мікроконтролерах, хоча б кілька разів замислювався над можливістю керувати пристроєм за допомогою звичайного ІЧ-пульта від телевізора. Особливо приваблює те, що для підключення ІЧ-приймача TSOP4836 потрібні лише один вільний вивід і два резистори! Колись і я спробував такий варіант.


Розташування виводів TSOP4836
Я зібрав просту схему на 18F2520, розібрався, як декодувати сигнали, і написав код, за допомогою якого отримав сигнатури всіх доступних на той час ІЧ-пультів.
Нижче наведено вихідний код, за допомогою якого можна отримувати 32-бітні сигнатури для різних кнопок пульта:
#include <18f2520.h>
#define FCONST OSC_8MHZ // цю частоту встановлюватимемо програмно (використовуючи PLL)
#define FREQ 8000000 // робоча частота
#pragma config WDT = OFF
#pragma config LVP = OFF
#fuses INTRC_IO
#use delay (clock=FREQ)
#use rs232(baud=9600, xmit=PIN_A2,rcv=PIN_A3)
#define LED PIN_A0
INT1 Received=false;
long t;
int8 i;
// налаштування переривання на потрібний фронт імпульсу
#define LH_Edge 0
#define HL_Edge 1
int8 edge; // показує, на який фронт імпульсу налаштовано переривання: 0 — L_to_H, 1 — H_to_L
void setEdge(int1 e) {
edge=e;
if (e==LH_Edge) {
ext_int_edge(0, L_TO_H);
} else {
ext_int_edge(0, H_TO_L);
}
}
int32 t0,t1; // для збереження тривалості 0 та 1
int32 code; // декодований код із пульта дистанційного керування
int8 timerov; // кількість переповнень таймера
int8 cnt=0xFF; // кількість прийнятих імпульсів (якщо FF, підрахунок не ведеться — це ознака скидання)
#define MIN_LEAD_IN 1000 // 4 ms
#define MAX_LEAD_IN 1500 // 6 ms
#define MIN_TIME 60 // 0.24 ms
#define MID_TIME 200 // 0.8 ms
#define MAX_TIME 800 // 3.2 ms
#int_EXT
EXT_isr() {
if (!received) { // якщо код уже зчитано, але основна програма ще його не обробила, нічого не робимо
if (edge==HL_Edge) { // якщо виявлено 1→0
t1=(0x10000*timerov+get_timer0()); // запам’ятовуємо тривалість 1
} else { // якщо виявлено 0→1
t0=(0x10000*timerov+get_timer0()); // запам’ятовуємо тривалість 0
if (cnt==0xFF) {
if ((t1>MIN_LEAD_IN)&&(t1<MAX_LEAD_IN)) { // виявлено сигнал початку передавання
cnt=0;
code=0;
}
} else {
// прийнято чергову пару 0→1
if ((t1<MAX_TIME)&&(t1>MIN_TIME)&&(t0>MIN_TIME)&&(t0<MAX_TIME)) { // параметри сигналу в нормі, аналізуємо
if ((t1<MID_TIME)&&(t0<MID_TIME)) { // це 0
} else { // це 1
bit_set(code,cnt);
}
cnt++;
} else { // параметри вийшли за межі, виконуємо скидання
cnt=0xFF;
}
}
if (cnt==23) { // прийнято всі 23 біти
received=TRUE;
cnt=0xFF;
}
}
}
setEdge(!edge); // тепер відстежуватимемо інший фронт імпульсу
timerov=0;
set_timer0(0);
}
#int_TIMER0
// виконується під час переповнення 16-бітного таймера
TIMER0_isr() {
if (timerov<255)
timerov++;
}
void main()
{
setup_oscillator(FCONST);
delay_ms(5000);
printf("initr");
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER0);
setEdge(HL_Edge);
set_timer0(0);
delay_ms(10);
t=get_timer0();
printf("%Lu",t);
printf("00 tick/sec");
printf("gor");
DO
{
IF (received) {
disable_interrupts(GLOBAL);
printf("%lx ",code);
printf("r");
enable_interrupts(GLOBAL);
received=false;
}
}
WHILE (true);
}
Нижче наведено таблиці ІЧ-кодів для досліджених мною пультів. Коди в таблицях розташовані відповідно до розташування кнопок на пультах.
Таблиця кодів пульта «TOSHIBA CT-90119»
![]() |
0016bf40 | 0012bf40 | |
| 0013bf40 | 0017bf40 | 0010bf40 | |
| 0001bf40 | 0002bf40 | 0003bf40 | |
| 0004bf40 | 0005bf40 | 0006bf40 | |
| 0007bf40 | 0008bf40 | 0009bf40 | |
| 000bbf40 | 0000bf40 | 0014bf40 | |
| 001bbf40 | |||
| 001ebf40 | 001abf40 | ||
| 001fbf40 | |||
| 005bbf40 | 0018bf40 | 001cbf40 | |
| 0053bf40 | 0054bf40 | 000dbf40 | |
| 0048bf40 | 0015bf40 | 004bbf40 | |
| 0049bf40 | 004abf40 |
Таблиця кодів пульта «Twinhan-DVB»
![]() |
004dff00 | 0016ff00 | |
| 0003ff00 | 0001ff00 | 0006ff00 | |
| 0009ff00 | 001dff00 | 001fff00 | |
| 000dff00 | 0019ff00 | 001bff00 | |
| 0011ff00 | 0015ff00 | 0017ff00 | |
| 0040ff00 | 0005ff00 | 0012ff00 | |
| 000aff00 | 0014ff00 | 001eff00 | |
| 000eff00 | 0002ff00 | 001aff00 | |
| 004cff00 | 0010ff00 | 000cff00 | |
| 0054ff00 | 0048ff00 | 001cff00 | |
| 0004ff00 | 0000ff00 | 000fff00 |
Таблиця кодів пульта ORION-DVD
![]() |
0054bf40 | 005bbf40 | ||
| 0014bf40 | 0057bf40 | 0041bf40 | 0046bf40 | |
| 0009bf40 | 001dbf40 | 001fbf40 | 000dbf40 | |
| 0019bf40 | 001bbf40 | 0011bf40 | 0015bf40 | |
| 0017bf40 | 0012bf40 | 0059bf40 | 0008bf40 | |
| 0050bf40 | 0055bf40 | 0048bf40 | 004abf40 | |
| 005ebf40 | 0006bf40 | 0005bf40 | 0003bf40 | |
| 0047bf40 | 0007bf40 | 0040bf40 | 0002bf40 | |
| 0018bf40 | 0044bf40 | 000fbf40 | 0051bf40 | |
| 000abf40 | 001ebf40 | 000ebf40 | 001abf40 | |
| 0053bf40 | 0052bf40 | 0001bf40 | 0045bf40 |
Таблиця кодів ІЧ-пульта AVerMedia:
![]() |
0001fd02 | 0002fd02 | 0003fd02 | 0000fd02 |
| 0005fd02 | 0006fd02 | 0007fd02 | 0004fd02 | |
| 0009fd02 | 000afd02 | 000bfd02 | 0008fd02 | |
| 000dfd02 | 000efd02 | 000ffd02 | 000cfd02 | |
| 0011fd02 | 0012fd02 | 0013fd02 | 0010fd02 | |
| 0015fd02 | 0016fd02 | 0017fd02 | 0014fd02 | |
| 0019fd02 | 001afd02 | 001bfd02 | 0018fd02 | |
| 001dfd02 | 001efd02 | 001ffd02 | 001cfd02 | |
| 0001fc03 | 0002fc03 | 0003fc03 | 0000fc03 |





When specific buttons are pressed, you can use the incoming values to do something else in your code, for example turn on and off a motor or LED.
Yes, instead of code
printf(“%lx “,code);
printf(“r”);
you can insert your own code