Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: GPIO прерывания Rising/Falling edge приходят одновременно?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
evgen2
Есть дивайс для измерения температуры TMP03, с него идет ШИМ с частотой около 30 Гц.
Точнее - два дивайса. Выходы подаются на GPIO ноги, на которые можно назначить прерывания Rising/Falling edge. Микроконтроллер - lpc1768

Меряем одно время прихода Rising edge, меряем время прихода Falling edge, получаем два интервала времени, потом по формуле
Temp= CoeffSensorA + CoeffSensorB * td0 / dt1;

получаем температуру, и всё работает замечательно.

Только вот изредка меряется какая-то ерунда. Стал разбираться.

Сделал тест

Код
int TL[1000];
int TS[1000];
int tln=0;

void EINT3_IRQHandle(void)
{  int ti, v;
    static int tiold=0;
      ti = LPC_TIM1->TC;
        if((LPC_GPIOINT->IO0IntStatR &  0x00000001) || (LPC_GPIOINT->IO0IntStatF &  0x0000001)) // это ШИМ с первого TMP03
      { v = (LPC_GPIOINT->IO0IntStatR &  0x00000001) | (((LPC_GPIOINT->IO0IntStatF &  0x0000001)<<1));
        if(tln == 0)
             TL[tln] = ti;
        else
            TL[tln] = ti - tiold;
                tiold = ti;
        TS[tln] =v;  
        tln++;        
        if(tln == 1000)
           tln = 0;
                LPC_GPIOINT->IO0IntClr =0x00000001;
    }
       if((LPC_GPIOINT->IO0IntStatR &  0x00000002) || (LPC_GPIOINT->IO0IntStatF &  0x0000002)) // это ШИМ с второго TMP03
      {
          LPC_GPIOINT->IO0IntClr =0x00000002;
      }    
}


Смотрю на TS и вижу вот такое:

1
2
1
2
3 <== этого не может быть, потому что не может быть никогда
2
1
2
1

Т.е. одновременно приходит и Rising м Falling edge
причем, если смотреть на TL - никакого дребезга с небольшими временами не видно.
Одновременно Rising и Falling (3) получаются вроде бы точно вместо Rising (1), но это на небольшом интервале измерения. Причем, если Rising и Falling одновременно считать за Rising, то смотри начало - все меряется замечательно, кроме как изредка какая-то фигня. Причем эта фигня систематическая и не лечится усреднением. Связано ли это как-то с одновременным приходом Rising м Falling edge - пока неясно.
Golikov A.
а сколько времени между падающим и восходящим?
прерывание имеет же некоторую плавающую задержку, может наплывает одно на другое?

и не лучше ли это капчем таймера делать?
alexdos
Цитата(Golikov A. @ Jan 10 2014, 22:09) *
а сколько времени между падающим и восходящим?
прерывание имеет же некоторую плавающую задержку, может наплывает одно на другое?

и не лучше ли это капчем таймера делать?

Наплывать при частоте "30 Гц."
Сергей Борщ
Цитата(alexdos @ Jan 10 2014, 21:20) *
Наплывать при частоте "30 Гц."
А вдруг у него задержки в прерываниях (на пустых циклах)?
evgen2
Цитата(Сергей Борщ @ Jan 11 2014, 01:00) *
А вдруг у него задержки в прерываниях (на пустых циклах)?

если б были большие задержки, я б их увидел в массиве TL, а так идут значения типа
369699 //25=1мкс
205851
369120
204589
........
Даже если предположить, что есть какая-то наводка, типа дребезга контактов, то куда девается второй edge ?
jcxz
А где у вас чтение IOIntStatus для квитирования прерывания?

