[?] RC5+mega БЕЗ внешнего прерывания?

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить
Johnson
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт мар 05, 2009 08:15:25
Контактная информация:

[?] RC5+mega БЕЗ внешнего прерывания?

Сообщение Johnson »

Здравствуйте, премногоуважаемые коты!

Без предисловий к делу: нужна Ваша помощь.

Дано: от одного самого умного инженера досталась плата на меге с ик-приемником (TSOP-31236) и кучей обвеса.
Сей премудрый инженер умудрился повесить приемник НЕ на внешнее прерывание, а на ногу PB.0
Программист написал под это дело программу, работает. Пришло время править код - у программиста аврал, не до того. Запрягли самого близко знакомого с мегами :)
Плата находится в массовом производстве, исправлять трассировку - нельзя.

Начал практиччески с нуля вспоминать си и меги в частности... Сам работаю для удовольствия в джаве.
Для лучшего понимания начал писать программу с нуля, а не перепиливать имеющуюся...

Итак...
Частота процессора 11059200 гц. Соответствующая константа FCLK наличествует в заголовке основого файла, и в проекте указана (CodeVision).

Есть старый код обработки данных:

Код: Выделить всё

//#define DivOvfTC2 37 // Константа выверена для FCLK=11059200 уточнена для FCLK=16MHz
//#define DivOvfTC2 (FCLK/296296) // 37 для FCLK=11059200
#define DivOvfTC2   (FCLK/291031) // 38 для FCLK=11059200

unsigned char cntOvfTC2=0,rc5command;
unsigned char RC5cnt14=0,RC5prev1=0x1,RC5prev2=0x1;
unsigned int RC5code=0xFFFF,RC5temp=0xFFFF,RC5delay=0;

// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void){
   unsigned char RC5tek;
   cntOvfTC2++;
   if (cntOvfTC2>=DivOvfTC2){
      // Константа DivOvfTC2 выверена для кварца на 11059200 МГц... (определена в RC5_T2.h)
      RC5delay++;
      if (RC5delay>562){
         RC5tek=PINRC5 & (1<<DD_RC5);
         if ((RC5tek==0) || (RC5prev1==0) || (RC5prev2==0)){
            RC5cnt14++;
            if ((RC5cnt14 & 1)==0){ // Есть очередной разряд
               RC5temp<<=1;  // Накопление результата
               if (RC5prev1==0) RC5temp|=1;
            }
            if ((RC5cnt14==28) && ((RC5temp & 0xF0)!=0xF0)){
               RC5code=RC5temp;
               RC5delay=0;
               rc5command=RC5code&0x3F;
            }
            RC5prev2=RC5prev1; RC5prev1=RC5tek;
         }else{
            RC5cnt14=0; RC5temp=0x00;
         }
      }
      cntOvfTC2=0;
   }
}


Далее в основном цикле программы опрашиваются переменные и выводится полученная команда на экран:

Код: Выделить всё

        if (RC5code != 0xFFFF){
            clearBuffer();
            flushBuffer();
            delay_ms(100);
               
            putNumberIntoBuffer(0,rc5command,4);
       
            RC5code=0xFFFF; // Нажатие кнопки ПДУ отработано...
            flushBuffer();   
        }


Но, работает это дело очень криво: часть кнопок не работает. Если сработало - выдает не всегда одинаковый код на дисплей.

Есть ли у кого-нибудь опыт "разборок" с RC5 без внешнего прерывания, чисто по таймерам?
Буду очень благодарен за помощь!
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Re: [?] RC5+mega БЕЗ внешнего прерывания?

Сообщение zero648 »

Сей премудрый инженер умудрился повесить приемник НЕ на внешнее прерывание, а на ногу PB.0

Какой камень, может на PB0 имеется всетаки какое прерывание? Обязательно INTn использовать чтоли, можно любой вектор использовать, а событие обрабатывать уже как угодно.
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: [?] RC5+mega БЕЗ внешнего прерывания?

Сообщение shads »

Сей премудрый инженер умудрился повесить приемник НЕ на внешнее прерывание, а на ногу PB.0
Я тоже делал декодирование не по внешнему прерыванию, все отлично работает (мне даже больше нравится такой вариант чем по внешнему прерыванию), просто настраиваеш таймер счетчик на частоту в 10 раз больше чем частота RC5 и в каждом прерывании анализируеш состояние линии.....
Johnson
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт мар 05, 2009 08:15:25
Контактная информация:

