asis-kbr.ru

автоматические системы и системы безопасности
Текущее время: 21 окт 2018, 08:04

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ 1 сообщение ] 
Автор Сообщение
 Заголовок сообщения: работа с ИК протоколом NEC
СообщениеДобавлено: 22 мар 2013, 03:30 
Не в сети
Администратор
Аватара пользователя

Зарегистрирован: 19 янв 2012, 12:52
Сообщения: 575
Откуда: KBR
БИБЛИОТЕКА ОБРАБОТКИ СИГНАЛА ИК ПУЛЬТА ДИСТАНЦИОННОГО УПРАВЛЕНИЯ СТАНДАРТА NEC

Код:
//***************************************************************************************************************************
//БИБЛИОТЕКА ОБРАБОТКИ СИГНАЛА ИК ПУЛЬТА ДИСТАНЦИОННОГО УПРАВЛЕНИЯ СТАНДАРТА NEC
//для частоты контроллера 8000000 Hz
//при работе IR NEC задействован таймер\счетчик T0.
//выход IR сенсора подать на внешнее прерывание INT0
//программа создана SHADS

//НАСТРОЙКА ПОРТА И ВЫВОДА IR СЕНСОРА
#define IR_NEC_PORT    PORTD
#define IR_NEC_DDR    DDRD
#define IR_NEC_Line    (1<<2)


//***************************************************************************************************************************
//переменные и флаги библиотеки
char IrNecData [4];                //массив байтов для приема данных
char IrNecCounBites;            //счетчик принятых битов данных

volatile char IrNecFlags;        //байт флагов
#define bIrNecStreamEnb    (1<<0)    /*флаг наличия запущеннного процесса приема серии*/
#define bIrNecRcvCmpltd    (1<<1)    /*флаг завершения приема данных*/
#define bIrNecTmrOvf     (1<<2)    /*флаг фиксации переполнения счетчика\таймера*/


//***************************************************************************************************************************
//инициализация работы библиотеки
void IrNecInit (void)
{
    //настройка порта
    IR_NEC_DDR &= ~IR_NEC_Line;    //линия на ввод
    IR_NEC_PORT |= IR_NEC_Line;    //включить подтяжку

    //Настройка таймера/счетчика T0
    TCCR0 = 0x05;                 //настройка тактирования T0 (0x01-clk, 0x02-clk/8, 0x03-clk/64, 0x04-clk/256, 0x05-clk/1024)    
    TIMSK |= (1<<TOIE0);        //включить прерывание по переполнению T0

    //Настройка внешнего прерывания
    GICR  |= (1<<INT0);            //включить внешнее прерывание с вывода INT0
    MCUCR |= (1<<ISC01);         //генерация прерывания по спадающему фронту 
}


//***************************************************************************************************************************
//проверка готовности данных IR NEC
//ЗНАЧЕНИЕ - результат проверки на готовность принятых данных к чтению (0x00 - данные не готовы, 0xFF - данные готовы)
//ВАЖНО!!!!! если с помощью этой функции определено что имеются поступившие данные, то следом необходимо вызвать
//функцию чтения команды IrNecCommandGet (), (или сначала IrNecDevNumGet (), а потом IrNecCommandGet ()), 
//только после этого может быть принята следующая команда.
char IrNecDataCheck (void)
{
    if (IrNecFlags & bIrNecRcvCmpltd)
        return 0xff;
    return 0x00;
}


//***************************************************************************************************************************
//чтение данных адреса IR NEC
//ЗНАЧЕНИЕ - номер адресуемого устройства.
unsigned char IrNecDevNumGet (void)
{
    volatile char* pAddr = &IrNecData[0];            //адрес байта номера устройства в буфере данных
    return *pAddr;
}


//***************************************************************************************************************************
//чтение данных команды IR NEC
//ЗНАЧЕНИЕ - принятая команда.
//ВАЖНО!!!!! также тут происходит сброс флага наличия готовых данных bIrNecRcvCmpltd,
//если с помощью функции IrNecDataCheck() определено, что данные готовы,
//то пока не будет вызвана функция IrNecCommandGet (), новые данные не будут приниматся!
unsigned char IrNecCommandGet (void)
{
    volatile char* pCommand = &IrNecData[2];        //адрес байта команды в буфере данных
    IrNecFlags &= ~bIrNecRcvCmpltd;                    //сброс флага окончания приема данных
    return *pCommand;
}


//***************************************************************************************************************************
//Внешнее прерывание INT0 (по спаду сигнала)
ISR (INT0_vect)
{
    uint8_t val = TCNT0;                            //копируем и обнуляем счетчик таймера
    TCNT0 = 0;
    char flags = IrNecFlags;                        //копия флагов из волатильной переменной (для увеличения скорости работы )
    if (flags & bIrNecRcvCmpltd)                    //если предыдущие данные не обработаны - выход
        return;                                        //флаг сбрасывается функцией забирающей данные

    //проверка на переполнение
    if (flags & bIrNecTmrOvf){                        
        flags 
&= ~(bIrNecTmrOvf | bIrNecStreamEnb);    //сбросить флаги переполнения и приема (т.е. начать с начала)
        IrNecFlags = flags;
        return;
    }

    //проверка на заголовок пакета
    if ((val > 70) && (val < 140)){                    //105 - длительность периода импульса старта (берем шире 70 - 140)
        IrNecCounBites = 0;                            //обнулить счетчик принятых битов
        flags |= bIrNecStreamEnb;                    //установить флаг приема
        IrNecFlags = flags;                
        return
;
    }    

    
//если прием активен (т.е. заголовок пакета уже был)
    if (flags & bIrNecStreamEnb){                    
    
        
//проверка на правильность длины импульса
        if ((val < 6) || (val >= 24)){                //ошибочный размер периода
            flags &= ~bIrNecStreamEnb;                //сбросить флаг приема (т.е. начать с начала)
            IrNecFlags = flags;    
            return
;
        }

        //вычисляем место в буфере, куда поместим принятый бит
        char* pIrNecData = IrNecData + (IrNecCounBites >> 3);    
        char BitNum 
= 0x80 >> (IrNecCounBites & 0x07);
        if (val >= 12)                                                
            
*pIrNecData |= BitNum;                    //принятый бит = 1 (бит = 1 если значение 12-23)    
        else
            
*pIrNecData &= ~BitNum;                    //принятый бит = 0 (бит = 0 если значение 6-11)
            
        
//проверка, принята ли вся серия IR NEC
        if (++IrNecCounBites == 32){                //приняты все 32 бита    
            if ((char)~IrNecData[0] == IrNecData[1]){        //сравниваем прямую и инверсную части адреса устройства
                if ((char)~IrNecData[2] == IrNecData[3])    //сравниваем прямую и инверсную части команды

                    //данные верны - установить флаг наличия готовых данных    
                    flags |= bIrNecRcvCmpltd;        
            
}

            flags &= ~bIrNecStreamEnb;                //сбросить флаг приема (т.е. начать с начала)
            IrNecFlags = flags;    
        
}
    }
}


//***************************************************************************************************************************
//Прерывание по переполнению T0
ISR (TIMER0_OVF_vect)
{
    IrNecFlags |= bIrNecTmrOvf;                        //флаг переполнения
}


//***************************************************************************************************************************   


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ 1 сообщение ] 

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB