Примеры с сайта AVR+ Electronics - RC5 декодер на Tiny2313.

Автор: Internet. Posted in Початківцям з CV AVR

Зміст статті

    RC5 декодер на Tiny2313.

Сегодня разберём протокол RC5. В протоколе RC5, тут кодирование информации осуществляется не длительностью импульса. Такой способ кодирования информации называется еще манчестерским. RC5 посылка на выходе интегрального приёмника TSOP36 , который на выходе фильтрует несущую частоту 36кГц:


Длительность посылки в протоколе RC5 составляет - 24.9мс, а период повторения - 114мс. Посылка состоит из 14бит. Первые два бита в посылке (S1 и S2) это стартовые биты они всегда должны быть равны 1. Третий бит (Т) это бит триггера, он меняет состояние каждый раз, когда на пульте нажимается кнопка. Служит для отличия многократного нажатия кнопки на пульте. После бита триггера идут 5 бит адреса устройства. Далее идут 6 бит самой команды. Ну, в прочем хватит теории. Для отладки я собрал вот такое устройство, для приёма команд с пульта с протоколом RC5. Собираем такую схему.


О прошивке долго рассказывать не буду. Код написан под компилятор Code Vision AVR. В исходниках и так всё понятно. Устройство тактируется от внутреннего генератора на частоте 8мгц. При получении кода, МК выводит полученную команду на 2-х разрядный LED дисплей. Вот фото:


Исходники можно скачать тут rc5_main

Благодарности: 

Goodefine - за исходники и помощь с их переделкой.

Code
/*****************************************************
Chip type           : ATtiny2313
Clock frequency     : 8,000000 MHz
Data Stack size     : 64
*****************************************************/
#include <tiny2313.h>
#include <delay.h>
#define digit0 PORTD.0      //питание дисплея
#define digit1 PORTD.3      //питание дисплея
flash char digits[] = {     //массив с цифрами
0b01010000, //0
0b01011111, //1
0b00110010, //2
0b00010110, //3 
0b00011101, //4
0b10010100, //5
0b10010000, //6
0b01011110, //7
0b00010000, //8
0b00010100 //9
};   
char digit_out[2], cur_dig; 
//Временные пределы
#define Tmin 40 //длинный промежуток
#define Tmax 68
#define TminK 22 //короткий промежуток
#define TmaxK 34
unsigned char sct_bit = 0;      //Счетчик битов RC5
unsigned char RC5_buffer [14];  //Буфер RC5
bit centre =  0;                //Флаг центра 
bit not_korr = 0;               //Флаг попадания в промежутки
unsigned char Timer = 0;        //число в счетчике таймера
unsigned char trigger = 0;      //переменная триггера
unsigned int device = 0;        //переменная адреса ПДУ
unsigned char command = 0;      //переменная для команды
void rc5_cl_buf(void){            //очищаем буфер
  char i = 0;      
  for (i=0; i<14; i++){ RC5_buffer [i] = 0;  }
}   
void rc5_ti_stop(void){           //остановка таймера
   GIMSK |=0x00;
   TCCR0B = 0x00;
   TCNT0 = 0;
   sct_bit = 0;
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
Timer = TCNT0; //запоминаем значение счетчика   
TCNT0 = 0;     //обнуляем счетчик
not_korr = 1;                         
if(sct_bit==0){
                  TCCR0B = 0x04; //запускаем таймер  (31.250 KHz)
                  RC5_buffer [sct_bit] = !PIND.2;//записываем в эл.массива
                  sct_bit++;            //+1 к счётчику принятых битов
                  centre = 1;           
        }else{
                  if ((Timer>TminK)&&(Timer<tmaxk)){ <span="" data-mce-bogus="1" class="mceItemHidden mceItemNbsp">  // проверка короткого промежутка
                                                  if (centre) {
                                                              centre = 0;
                                                              not_korr = 0; 
                                                  }else{
                                                              centre = 1;
                                                              RC5_buffer [sct_bit] = !PIND.2;
                                                              sct_bit++;
                                                              not_korr=0;
                                                  };
                  }; 
                  if ((Timer>Tmin)&&(Timer
                                                  RC5_buffer [sct_bit] = !PIND.2;
                                                  sct_bit++;
                                                  not_korr = 0;
                  };                               
                  if (not_korr == 1) {             // если не попали ни в один из промежутков то  
                                       rc5_ti_stop();   //останавливаем таймер
                                       rc5_cl_buf();    //очищаем буфер
                  };
                  if (sct_bit == 14){        // если бит последний то 
                    rc5_ti_stop();   //останавливаем таймер
                     
                    trigger = RC5_buffer [2];  //формируем переменную триггера 
                   
                    device = (RC5_buffer [3] << 4) |(RC5_buffer [4] << 3) |(RC5_buffer [5] << 2) |(RC5_buffer [6] << 1) |RC5_buffer [7];                                    //формируем адрес ПДУ                
                    command = (RC5_buffer [8] << 5) |(RC5_buffer [9] << 4) |(RC5_buffer [10] << 3 ) |(RC5_buffer [11] << 2) |(RC5_buffer [12] << 1) |RC5_buffer [13];        //формируем команду
                    
                    //выводим данные на дисплей   
                    digit_out[0]=command%10;   //перевод для 1 цифры
                    command=command/10;                //подготовка 
                    digit_out[1]=command%10;   //перевод для 2 цифры 
       
                    EIFR=0x40;   // сбрасываем флаг прерывания по входу INT0
                       };                                                                         
        };    
}
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{   
rc5_ti_stop();        //останавливаем таймер
rc5_cl_buf();        //очищаем буфер
GIMSK |=0x40; //разрешаем прерывания по входу
EIFR=0x40;  //сбрасываем флаг прерывания (если произошло)
//динамическая индикация
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
PORTB=0xFF;                   //чтобы небыло тени
switch (cur_dig)                             //---
{   
case 0:{digit1=0;digit0=1;break;};  //подаём питание на 1
case 1:{digit0=0;digit1=1;break;};  //подаём питание на 2
}                          
PORTB=digits[digit_out[cur_dig]]; 
cur_dig++;                        
if (cur_dig==2) cur_dig=0;
}
void main(void)
{
// Port A initialization
PORTA=0x00;
DDRA=0x00;
// Port B initialization
PORTB=0x00;
DDRB=0xFF;
// Port D initialization
PORTD=0x04;
DDRD=0x0B;
// Timer/Counter 0 initialization
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
TCCR1A=0x00;
TCCR1B=0x01;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Any change
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
GIMSK=0x40;
MCUCR=0x01;
EIFR=0x40;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x82;
// Global enable interrupts
#asm("sei")
while (1)
      {
      };
}