Re: [?] RC5+mega БЕЗ внешнего прерывания?

Сообщение Johnson »

Камень AtMega8, там нет вектора...

По поводу частоты - можете пример дать рассчета или Вашего кода? Частоту нашего камня я писал в первом посте...
polyname
Прорезались зубы
Сообщения: 249
Зарегистрирован: Пт май 18, 2012 23:12:23

Re: [?] RC5+mega БЕЗ внешнего прерывания?

Сообщение polyname »

программній прием одним таймером, частота опроса желательно >5кГц:
http://we.easyelectronics.ru/reptile/bi ... ik-du.html
Аватара пользователя
blackx
Говорящий с текстолитом
Сообщения: 1518
Зарегистрирован: Пт дек 28, 2012 21:56:46
Откуда: St. Petersburg

Re: [?] RC5+mega БЕЗ внешнего прерывания?

Сообщение blackx »

Johnson писал(а):Камень AtMega8, там нет вектора....

Почему? В меге 8 есть поддержка внешнего прерывания (ноги PD2 и PD3).

Если вы имели ввиду конкретно пин PB0, то по нему тоже можно прерывание сгенерить. Его альтернативная функция - ICP1 - Input Capture Pin 1.

Atmel datashit писал(а):When a change of the logic level (an event) occurs on the Input Capture Pin (ICP1), alternatively
on the Analog Comparator Output (ACO), and this change confirms to the setting of the edge
detector, a capture will be triggered. When a capture is triggered, the 16-bit value of the counter
(TCNT1) is written to the Input Capture Register (ICR1). The Input Capture Flag (ICF1) is set at
the same system clock as the TCNT1 value is copied into ICR1 Register. If enabled (TICIE1 =
1), the Input Capture Flag generates an Input Capture interrupt. The ICF1 Flag is automatically
cleared when the interrupt is executed. Alternatively the ICF1 Flag can be cleared by software
by writing a logical one to its I/O bit location.


При изменении уровня на ноге происходит копирование значения TCNT1 в регистр ICR1, одновмеренно устанавливается флаг ICF1, и если TICIE1 = 1 то генерируется прерывание.

В сообщении ниже также уже ответили, собственно :)
Последний раз редактировалось blackx Пн фев 18, 2013 11:39:24, всего редактировалось 2 раза.
Изображение only pure true norwegian blackx Изображение
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Re: [?] RC5+mega БЕЗ внешнего прерывания?

Сообщение zero648 »

Johnson писал(а):Камень AtMega8, там нет вектора...

Как нет, а ICP1 чем не вектор, возможно через него все и работает.
Johnson
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт мар 05, 2009 08:15:25
Контактная информация:

Re: [?] RC5+mega БЕЗ внешнего прерывания?

Сообщение Johnson »

Спасибо за ответы!
Порылся в коде - нет, этот вектор не используется.

Всё, что связано с ремоутом - только в прерывании таймера.
Предполагаю, что проблема в таймингах, попробую методом тыка "поймать" нужный.

Хотя тут немного не понимаю, таймер настроил в точности как в существующем проекте, код использовал тот же, а результат разный...

Про прерывание ICP1 - можете пример показать, как настроить его и использовать для этих целей?


PS: Про отсутствие векторов - имел в виду именно эту ногу. Про вектор ICP1 не слышал раньше...

polyname, спасибо большое за код! Буду разбираться и кастрировать его под конкретный пульт! :)
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Re: [?] RC5+mega БЕЗ внешнего прерывания?

Сообщение zero648 »

На асме настраивается так:

cbi DDRB, 0
.......
ldi r16, (1<<TICIE1)
out TIMSK, r16 ; Включаем вектор TIMER1 CAPT
in r16, TIFR
out TIFR, r16
sei
.........

MAIN_loop:
rjmp MAIN_loop ; Go again

TMR1_ICP:
.....
reti


P.S. еще подтяжку забыл: sbi PORTB,0
Johnson
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт мар 05, 2009 08:15:25
Контактная информация:

Re: [?] RC5+mega БЕЗ внешнего прерывания?

Сообщение Johnson »

