Прерывание по переполнению таймера срабатывает и по переполнению и по достижении половины

не понял. если речь о том чтобы программа считала как надо, то вопрос не в этом. я в 28 стоке изменил 16 на 15 и все считает как мне надо. мне просто охота понять почему так происходит.

Так вроде так и есть, в обработчике он уже с нуля тикать начинает…

не, мне кажется там все верно. Он по первому фронту сбрасывает TCNT1 на ноль, а по второму считывает значение - это автоматически получается разница между фронтами

А вот где, как мне кажется, есть “дыра” -

 if (!Start)
  {
    TCNT1 = 0;
    Start = 1;
  }

это то что он при приходе первого импульса обнуляет только счетчик таймера, а счетчик прерываний нет. А ведь счетчик прерывания к этому моменту может быть не нулем.

1 лайк

ну в классическом варианте да, но я попробовал по первому фронту просто обнулять таймер и ничего не изменилось, но упростилось.

согласен, но на поставленный вопрос не отвечает. и по теории вероятностей на работу устройства практически не влияет.

если у вас реально происходит прерывание на 32767 - это не должно было помочь.

Смотрите, при сдвиге на 16 бит у вас после 32767 шло 98304 = (32768 + 65536)
Если вы меняете на 15 бит - у вас все равно не будет плавного набора цифр - после 32767 будет идти 65536

то есть вы понимаете, что это косяк - но исправлять не будете? Тогда зачем мы тут время теряем?
Спокойной ночи всем

я подумал, что кому-то, как и мне, будет интересно понять, почему так происходит.

Думаю нет. 32769 логически сложится с 32768 и получится 32769.

Почему не буду. Конечно добавлю обнуление счетчика прерываний.

Уточните логику работы расходомера, а то здесь противоречие - в первой строке импульс константа, а во второй уже нет
P.S. То есть, если вычисляем период, значит один импульс не может означать постоянный расход воды.

Это да, но нарушается отсчёт по переполнению.

Возможно, здесь не нужно два прерывания, достаточен один захват.

Это как так? А сдвиг << 16?

P.S. К b707: не обращайте внимание, похоже выше глупость написал

определяя длину периода импульса определяется за сколько времени пройдет 2,442 Е-2 литра отсюда вычисляется расход.

это здесь 16 и считает не правильно, а я изменил на 15 и считает как мне надо.

Так что, вопрос решён?

вопрос не в этом, а в том, почему счетчик переполнений считается в 2 раз быстрее чем должен.

вопрос не практический

Это не так. Допишите два массива, как у меня в примере, и убедитесь, что счётчик работает верно.
Вы выводите на экран расчётное значение, а не реальное

это когда прерываний нет. Завтра верне сегодня попробую в работе с сигналом.

Так и не смог понять, зачем вообще прерывание по переполнению.

Спойлер
//сигнал поступает на пин8,считается длина периода, по нему вычисляется расход воды в л/мин.


volatile bool Start = 0;

//======
volatile uint16_t CAPT = 0;
volatile uint16_t saveCAPT = 0;
volatile uint16_t PeriodCAPT = 1;


ISR(TIMER1_CAPT_vect)
{
  if (!Start)
  {
    saveCAPT = ICR1;
    Start = 1;
  }
  else
  {
    CAPT = ICR1;
    PeriodCAPT = CAPT - saveCAPT;
    Start = 0;
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(8, INPUT);
  cli();
  TCCR1A = 0; TCCR1B |= B11000011;  //шумоподавитель вкл, передний фронт вкл, прескалер =64
  TIMSK1 |= B00100000; // B00100001 вкл прерывания /*по переполнению и*/ захвату
  sei();
}
//==================

// 16/64 = 0.25MHz; 1такт таймера = 4мкс; 


void loop() { 
  TIMSK1 = 0;
  Serial.print("Per = ");
  Serial.print( PeriodCAPT * 4);
  Serial.println(" us");
  Serial.println();
  Serial.print("Fr = ");
  Serial.print(1.0/(PeriodCAPT * 4.0/1000));
  Serial.println(" kHz");
  Serial.println();
  TIMSK1 |= B00100000;
  delay(1000);

}
Спойлер

Screenshot_92

Спойлер

Screenshot_93

Прерывание по переполнению для того чтобы диапазон расширить. но вопрос не в этом. Еще раз повторяю, вопрос не практический, а скорее академический. Сделать простую программу для расчета не проблема. Вопрос почему программа ведет себя так, как будто прерывание по переполнению срабатывает не там где надо. Я понимаю что то, что я написал в заголовке теоретически невозможно, иначе бы об этом уже тысячи раз везде написали. Мне (в данном случае) не интересно написать другую программу, а интересно понять почему эта программа ведет себя так.