Помогите пожалуйста определить разрядность ШИМ Arduino Mega 2560

Здравствуйте уважаемые специалисты. Достался мне код, который работает на Arduino Mega 2560.
Помогите пожалуйста определить с какой разрядностью работает ШИМ в этом коде.

void init() {
TCCR1B = 0x00;  //Disbale Timer1 while we set it up
  TCNT1 = 0;      //Reset Timer Count

  TCCR1A = 0x00;  //Timer1 Control Reg A: Wave Gen Mode normal (Simply counts up from 0 to 65535 (16-bit int)

  // Эта команда настраивает регистр TCCR1B (регистр управления таймером 1) для работы в режиме счетчика с частотой внутреннего тактового сигнала, деленного на 8.
  TCCR1B = 0x02;  // задание делителя частоты: коэффициент 8 // частота почти в 8 раз меньше ~1.5Кгц

  // Эта команда устанавливает биты OCF1A, OCF1B, OCF1C, TOV1 и ICF1 в регистре TIFR1 (регистр флагов таймера 1), что приводит к сбросу соответствующих флагов прерываний таймера 1.
  TIFR1 = (1 << OCF1A) | (1 << OCF1B) | (1 << OCF1C) | (1 << TOV1) | (1 << ICF1);  //Clear the compare flags, overflow flag and external input flag bits

  // Эта команда устанавливает значение регистра OCR1A (регистр сравнения таймера 1) равным 1.
  // Это означает, что при достижении таймером 1 значения 1 произойдет событие сравнения, которое может быть использовано для генерации прерывания или других действий.
  OCR1A = 1;
  
  // Эта команда устанавливает бит OCIE1A (разрешение прерывания по сравнению с регистром OCR1A) в регистре TIMSK1 (регистр управления прерываниями таймера 1)
  // путем установки соответствующего бита в единицу. Это позволяет генерировать прерывание при достижении значения OCR1A таймером 1.
  TIMSK1 |= (1 << OCIE1A);  //Turn on the compare unit (ie turn on the interrupt)

  OCR1B = 1;
  TIMSK1 |= (1 << OCIE1B);  //Turn on the compare unit (ie turn on the interrupt)

  OCR1C = 1;
  TIMSK1 |= (1 << OCIE1C);  //Turn on the compare unit (ie turn on the interrupt

}

// обработчик прерывания по совпадению значения таймера со значением регистра OCR1A
ISR(TIMER1_COMPA_vect) {
  //compare_cntr0 += 1;

  if (TCNT1 >= 2000) {

    // AT_solenoid_2_3
    if (currentStatus.at_solenoid_pwm_value[3] > 0) digitalWrite(at_solenoid_pin[3], HIGH);  // AT_solenoid_2_3
    else digitalWrite(at_solenoid_pin[3], LOW);

    // AT_solenoid_3_4
    if (currentStatus.at_solenoid_pwm_value[4] > 0) digitalWrite(at_solenoid_pin[4], HIGH);  // AT_solenoid_3_4
    else digitalWrite(at_solenoid_pin[4], LOW);

    // AT_solenoid_lockup
    if (currentStatus.at_solenoid_pwm_value[5] > 0) digitalWrite(at_solenoid_pin[5], HIGH);  // AT_solenoid_lockup
    else digitalWrite(at_solenoid_pin[5], LOW);

    //digitalWrite( at_solenoid_pin[3], HIGH );
    //digitalWrite( at_solenoid_pin[4], HIGH );
    //digitalWrite( at_solenoid_pin[5], HIGH );

    //noInterrupts();
    OCR1A = max(1, currentStatus.at_solenoid_pwm_value[3] * 2);  // pin_AT_solenoid_2_3
    OCR1B = max(1, currentStatus.at_solenoid_pwm_value[4] * 2);  // pin_AT_solenoid_3_4
    OCR1C = max(1, currentStatus.at_solenoid_pwm_value[5] * 2);  // AT_solenoid_lockup // третий выход таймера 1

    TCNT1 = 0;
    //interrupts();

  } else {
    if (currentStatus.at_solenoid_pwm_value[3] < TIMER_PWM_CUT_MAX_VALUE)  // pin_AT_solenoid_2_3
      digitalWrite(at_solenoid_pin[3], LOW);
    OCR1A = 2000;
  }
}

