Страница 2 из 2

Re: Захват импульсного сигнала с определением времени следов

Добавлено: Ср июл 28, 2010 22:28:16
ВитГо
а я вот смотрю на ETIMSK и думаю а почему там не ноль?

сейчас проверю свою догадку !

Re: Захват импульсного сигнала с определением времени следов

Добавлено: Ср июл 28, 2010 22:32:03
ВитГо
все вопрос по зависанию снят !!!

ETIMSK должен быть равен нулю ! а там было 0х10 - то есть прерывание по переполнению timer3 - вот и был вис !

Re: Захват импульсного сигнала с определением времени следов

Добавлено: Ср июл 28, 2010 22:37:17
Елисей
Ура))) теперь ждем результата по отсчитыванию длинны импульса.

Re: Захват импульсного сигнала с определением времени следов

Добавлено: Ср июл 28, 2010 23:20:48
ВитГо
а как задается приоритет прерываний?

что более приоритетно timer1 или внешнее прерывание int7 ?

Re: Захват импульсного сигнала с определением времени следов

Добавлено: Ср июл 28, 2010 23:29:19
Елисей
никак не задается. что первое сработает то и будет выполняться. во время обработки одного прерывания, все остальные на это время запрещаются. так чтоб оба сразу - какая то невероятная ситуация, хотя самому интересно что будет.

Re: Захват импульсного сигнала с определением времени следов

Добавлено: Пн авг 02, 2010 10:05:47
ВитГо
запрещаются автоматом или я вначале обработчика прерывания должен cli поставить ?

Re: Захват импульсного сигнала с определением времени следов

Добавлено: Вт авг 03, 2010 22:49:15
ВитГо
докладываю о своих экспериментах

реализовываю следующий алгоритм:

запустил таймер3 на счет со скоростью 2 мгц...

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

// Timer/Counter 3 initialization   - генератор для отсчета микросекунд для захвата PPM
// Clock source: System Clock
// Clock value: 2000,000 kHz
// Mode: Normal top=FFFFh
// Noise Canceler: Off
// Input Capture on Falling Edge
// OC3A output: Discon.
// OC3B output: Discon.
// OC3C output: Discon.
// Timer 3 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
// Compare C Match Interrupt: Off
TCCR3A=0x00;
TCCR3B=0x02;
TCNT3H=0x00;
TCNT3L=0x00;
ICR3H=0x00;
ICR3L=0x00;
OCR3AH=0x00;
OCR3AL=0x00;
OCR3BH=0x00;
OCR3BL=0x00;
OCR3CH=0x00;
OCR3CL=0x00;
далее сконфигурировал вход на генерацию прерывания по любому изменению на нем

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

    PORTG=0b00010000; // включаем прерывание на захват
    EICRA=0x00; // любое изменение сигнала
    EICRB=0x40;
    EIMSK=0x80;
    EIFR=0x80;
после этого вся работа идет в обработчике прерывания
// External Interrupt 7 service routine
// Прерывание в котором осуществляется захват PPM с тренерского разъема
unsigned char cap_step; // фаза захвата
unsigned int f1,f2; // длительности захваченных импульсов
unsigned char cap_ch; // номер захватываемого канала
unsigned int TCAP_PPM[8]; // временные значения захваченных каналов - не проверенные