Цитата(evgen2 @ Jan 10 2014, 23:43) *
if((LPC_GPIOINT->IO0IntStatR & 0x00000001) || (LPC_GPIOINT->IO0IntStatF & 0x0000001)) // это ШИМ с первого TMP03
{ v = (LPC_GPIOINT->IO0IntStatR & 0x00000001) | (((LPC_GPIOINT->IO0IntStatF & 0x0000001)<<1));

Зачем два раза одну и ту-же операцию делать?

Цитата(evgen2 @ Jan 10 2014, 23:43) *
if((LPC_GPIOINT->IO0IntStatR & 0x00000002) || (LPC_GPIOINT->IO0IntStatF & 0x0000002)) // это ШИМ с второго TMP03

И вообще лучше однократно считать IO0IntStatR и IO0IntStatF в начале ISR, а потом работать уже с переменными в регистрах, а не читать многократно
с портов... Чтобы чудес меньше было... rolleyes.gif

Цитата(evgen2 @ Jan 10 2014, 23:43) *
if(tln == 1000)
tln = 0;

Уж не из-за этого-ли случается периодическая фигня biggrin.gif
При переходе индекса массива через 1000 у вас записывается просто ti, а иначе - разница между ti и предыдущим.
evgen2
Цитата(jcxz @ Jan 11 2014, 20:14) *
А где у вас чтение IOIntStatus для квитирования прерывания?


Чего-чего?

Цитата(jcxz @ Jan 11 2014, 20:14) *
Зачем два раза одну и ту-же операцию делать?

И вообще лучше однократно считать IO0IntStatR и IO0IntStatF в начале ISR, а потом работать уже с переменными в регистрах, а не читать многократно
с портов... Чтобы чудес меньше было... rolleyes.gif


Уж не из-за этого-ли случается периодическая фигня biggrin.gif
При переходе индекса массива через 1000 у вас записывается просто ti, а иначе - разница между ti и предыдущим.

написано ж - и тест, и времени - попой ешь
jcxz
Цитата(evgen2 @ Jan 11 2014, 22:22) *
Чего-чего?

UM откройте.

Цитата(evgen2 @ Jan 11 2014, 22:22) *
написано ж - и тест, и времени - попой ешь

тады и не удивляйтесь что и результат как из попы smile3046.gif
evgen2
Цитата(jcxz @ Jan 11 2014, 20:14) *
Уж не из-за этого-ли случается периодическая фигня biggrin.gif
При переходе индекса массива через 1000 у вас записывается просто ti, а иначе - разница между ti и предыдущим.


Ага, при переходе индекса массива внезапно выпрыгивает прерывание rolleyes.gif
Эта фигня встречается через примерно от 12 до 100 прерываний, так что там дальше не сильно влияет на размышления cranky.gif

Цитата(jcxz @ Jan 11 2014, 20:25) *
UM откройте.

и что это даст ?
Не чтение UM, а чтение информации о возможном наличии pending interrupt внутри прерывания для понимания причины появления одновременно Rizing и Falling прерывания ?
jcxz
Цитата(evgen2 @ Jan 11 2014, 22:38) *
и что это даст ?
Не чтение UM, а чтение информации о возможном наличии pending interrupt внутри прерывания для понимания причины появления одновременно Rizing и Falling прерывания ?

Я же уже сказал: чтение IOIntStatus - квитирование прерывания.
evgen2
Цитата(jcxz @ Jan 11 2014, 21:13) *
Я же уже сказал: чтение IOIntStatus - квитирование прерывания.


квитирование - техн., комп. действие по значению гл. квитировать; подтверждение приёма-передачи структурной единицы информации

ну и как это прерывание квитировать? IO0IntClr - это не квитирование?



jcxz
Просто прочитать этот регистр. Чтение его - это и есть подтверждение модулю GpioInt.
У меня были проблемы на LPC17x когда использовал GpioInt и не читал IOIntStatus в ISR.
evgen2
Цитата(jcxz @ Jan 11 2014, 22:10) *
Просто прочитать этот регистр. Чтение его - это и есть подтверждение модулю GpioInt.
У меня были проблемы на LPC17x когда использовал GpioInt и не читал IOIntStatus в ISR.


Спасибо, попробую. В понедельник.
В UM про это ничего не написано, в нарытых примерах для GPIO прерываний в LPC17xx тоже нет.
evgen2
Цитата(jcxz @ Jan 11 2014, 22:10) *
Просто прочитать этот регистр. Чтение его - это и есть подтверждение модулю GpioInt.
У меня были проблемы на LPC17x когда использовал GpioInt и не читал IOIntStatus в ISR.

попробовал - ничего не дало.
Убил всё, кроме этого прерывания - пропало. Методом последовательного включения определил, что появлется после включения I2C2Init - Initialize I2C controller as a master
Т.е. проинициализировал, ничего c I2 не делаю, прерывание I2 не появляется...
Хрень какая-то, завтра попробуем с осциллографом посмотреть что меняется после инициализации иваси.
evgen2
Пока резюме такое:

Пока не включаю I2C2 никакой потери GPIO прерываний нет

Код
void I2C2Init( void )
{
  LPC_SC->PCONP |= (1 << 26);

  /* set PIO0.10 and PIO0.11 to I2C2 SDA and SCL */
  /* function to 10 on both SDA and SCL. */
  LPC_PINCON->PINSEL0 &= ~((0x03<<20)|(0x03<<22));
  LPC_PINCON->PINSEL0 |= ((0x02<<20)|(0x02<<22));

  /*--- Clear flags ---*/
  LPC_I2C2->I2CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;    

  /*--- Reset registers ---*/
  LPC_I2C2->I2SCLL   = I2SCLL_SCLL;
  LPC_I2C2->I2SCLH   = I2SCLH_SCLH;

  /* Install interrupt handler */
  NVIC_EnableIRQ(I2C2_IRQn);

  LPC_I2C2->I2CONSET = I2CONSET_I2EN;
  return;
}


Если вызываю I2C2Init - (и чуть поработаю с I2C - один раз прочитаю коффициенты) через произвольное время (от секунд до нескольких минут) )происходит потеря прерывания GPIO с последующим коротким, порядка 0.5 мкс "вторичным" или "ложным" прерыванием.

Если при этом (после инициализации и чтения коэффициентов) поставить брейкпонт в функции прерывания I2C2_IRQn, то отладчик туда не попадает, т.е. прерывания от I2C2 никак не могут "убить" прерывания GPI.

Такое впечатление, что прерывания запрещаются каким-то внутренним резидентным процессом, который непонятно как искать и непонятно как связан с I2C
cranky.gif

KRS
Попробуйте в начале прерывания считать статусы IntStatF и IntStatR в переменные (а не постоянно читать из регистров) и сразу же очистить прерывания IoIntClr = statf | statr;
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.