Блин, весь мозг себе сломал с этим капчером.

Есть у кого-нибудь соображения, как с его помощью читать команду с RC5?
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: [?] RC5+mega БЕЗ внешнего прерывания?

Сообщение shads »

Вечером соображу, поделюсь.....
Johnson
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт мар 05, 2009 08:15:25
Контактная информация:

Re: [?] RC5+mega БЕЗ внешнего прерывания?

Сообщение Johnson »

Вообщем, нашел исходник, слегка переделал его на прерывание ICP1...
Работает даже более, чем идеально: команды посылаются каждые 114мс, и слишком часто обрабатываются нажатия.

Пока решил эту проблему простым таймаутом, но хотелось бы более правильно: обработкой третьего бита команды.

Полностью "переварить" код пока не могу, прощу помощи.

Итак, код, который работает:

Код: Выделить всё

unsigned char rc5command,rc5temp1,rc5temp2;
unsigned int rc5time,rc5data;

#define rc5_max 1400
#define rc5_min 900

void rc5init(){
   TCCR1A = 0;TCCR1B = 1<<CS11|1<<ICNC1;
   TCNT1H = 0;TCNT1L = 0;
   OCR1AH = 0X0B;OCR1AL = 0XB8;
   ICR1H = 0;ICR1L = 0;
   TIFR = 1<<ICF1|1<<OCIE1A;
   TIMSK |= 1<<TICIE1|1<<OCIE1A;
   rc5temp1=0;
    rc5temp2=0;
    rc5data=0;
}

void rc5_recive_bit(void){
   if (rc5temp1 == 0x00){
      TCCR1B |= 1<<ICES1|1<<ICNC1;
      rc5temp1 = 0xff;
      if ((rc5time > rc5_min) && (rc5time < rc5_max)){
         rc5data = (rc5data << 1)& 0xfffe;
         ++rc5temp2;
         goto rbok;
      }
      if ((rc5time > (rc5_min*2)) && (rc5time < (rc5_max*2))){
         rc5data = (rc5data << 2)& 0xfffc;
         rc5temp2+=2;
         goto rbok;
      }
   }else{
      TCCR1B = (1<<CS11)|(1<<ICNC1);
      rc5temp1 = 0;
      if ((rc5time > rc5_min) && (rc5time < rc5_max)){
         rc5data = (rc5data << 1) | 0x0001;
         ++rc5temp2;
         if (rc5temp2 == 27){
            ++rc5temp2;
            rc5data = (rc5data << 1)& 0xfffe;
         }
         goto rbok;
      }
      if ((rc5time > (rc5_min*2)) && (rc5time < (rc5_max*2))){
         rc5data = (rc5data << 2) | 0x0003;
         rc5temp2+=2;
         if (rc5temp2 == 27){
            ++rc5temp2;
            rc5data = (rc5data << 1)& 0xfffe;
         }
         goto rbok;
      }
   }
   rc5init();
   return;
   rbok:
   TIFR = 1<<ICF1;
}

interrupt [TIM1_CAPT] void timer1_capt_isr(void){
   unsigned char templ,temph,ttst=0;
   templ= ICR1L;temph= ICR1H;
   rc5time = templ;
   rc5time = rc5time | (temph << 8);
   TCNT1H = 0;TCNT1L = 0;
   ICR1H = 0;ICR1L = 0;
   if (rc5temp2 == 0){
      TCCR1B |= (1 << ICES1)|(1<<ICNC1);
      TIFR = (1 << ICF1);
      rc5temp1 = 0xff;
      ++rc5temp2;
   }else
        rc5_recive_bit();
   
   if (rc5temp2 == 28){
      rc5command = 0;
      while (ttst != 7){
         switch (rc5data & 0x0003){
            case 0x01:   rc5temp2 = 1;break;
            case 0x02:   rc5temp2 = 0;break;
         }
         rc5command |= rc5temp2 << ttst;
         rc5data >>= 2;
         ++ttst;
      }
      rc5init();
   }
}

interrupt [TIM1_COMPA] void timer1_compa_isr(void){
    rc5init();
}


Нужно его подправить так, чтобы значение третьего бита команды сохранялось в отдельную переменную.
Буду очень благодарен за помощь!
Ответить

Вернуться в «Периферия»