дописал таки толковую функцию приема байта по ИК каналу, которая не чувствительна к длине пакета и достаточно простая и компактная. Но работать будет только на PIC16F886, потому как задействует ресурсы железа для разгрузки программной части
для отработки прерываний по фронту и срезу использован модель CCP1 процессора, чтобы не заморачиваться с прерываниями на портах. Для счета соответственно таймер TMR1, который работает автоматически. То есть управляется внешним сигналом GATE, от TSOPа. Как только сигнал падает в ноль, таймер начинает считать сам, потом по прерыванию от ССP он свое значение защелкивает в его регистры хранения (все это железка сама делает). Нам остается только считать его показания, переключить модуль CCP на прерывание теперь уже по фронту и просто сидеть и ждать следующего события. Каждый бит принятый при активном сигнале TSOP сохраняется в массиве. А каждое значение длинны паузы проверяется на соответствие и в случае превышения длинны паузы фиксируется битый пакет. Отработка конца передачи производится в основном цикле программы по обычному таймауту. 0,035 сек примерно
Код:
if (CCP1IF)
{
CCP_buf = CCPR1; // save CCPR1
CCP1IF = 0; // clear interrupt flag
TMR1 = 0x0000; // clear TMR1
if (CCP1M0) // if last interrupt on rising
{
T1GINV = 1; // rising count enable
CCP1M0 = 0; // next interrupt on falling
}
else
{
T1GINV = 0; // falling count enable
CCP1M0 = 1; // next interrupt on rising
}
// bit receive handler
if (RX_START)
{
if (!CCP1M0) // after each rising edge
{
_input[packet_counter] = CCP_buf; // recieve bit without encoding
packet_counter ++; // increment bit counter
}
// error recieving handler
if (CCP1M0 && CCP_buf > 1300 || CCP_buf <1100) // if bit too long or too short, then error
{
RX_START = 0; // stop recieve
RX_END = 0; // clear flags
packet_counter = 0; // and counters
}
}
// start bit handler
if (RX_START == 0 && CCP1M0 == 0 && CCP_buf > 4700 && CCP_buf < 4900) // start packet receiving if header detect
{
RX_START = 1; // detect start bit
}
}
в код основного цикла пишем то что ниже, для отработки конца пакета
Код:
while (1)
{
// end of packet handler
if (TMR1IF) EndOfPacketHndl();
}
// end of packet handler
void EndOfPacketHndl(void)
{
TMR1IF = 0; // clear interrupt flag
T1GINV = 0; // switch count on falling
TMR1 = 0x0000; // clear Timer 1
CCP1M0 = 0; // reset next interrupt on falling
if (packet_counter > 10) // packet received succsessful
{
RX_START = 0; // reset RX flag
RX_END = 1; // set end flag
packet_counter = 0; // clear counter
}
else // packet corrupt
{
RX_START = 0; // reset RX flag
RX_END = 0; // ERROR
packet_counter = 0; // clear counter
}
}
тут я немножко упростил проверки, и битость пакета проверяется просто по длине. Врятли придет сразу 10 помех, да еще и с правильными паузами. Поэтому если пакет короче ожидаемого, то просто гасим его да и все как ошибочный.
а дальше с массивом _input[] можно делать все что угодно. Я забил на декодирование, так как мне нужен только цвет команды
все значения в массиве будут иметь размер ровно вдвое больше, чем предполагаемый бит, потому как разрешение счетчика 0,5 мкс
к примеру если нолик у нас равен по длинне 600 мс, то его значение в массиве будет примерно 1200 (плюс минус)
единичка соответственно вдвое длиннее, то есть 2400 в десятичном измерении