Skip to main content
Arduino

Return to Question

Tweeted twitter.com/StackArduino/status/1027525413558464512
replaced http://arduino.stackexchange.com/ with https://arduino.stackexchange.com/
Source Link

This is a follow up to my previous question my previous question.

This is a follow up to my previous question.

This is a follow up to my previous question.

Post Undeleted by Tom van der Zanden
Post Deleted by Tom van der Zanden
deleted 98 characters in body
Source Link
#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
 TCCR2B |= (1 << FOC2B); // Force match
 PORTD |= (1 << PD3); // Output high
 TCCR2B |= (1 << FOC2B); // Force match again
 TCCR2A |= (1 << COM2B1); // Enable clear OC2B on match
}
void loop() {
 
}

Why does this not work the way I expect it to, and is there a way to get my desired behavior? Also, if this is not possible, what on earth is the purpose of the clear on compare match feature if you can't turn the pin on at all when using it?

I have discovered I can sort of get the behavior I want by setting COM2B0 instead of COM2B1 (toggle on match rather than clear on match) and forcing a compare match in the interrupt (toggling the pin off) so that later the "real" toggle on match will turn it off. However, this is not ideal (as if the real and forced match overlap, I would lose track of the pin's state), and I'm still wondering what the purpose of the clear on match functionality is if it just forces the pin low.

#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
 TCCR2B |= (1 << FOC2B); // Force match
 PORTD |= (1 << PD3); // Output high
 TCCR2B |= (1 << FOC2B); // Force match again
 TCCR2A |= (1 << COM2B1); // Enable clear OC2B on match
}
void loop() {
 
}

Why does this not work the way I expect it to, and is there a way to get my desired behavior? Also, if this is not possible, what on earth is the purpose of the clear on compare match feature if you can't turn the pin on at all when using it?

#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() {
 
}

Why does this not work the way I expect it to, and is there a way to get my desired behavior? Also, if this is not possible, what on earth is the purpose of the clear on compare match feature if you can't turn the pin on at all when using it?

I have discovered I can sort of get the behavior I want by setting COM2B0 instead of COM2B1 (toggle on match rather than clear on match) and forcing a compare match in the interrupt (toggling the pin off) so that later the "real" toggle on match will turn it off. However, this is not ideal (as if the real and forced match overlap, I would lose track of the pin's state), and I'm still wondering what the purpose of the clear on match functionality is if it just forces the pin low.

Source Link

Timer2 "Clear OC2B on Compare Match" not working as expected in CTC mode

This is a follow up to my previous question.

I have Timer2 in CTC mode, with TOP=OCR2A set to 150 (with a prescaler of 8, giving a 75us timing interval).

The datasheet states that setting COM2B1 to 1 in TCCR2A will "clear OC2B on compare match" (= Arduino pin D3) when you are in CTC mode.

I would like to use this functionality to get a "pwm" signal with a period of 75us, with duty cycle determined by OCR2B. I realize that this is a very convoluted way of achieving this, but eventually I want to be continually be changing OCR2B to get a (rapidly) varying duty cycle.

In the compare channel A interrupt I would like to turn D3 high, relying on the "clear on compare match" feature of channel B to turn it low a small interval later.

I have the following minimal(-ish) example:

#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
 TCCR2B |= (1 << FOC2B); // Force match
 PORTD |= (1 << PD3); // Output high
 TCCR2B |= (1 << FOC2B); // Force match again
 TCCR2A |= (1 << COM2B1); // Enable clear OC2B on match
}
void loop() {
 
}

Ideally the ISR would just consist of PORTD |= (1 << PD3); but this does not give my desired 50% duty cycle, but apparently it's impossible to write to the pin with COM2B1 enabled, so I tried various combinations of disabling it and reconnecting the pin but all I am getting is a very, very short pulse. It looks like as soon as COM2B1 is re-enabled, the pin goes low, even though a compare match on channel B should not have happened yet.

Setting COM2B0 instead of COM2B1 works as expected: the pin toggles state (but this is not what I want).

Why does this not work the way I expect it to, and is there a way to get my desired behavior? Also, if this is not possible, what on earth is the purpose of the clear on compare match feature if you can't turn the pin on at all when using it?

AltStyle によって変換されたページ (->オリジナル) /