I need to implement a clock signal and I'd like to use the Arduino, however the clock signal has to be high frequency and variable.
I have generated an acceptable square wave using digitalWrite and delayMicrosecond but I need more than 1us resolution.
I attempted to use inline assembly and the "nop" command to get nanosecond resolution, but so far my code does not produce a squarewave. The pin just stays low according to the scope.
Here is the code (I am using digitalWriteFast to save programming time). There are no compile errors or anything to suggest something is wrong.
How can I fix this? Any pointers? This is my first time using inline assembly and my searches haven't turned up much I can use (or that makes sense to me.)
Thanks for the help, I can post pictures of the o-scope output if that will help.
You might also want to look into assembly language for this kind of code. There is some overhead in Arduino that you may be able to sidestep if you use assembly. There are other challenges, but it is an option where you are trying to push the envelope because you can work with a smaller envelope.
I am looking into using timers now, I think I can find the flexibility I need in there. However, I'm still worried about the overhead.
If I wait for the overflow interrupt it will be too slow, even at system clock. what is the overhead for using the compare register? I think I could just set the interval in the compare register, and then clear the register after interrupt. Would that work? Does anyone know off the top of their head how many clock cycles that kind of compare would take?
Okie day, I tried a timer implementation, and it seems pretty great except that I can't seem to get it to move faster than 250kHz. With a while(1) loop and assembly, I could get 2MHz. According to the scope and some fiddling, it takes 34 clock cycles to execute the register compare and the interrupt code.
Here is the code:
#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER1_COMPA_vect)
{
PORTB = ~PORTB; // Reverse all the damn pins
}
void setup()
{
pinMode(13, OUTPUT);
cli(); // disable global interrupts
TCCR1A = 0x00; // set entire TCCR1A register to 0
TCCR1B = 0x00; // same for TCCR1B
// set compare match register to 34 cycles:
OCR1A = 0x22;
// turn on CTC mode:, set TCCR1 prescaler to system clock
TCCR1B = B00001001;
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
// re-enable global interrupts:
sei();
}
//avoiding linking errors
void loop()
{
}
If this is all crazy talk, let me know. If you can think of anything to speed up the code, please tell me. I need 1.5 Mhz for timing/measuring purposes.
I'm not sure what you get when you read the port's output register so I don't know if that will affect what you are doing or not, but it certainly is what you intended I think.
There will be a large overhead with interrupts, I think the guys were suggesting you use the PWM abilities of the timer, that is totally hardware.