interrupt [EXT_INT7] void ext_int7_isr(void) {

#asm("cli")

f1=(TCNT3H*256+TCNT3L)/2; // отсчитаем длительность импульса

// вариант 1

if ( (f1>30) && (f1<500)) { // изменение уровня произошло от 50 до 300 мкс от предыдущего

мы получили длительность импульса "=" за ним идет пауза - то есть импульс имеет вид "=__"
если мы получили такой импульс-то все в порядке, к его длительности нужно прибавить
значение паузы до следующего импульса

мы не обнуляем счетчик TCNT3 - так как нам понадобиться длительность и импульса и паузы

}

else

// если изменение уровня произошло в большее время от 700 до 2400 - то мы получили
// значение канала равно длина импульса + длина паузы "=____"

if ( (f1>700) && (f1<2400) ) { // это канальный импульс ?

TCNT3H=0; TCNT3L=0; // сбрасываем счетчик - для подсчета длительности следующего канала

// каналов не может быть больше 8 - поэтому сохраняем только 8 и потом не сохраняем потому что пакет ошибочен если каналов больше 8

if (cap_ch<8) {
f2=f2+f1; // считаем общую длительность пачки импульсов
TCAP_PPM[cap_ch]=f1; // сохраняем длительность канала во временном массиве
}
cap_ch++; // увеличиваем счетчик каналов
}

else

// если импульс + пауза длятся более 3000 мкс - то это уже не канал а пауза между пачками каналов "=_____________"

if (f1>3000) { // это пауза между пачками ?

TCNT3H=0; TCNT3L=0; // сбрасываем счетчик - теперь идет канал-1 следующей пачки

сумма длительностей импульсов + длительность паузы не должны быть более 23 мс (23000 мкс)
if ((f2+f1)<23000) { // если пачка правильная по длительности то выводим ее

for (cap_ch=0;cap_ch<8;cap_ch++) CAP_PPM[cap_ch]=TCAP_PPM[cap_ch];
массив CAP_PPM - это как раз выход захваченных импульсов
}
else // иначе обнуляем временный массив длительностей каналов
for (cap_ch=0;cap_ch<8;cap_ch++) TCAP_PPM[cap_ch]=0;

f2=0; // обнуляем сумму длительностей всех каналов

cap_ch=0; // считываем каналы с начала
}

#asm("sei")
}
все вроде правильно.. но вот незадача- это прерывание должно работать параллельно с другим прерыванием... причем более тяжеловесным и занимающим больше процессорного времени..
мне нужно обеспечить приоритетность этого прерывания, чтобы захват импульсов происходил даже из процедуры другого прерывания...
это возможно?

Re: Захват импульсного сигнала с определением времени следов

Добавлено: Вт авг 03, 2010 23:00:04
ВитГо
выше был первый вариант процедуры захвата

второй вроде умнее.. но почему то не работает
// External Interrupt 7 service routine
// Прерывание в котором осуществляется захват PPM с тренерского разъема

unsigned char cap_step; // фаза захвата
unsigned int f1,f2; // длительности захваченных импульсов
unsigned char cap_ch; // захватываемый канал
unsigned int TCAP_PPM[8]; // временные переменные захвата

interrupt [EXT_INT7] void ext_int7_isr(void) {
#asm("cli")

f1=(TCNT3H*256+TCNT3L)/2; // отсчитаем длительность импульса

switch (cap_step) {

case 0 : { // начало импульса (нарастающий фронт)
TCNT3H=0; TCNT3L=0; // сброс счетчика
cap_step=1; // ищем спадающий фронт
break;
}

case 1 : { // получаем падающий фронт

if ( (f1>30) && (f1<400) ) { // проверяем длительность импульса от 30 до 400 мкс

cap_step=2; // ждем начала следующего импульса отсчета
}
else { // если длительность импульса не правильная - то ждем следующее
изменение уровня сигнала на входе пока не получим правильную длину импульса

TCNT3H=0; TCNT3L=0; // сброс счетчика

cap_step=1; // ищем второй фронт импульса

}
break;
}

case 2 : { // получаем фронт второго импульса - между первым фронтом первого импульса и первым фронтом второго импульса - промежуток времени показывает нам значение канала или указывает на паузу

TCNT3H=0; TCNT3L=0; // сброс счетчика для подсчета следующего канала

// если длительность от 750 до 2400 мкс - значит это канал !

if ( (f1>750) && (f1<2400) ) { // у нас считан канал

if (cap_ch<8) { // если каналов не больше 8 - значит все ОК, сохраняем
f2=f2+f1;
TCAP_PPM[cap_ch]=f1; // сохраняем длительность канала
}
cap_ch++; // увеличиваем номер канала для ожидания
cap_step=1; // ждем второй фронт импульса
}
else {

if (f1>3000) { // у нас считана межканальная пауза

TCNT3H=0; TCNT3L=0; // сбрасываем счетчик

if ((f2+f1)<23000) { // если пачка правильная по длительности то выводим ее
for (cap_ch=0;cap_ch<8;cap_ch++) CAP_PPM[cap_ch]=TCAP_PPM[cap_ch];
} else for (cap_ch=0;cap_ch<8;cap_ch++) TCAP_PPM[cap_ch]=0;
f2=0;
cap_ch=0; // считываем каналы с начала
cap_step=1;
}
}
break;
}
default : { cap_step=0; }
}
этот код не работает. хотя вроде как правильный.. и должен синхронизироваться сам по сигналу (шаг 1) и потом работать....

Re: Захват импульсного сигнала с определением времени следов

Добавлено: Ср авг 04, 2010 17:01:10
ВитГо
неужели никак нельзя находясь в одном прерывании разрешить другие ?