Timer2 «Clear OC2B on Compare Match» работает не так, как ожидалось, в режиме CTC

Это продолжение мой предыдущий вопрос .

У меня есть Timer2 в режиме CTC, с TOP = OCR2A, установленным на 150 (с предварительным делителем 8, дающим интервал времени 75us).

В техническом описании указано, что установка COM2B1 в 1 в TCCR2A «очистит OC2B при сравнении соответствия» (= контакт Ardino D3), когда вы находитесь в режиме CTC.

Я хотел бы использовать эту функциональность, чтобы получить сигнал «pwm» с периодом 75us, причем рабочий цикл определяется OCR2B. Я понимаю, что это очень запутанный способ достижения этого, но в конечном итоге я хочу постоянно менять OCR2B, чтобы получить (быстро) меняющийся рабочий цикл.

В перерыве канала сравнения A я хотел бы включить D3 высоко, полагаясь на функцию «clear on compare match» канала B, чтобы повернуть его на небольшой промежуток позже.

У меня есть следующий минимальный (-ish) пример:

#define OCIEA 1
#define CA21 1

void setup() {
  // PD3 as output
  DDRD |= (1 << PD3);

  // Pause the timers so they sync up
  GTCCR = (1<<TSM)|(1<<PSRASY)|(1<<PSRSYNC); // Halt all timers

  // Reset timer
  TCNT2 = 0; // set timer2 to 0 (8-bit timer)

  // Enable CTC mode
  TCCR2A = (1 << WGM21); // Timer 2 in CTC (TOP = OCR2A)

  // Clear output pins on compare match
  TCCR2A |= (1 << COM2B1); // Clear OC2B on match

  // Set prescaler
  TCCR2B = (1 << CA21); // set timer 2 divisor to 8

  // Set output compare
  OCR2A = 150; // Determines TOP for Timer2

  // Determines the pulse width
  OCR2B = 75; // Timer 2 output B (controls OC2B = PD3 = D3)

  // Enable interrupts for timer 2
  TIMSK2 = (1 << OCIEA);

  // Set the timers going again
  GTCCR = 0; // release all timers
}

ISR(TIMER2_COMPA_vect)
{
  TCCR2A &= ~((1 << COM2B1) | (1 << COM2B0)); // Disable clear OC2B on match
  DDRD |= (1 << PD3); // Enable output
  PORTD |= (1 << PD3); // Output high
  TCCR2A |= (1 << COM2B1); // Enable clear OC2B on match
}

void loop() {

}

В идеале ISR будет состоять только из PORTD |= (1 << PD3);, но это не дает мой желаемый 50% -ный рабочий цикл, но, по-видимому, невозможно писать к штырю с включенным COM2B1, поэтому я попробовал различные комбинации его отключения и повторного подключения булавки, но все, что я получаю, очень короткий импульс. Похоже, что как только COM2B1 снова включается, штырь становится низким, хотя сравнение на канале B еще не должно было произойти.

Настройка COM2B0 вместо COM2B1 работает так, как ожидалось: контакт переключает состояние (но это не то, что я хочу).

Почему это не работает так, как я ожидаю, и есть ли способ добиться желаемого поведения? Кроме того, если это невозможно, то, что на самом деле является целью прозрачной функции сравнения совпадений, если вы не можете вообще отключить контакт при использовании?

Я обнаружил, что могу выбрать поведение, которое я хочу, установив COM2B0 вместо COM2B1 (переключитесь на совпадение, а не очистите его на совпадение) и выставив сравнение в прерывании (переключив вывод выводов), чтобы позже " real "toggle on match отключит его. Тем не менее, это не идеально (как будто реальное и принудительное совпадение совпадений, я потерял бы отслеживание состояния булавки), и я все еще задаюсь вопросом, для чего цель явной функциональности совпадения заключается в том, что она просто заставляет штырь низко.

3 голоса | спросил Tom van der Zanden 25 +03002016-10-25T01:00:28+03:00312016bEurope/MoscowTue, 25 Oct 2016 01:00:28 +0300 2016, 01:00:28

2 ответа


2

Режимы PWM управляют выводом на обоих концах цикла.

Точка режимов CTC заключается в том, что они управляют выводом только на одном конце счетчика, но позволяют явно управлять другим концом.

Чтобы управлять обоими концами явно, вы используете обычный режим.

Чтобы установить бит OC2B с FOC2B в TCCR2B с вашим прерыванием:

ISR(TIMER2_COMPA_vect)
{
  TCCR2A |=  (1 << COM2B0); // Set OC2B on Compare Match
  TCCR2B |=  (1 << FOC2B ); // Force Output Compare B OC2B 
  TCCR2A &= ~(1 << COM2B0); // Clear OC2B on Compare Match
}
ответил Dave X 25 +03002016-10-25T17:26:24+03:00312016bEurope/MoscowTue, 25 Oct 2016 17:26:24 +0300 2016, 17:26:24
-3
  

Arduino предварительно конфигурируется как

     

TCCR2A = (1 <WGM20);

     

TCCR2B = (1 <WGM22);

     

, таким образом,   Первоначально сбросить регистр

     
    
      

TCCR2A = 0; //сбросить регистр

             

TCCR2B = 0; //сбросить регистр

    
  
ответил Randika Jayasekara 18 J000000Wednesday18 2018, 14:03:06

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132