Is it possible to simultaneously output a clock signal and it's inverse using the timer register(s)?
I'm using the following code in arduino to output a 1MHz signal on OC1A:
//Use Timer/Counter1 to generate a 1MHz square wave on Arduino pin 9.
//J.Christensen 27Apr2012
void setup(void)
{
DDRB = _BV(DDB1); //set OC1A/PB1 as output (Arduino pin D9, DIP pin 15)
TCCR1A = _BV(COM1A0); //toggle OC1A on compare match
OCR1A = 7; //top value for counter
TCCR1B = _BV(WGM12) | _BV(CS10); //CTC mode, prescaler clock/1
}
void loop(void)
{
}
4 Answers 4
How about this?
void setup()
{
// Defining PB1 and PB2 as outputs by setting PORTB1 and PORTB2
// Setting DDB1 and DDB2
DDRB |= bit (DDB1) | bit (DDB2);
// stop timer 1
TCCR1A = 0;
TCCR1B = 0;
TCCR1A = bit (COM1B0) | bit (COM1B1) // Set OC1B on Compare Match, clear
// OC1B at BOTTOM (inverting mode)
| bit (COM1A1) // Clear OC1A on Compare Match, set
// OC1A at BOTTOM (non-inverting mode)
| bit (WGM11); // Fast PWM, top at ICR1
TCCR1B = bit (WGM12) | bit (WGM13) // ditto
| bit (CS11); // Start timer, prescaler of 8
// Initialize OCR1A = 300 (pulse_width = 150us), OCR1B, and ICR1
ICR1 = 0xFFFF;
OCR1B = 299;
OCR1A = ICR1 - OCR1B;
} // end of setup
void loop()
{
}
Results on a Uno:
Normal and inverted timer output
Output on Uno pins 9 and 10.
Change the prescalers and counters to your desired frequency.
The screenshot doesn't show one signal exactly the inverse of the other. The pattern is inverted. If you had a 50% duty cycle, it would be an exact inverse.
It looks good except they overlap (slightly) by 50ns. If I set them to 16 and 8, respectively, they don't overlap but they are slightly asymmetrical
OK, make OCR1A and OCR1B both 7:
ICR1 = 15;
OCR1B = 7;
OCR1A = 7;
Why 7? And why 15?
The counts are zero-relative. So by counting to 15 on a 16 MHz processor we are actually getting 1/16th of the clock, namely 1 MHz. And half of that is 8 (which, zero-relative, is 7). So we are really doing:
- Period: 16 ticks of the 16 MHz clock
- Duty cycle: 8 ticks of the 16 MHz clock
Now, one cycle:
They change over at the same instant - pulse width exactly 500 ns.
And they change back at the same moment - pulse width also 500 ns.
-
1Thanks! I was able to get a 1Mhz square wave by eliminating the prescaler and setting
ICR1 = 15
andOCR1B = 7
. It looks good except they overlap (slightly) by 50ns. If I set them to16
and8
, respectively, they don't overlap but they are slightly asymmetrical.rob– rob2015年09月01日 02:12:59 +00:00Commented Sep 1, 2015 at 2:12 -
1See amended reply for how to fix this.2015年09月01日 02:56:01 +00:00Commented Sep 1, 2015 at 2:56
Various AVRs have the capability to output both the normal and inverted timer waveform from a single output compare register simultaneously on two pins. These devices include, but are not limited to, ATtinyX5/V, ATtiny26/L, ATtinyX61A, and ATmegaXXU4.
The ATmega328P does not have this capability, therefore the smallest primary source Arduino that does is the Leonardo (ATmega32U4) and comparable devices. The Adafruit Trinket and the Digispark (both ATtiny85-based) also offer this.
What about also setting COM1B0 and then setting the initial values of OC1A and OC1B to opposites by writing to PORTB?
Also, I presume you mean 1 MHz and not 1 mHz?
Another option is to do this in hardware - it's trivial to invert a signal.
For example, see the selected answer for https://electronics.stackexchange.com/questions/30238/how-to-invert-a-digital-signal - the second diagram - connect Vs to your clock, and Vo will be your inverted clock. For the two resistors, anything over 1k should be fine. Or use an inverter (which is the same thing, in one component, but is much less likely to be in your random-part box).
Note: There will be a very short delay going through this circuit - one place I saw suggested 1.5ns, but see the spec sheet of your transistor. A 1mhz clock "ticks" at 1,000ns (I guess, 500ns on, 500ns off), so this delay shouldn't be significant.
-
Thanks, I originally tried to use an op amp to invert the signal and was surprised by how slow it was – it took about 10µs to switch. This probably would have been a faster, better approach, but if I can do everything in software that would be ideal.rob– rob2015年08月31日 16:55:46 +00:00Commented Aug 31, 2015 at 16:55
-
This is out of my field of expertise a bit, but op-amps have a slew rate, which I believe means the time to change states. For example the LM158 is quoted as having 0.3 V/µs which means therefore to go from 0 to 5 V would take 5 / 0.3 = 16.66 µs, which is fairly close to your observations. You can get faster op-amps.2015年09月01日 11:15:04 +00:00Commented Sep 1, 2015 at 11:15