Arduino mega PinChangeInterrupt с 16 битным таймером

Со ссылкой на этот вопрос ::Я написал программу с помощью 16-битного таймера,

Программа выглядит следующим образом .

volatile uint32_t ovfCount = 0;

struct Pulse {
  uint32_t last_toggle;
  uint32_t width;
  bool stateHigh;
  uint32_t get_width() {
    noInterrupts();
    uint32_t width_copy = width;
    interrupts();
    return width_copy;
  }
};

Pulse ch1, ch2, ch3, ch4, ch5, ch6;

void setup() {
  Serial.begin(115200);

  pinMode(13, OUTPUT);

  /*
     Pin Change Interupt for
     measuring the pulse width
     from the receiver

  */

  DDRK = 0; // A8:A15 -> направление в качестве входного сигнала
  PORTK = B00111111; // A8:A15 -> pullupResistor

  PCIFR = 0; // resetting the flags
  PCIFR  = _BV(PCIF2);
  PCMSK2 = B00111111; // активация с A8:21 :: 6
  PCICR = B00000100; // активация 2-го PCINT

  /*
     настройка 16-битного таймера для подсчета голосов
     используется таймер 3
  */
  TCCR3B = 0x00;
  TCCR3A = 0x00; // генерация волн нормальна:: все нули
  TCNT3 = 0x00;
  TIFR3 = 0x00; // сброс всех флагов
  TIMSK3 = 0x01; //включение переполнения таймера
  TCR3B = 0x01; // нет предварительного масштабирования

}


ISR(TIMER3_OVF_vect) {
  ovfCount++;
}


ISR(PCINT2_vect) {
  uint8_t tcnt3 = TCNT3;
  uint32_t ovf_count = ovfCount;

  if ( bit_is_set(TIFR3, TOV3) && tcnt3 < 32768 ) {
    ovf_count ++;
  }

  uint32_t time = ovf_count << 16 | tcnt3;

  pinChangeFunction(&ch1, time, PK0);

}


void pinChangeFunction(Pulse *channel, uint32_t time, uint8_t pin) {
  bool input_is_high = bit_is_set(PINK, pin);
  if (input_is_high && !channel->stateHigh) {
    channel->stateHigh = true;
  } else if (! input_is_high && channel->stateHigh) {
    channel->width = time - channel->last_toggle;
    channel->stateHigh = false;
  }
  channel->last_toggle = time;
}

void loop() {
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
  delay(200);

  Serial.println(ch1.get_width() / 16e3, 5);


}

Вывод для того же самого прилагается ниже,

999.42663
999.43060
999.42645
999.42614
999.42730
999.42889
1003.52416
999.41473
999.42681
999.42211
999.42077
999.42718
999.42016
1003.52447
999.41802
999.42480
999.42541
999.43603
999.42767
1003.52075
999.42199
999.42767
999.41876
999.42816
999.41143
999.41998
1003.52429
999.42730
999.42950
999.41149
999.42028
999.42700
1003.50775
999.43743
999.42858
999.42584
999.41381
999.42852
999.43347
1003.52490
999.41925
999.41540
999.42510
999.42895
999.42980
999.42883
1003.52526
999.43658
999.43707
999.42889
999.41284
999.42401
1003.52343
999.42901
999.42950
999.42822
999.43481
999.42718
999.41986
1003.52398
999.42303
999.41442
999.42498
999.42950
999.42547
1003.51074


Когда я наблюдал за выходом , то увидел 999 миллисекунд вместо 1000, как ожидалось, а в промежутке между ними 1003 миллисекунды идут вместо 999/1003.

Кроме того ,если мы внимательно посмотрим, то можно заметить, что 999 приходит 6 раз, затем один 1003 приходит и уходит 2 раза вот так, затем 5 раз 999, затем 1003

поэтому я хочу знать , какую ошибку я совершаю в своей программе и какова причина такого поведения .

, 👍1

Обсуждение

Пожалуйста, ответьте @edgar-bonet ., @Lawliet

TCNT3 не вписывается в " uint8_t`., @Edgar Bonet

Спасибо. Его работа, @Lawliet