цифровая электроника
вычислительная техника
встраиваемые системы

 



Код для универсального пульта ДУ

Автор: Mike(admin) от 27-11-2014, 08:15

Современная электронная техника для облегчения ее использования человеком предусматривает зачастую ее управление дистанционно с помощью пульта. К сожалению, различные производители делают пульты только для своей технике, что неудобно при использовании техники различных производителей. В этом случае поможет универсальный пульт дистанционного управления, который можно собрать своими руками.


Приведенный код поможет создать универсальный пульт дистанционного управления на основе микроконтроллера PIC18F.


Изначальный принцип работы такого пульта предполагает получение инфракрасного сигнала любого пульта ДУ, кодирование его для передачи (в данном случае по RS485) и повторную передачу этого кода в удаленное место. Так, например, можно управлять телевизором или DVD-плеером, расположенным в гостиной, из спальни, имея при себе пульт от этого телевизора или DVD-плеера.


Основное требование к универсальному пульту – возможность работать с любым ИК-пультом любого производителя. Это не так просто, как кажется, поскольку существует очень много различных методов кодирования ИК-сигналов. Но на самом деле нам не нужно декодировать сигналы. Нужно просто «поймать» их, передать на удаленную точку и превратить их снова в сигналы инфракрасного диапазона.


Данный код представляет собой код на основе прерываний, который детектирует действительные ИК-сигналы, определяет ширину импульсов и в конечном итоге передает данные по шине UART. Другое устройство получает эти последовательные данные, декодирует их и передает их через логическую операцию И, на втором входе которой присутствуют тактовые импульсы 38 КГц. В конечном итоге полученный сигнал поступает на ИК-передатчик, который передает данные на конечное устройство (DVD-плеер, телевизор и т.д.).


Приемник ИК-сигналов подключен к входу INT0 микроконтроллера PIC, и прерывание срабатывает по фронту сигнала –VE. В обработчике прерывания затем подсчитывается количество времени, при котором сигнал остается в 1 или 0, либо счет ведется, пока не будет достигнуто максимальное значение. Каждое значение хранится в виде 16-битного беззнакового целого числа в массиве.


Значения не измеряются напрямую в миллисекундах или микросекундах, они зависят в первую очередь от внутреннего тактового генератора. Таким образом, чтобы повторно передать инфракрасный сигнал, что нужно знать, как эти коды соотносятся с реальными временными промежутками. Поэтому в коде присутствует коэффициент 1.42, который переведет значение в микросекунды, во время которых сигнал оставался в 1 или 0.


Данное устройство должно работать практически со всеми инфракрасными пультами дистанционного управления, включая пульты SONY, Philips, NEC, Denon и т.д.



#define MAX_IR_INDEX 64
#define ESCAPE_COUNT 0x2200ul

#pragma udata ircounts
unsigned int lcounts[MAX_IR_INDEX];
unsigned int hcounts[MAX_IR_INDEX];

#pragma interrupt high_isr /*=section(".tmpdata")*/

void high_isr(void) {

        unsigned int l;
        unsigned int c;
        unsigned char th, tl;

        l = 0;
        TMR1H = 0; // Всегда сначала записывать H перед L
        TMR1L = 0;

        // Проверка, что это прерывание INT0
        // IRRX это int0
        if(INTCONbits.INT0IF)
        {
                // отключаем источник прерывания
                INTCONbits.INT0IE = 0;
// код в while нужен для балансировки, так, биты ==0 и ==1 выражают размер циклов.
                while(lindex < MAX_IR_INDEX)
                {


                        while(PORTBbits.RB0 == 0)
                        {
                                l++;
                                if(l == ESCAPE_COUNT)
                                {
                                        lcounts[lindex] = 0xffff;
                                        goto done;
                                }
                        }

                        tl = TMR1L;
                        th = TMR1H; // << 8 ;// Всегда читаем L перед H
                        lcounts[lindex++] = th * 256 + tl;

                        l = 0;
                        TMR1H = 0;
                        TMR1L = 0;
                        while(PORTBbits.RB0 == 1)
                        {
                                l++;
                                if(l == ESCAPE_COUNT)
                                {
                                        hcounts[hindex] = 0xffff;
                                        goto done;
                                }
                        }


                        tl = TMR1L;
                        th = TMR1H; //<< 8 ;
                        hcounts[hindex++] = th * 256 + tl;

                        l = 0;
                        TMR1H = 0;
                        TMR1L = 0;

                }
        }
done:
        codeReady = 1;

        // сбрасываем бит статуса прерывания
        //INTCONbits.INT0IE = 1;
        //INTCONbits.INT0IF = 0;
        return;
}

void zeroIR() {
        unsigned char c;

        lindex = 0;
        hindex = 0;

        for(c = 0; c < MAX_IR_INDEX; c++)
        {
                lcounts[c] = 0xdead;
        }

        codeReady = 0;

        // сбрасываем бит статуса прерывания
        INTCONbits.INT0IE = 1;
        INTCONbits.INT0IF = 0;

}

void transmitIR(void) {

        unsigned char c;

        // В первую очередь проверяем, что код верен путем проверки LCOUNT.
        // Если оно меньше нашего определенного значения, передача не будет осуществлена.
        // Первый lcount содержит преамбулу, она должна быть минимальной дины, 
        // иначе она не будет представлять собой действительную для передачи преамбулу.

        if(lcounts[0] < PREAMBLE_MINIMUM)
        {
                return;
        }
       
        sprintf(serTX, (CAST) "$%c%cIC%d,", id1, id2, lindex);
        rs485_puts(serTX);

        for(c = 0; c < lindex; c++)
        {
                sprintf(serTX, (CAST) "%04x,%04x, ", lcounts[c], hcounts[c]);
                rs485_puts(serTX);
        }


        sprintf(serTX, (CAST) "\n");
        rs485_puts(serTX);

}



Перевод © digitrode.ru


<Via>


Теги: пульт ДУ




Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

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

Оставить комментарий