ISR(TIMER1_COMPB_vect) {
  //compare_cntr1 += 1;

  if (currentStatus.at_solenoid_pwm_value[4] < TIMER_PWM_CUT_MAX_VALUE)  // // pin_AT_solenoid_3_4
    digitalWrite(at_solenoid_pin[4], LOW);
}

ISR(TIMER1_COMPC_vect) {
  //compare_cntr2 += 1;

  if (currentStatus.at_solenoid_pwm_value[5] < TIMER_PWM_CUT_MAX_VALUE)  // // AT_solenoid_lockup
    digitalWrite(at_solenoid_pin[5], LOW);
}

В этом коде нет ШИМ (аппаратного) вообще. Таймер работает в режиме обычного счетчика

(исправлено -добавлено уточнение про ШИМ)

1 лайк

Спасибо. Но теперь я окончательно запутался )))
Насколько я понимаю счетчик идет от нуля до 2000. Верно ?

Вы бы код целиком выложили.
У вас тут программный ШИМ в прерываниях таймера.

@MaxAlex а что нужно-то? Если Вам просто нужен ШИМ нестандартного разрешения (не 8 бит, а 10 или там 12), то это проще сделать самому в несколько строк. Вот в этой теме готовый пример для Uno/Nano, но идея там понятна и для Mega переделать несложно (если вообще что-то надо переделывать).

Мне как раз нужно выяснить разрядность этого ШИМ, что бы перейти на ШИМ 12 бит. Естественно переделав процедуры, которые задают ШИМ с той разрядностью, которая сейчас, на 12 бит.

Каким образом знание параметров кода на выброс тебе поможет?

Весь код очень огромный, но сводится к расчету значений ШИМ

currentStatus.at_solenoid_pwm_value[0]
........
currentStatus.at_solenoid_pwm_value[5]

в зависимости от внешних условий.

разрядность программного ШИМ в этом коде… примерно 11 бит. Максимальное значение счетчика таймера 2000

1 лайк

Спасибо огромное. Именно это мне и было нужно знать.

Дисклаймер - нет уверенности в правильности, так как код неполный.Например, непонятно что такое

TIMER_PWM_CUT_MAX_VALUE

А что мешало самому посчитать ?
Тупо , сколько раз нужно 1, умножать на 2, что бы результат стал больше 2000…

Незнание именно этого. Меня регистры в страх вводят.

Ну двоичное счисление в той же педивикии вполне понятно описано

такие вещи не считать надо, а на память помнить :slight_smile:

Ну вот у меня под такие вещи в голове лишней оперативы нет , а калькулятор (и обычный и программистский) всегда рядом.
А в голове степени двойки до 255 включительно. Остальное считаю путем дальнейшего умножения.

я аналогично поступаю 10 бит 1024, 11 бит 2048, 12 бит 4096 )))

TIMER_PWM_CUT_MAX_VALUE = 900; 

И вот я все равно запутался. В одном месте считаем до 2000, в другом до 900.

А что делает вот эта операция?

OCR1A = max(1, currentStatus.at_solenoid_pwm_value[3] * 2);

Задает скважность(или коэффициент заполнения), в общем не суть , смысл понятен

Учитывая, что 255 не является степенью двойки, единственная возможная интерпретация этого утверждения:
2^255 примерно равно 5,7896044618658097711785492504344e+76.
Я могу такое только при помощи калькулятора (как вариант: ПК + Си/Паскаль/Фортран/…)
… Белая зависть …