roboforum.ru

Технический форум по робототехнике.

как измерить длину импульсов?

Программирование микроконтроллеров AVR, PIC, ARM.
Разработка и изготовление печатных плат для модулей.

как измерить длину импульсов?

Сообщение ximik » 09 янв 2011, 18:10

Есть 2х канальная радиоаппаратура, на выходе приемника импульсы для управления сервами или регуляторами скорости.
Задача стоит в том чтобы измерить длину управляющих импульсов и интерпретировать сигналы "газ" "поворот" в сигналы для танкового привода.

Вот кусок кода для ATmega8 (кварц 16МГц)
Прерывания настроены на любое изменение состояния порта
подтягивающие резисторы на порт D включены
Код: Выделить всёРазвернуть
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
if (flag1==0) {TCNT0=0x00;
               flag1=1;
              }
else  {flag1=0;
       move1=TCNT0;   
      };

 
}

// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
// Place your code here
if (flag2==0) {TCNT0=0x00;
               flag2=1;
              }
else  {flag2=0;
       move2=TCNT0;   
      };

переменный move1 и move2 хранят длину импульсов с 2х каналов.
НО!
Программа работает но считается только длина импульса на ноге "INT0".
Считает и импульс на ноге "INT1", если отключить прерывание на INT0 и оставить только INT1.
То-есть можно сделать вывод, что импульсы начинаются одновременно.

Если пытаться "поймать" импульс в основном цыкле программы, отключив внешние прерывания
Код: Выделить всёРазвернуть
 while(flag1==0){ if(PORTD.2==1){TCNT0=0;
                                        flag1=1;
                                       };
                       }; 
                     
         while(flag1==1){ if(PORTD.2==0){move1=TCNT0;
                                        flag1=0;
                                       };
                       };               


то ничего не получается вообще(
Вот и хочу спросить каким образом можно реализовать поставленную выше задачу на ATmega8?
ximik
 
Сообщения: 28
Зарегистрирован: 13 июл 2009, 14:18
Откуда: Барнаул
прог. языки: C/C++

Re: как измерить длину импульсов?

Сообщение avr123.nm.ru » 09 янв 2011, 19:04

Если у вас 2 сигнала то используйте 2 ноги внешних прерываний но настраивайте прерывание каждый раз на то событие которое ожидаете.
Читайте !
Аватара пользователя
avr123.nm.ru
отсылающий читать курс
 
Сообщения: 14195
Зарегистрирован: 06 ноя 2005, 04:18
Откуда: Москва
Предупреждения: -8

Re: как измерить длину импульсов?

Сообщение Radist » 09 янв 2011, 20:13

Я на Сях не пишу, поэтому мой ответ будет скорее общим, чем частным. Внешние прерывания работают оба - это точно. Если они произойдут одновременно, то нулевое прерывание будет обработано первым. Но флаг срабатывания первого прерывания сбрасывает только возврат из подпрограммы прерываний. Так что даже в этом случае прерывания должны обработаться оба. В симуляторе пробовали имитировать?
Аватара пользователя
Radist
 
Сообщения: 2241
Зарегистрирован: 01 июл 2009, 08:59
Откуда: Екатеринбург
прог. языки: асемблер AVR

Re: как измерить длину импульсов?

Сообщение Duhas » 09 янв 2011, 22:30

фронт смотреть одним прерыванием, спады - двумя.. по фронту пускать таймер, и переключать режимы прерываний, по спаду - смотреть таймер и возвращать режимы
«Как сердцу выразить себя? … Мысль изреченная есть ложь!»
В этом мире меня подводит доброта и порядочность...
"двое смотрят в лужу, один видит лужу, другой отраженные в ней звезды"
Аватара пользователя
Duhas
 
Сообщения: 6338
Зарегистрирован: 15 сен 2007, 13:03
Откуда: Красноярск
прог. языки: ASM(МК), C(PC)
ФИО: Гагарский Андрей Александрович

Re: как измерить длину импульсов?

Сообщение ximik » 10 янв 2011, 14:26

Все разобрался, заработало.
В протеусе пробовал но он вообще на прерывания не реагирует(может версия карявая...)
На счет того что должны работать влюбом случае оба - да, но импульс тогда измерится не правильно.
сделал вот так
Код: Выделить всёРазвернуть
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
if (flag1==0) {TCNT0=0x00;
               flag1=1;
              }
else  {flag1=0;
       move1=TCNT0;
       GICR=0x80;
      };

 
}

// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
// Place your code here
if (flag2==0) {TCNT0=0x00;
               flag2=1;
              }
else  {flag2=0;
       move2=TCNT0;
       GICR=0x40;
      };

}

то-есть внутри первого прерывания отключаем разрешение на его срабатывание, а во втором после выполнения разрешаем, в итоге они поочереди выполняются несмотря на одновременное начало импульсов
ximik
 
Сообщения: 28
Зарегистрирован: 13 июл 2009, 14:18
Откуда: Барнаул
прог. языки: C/C++


Вернуться в Микроконтроллеры

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

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