Generate high frequency square wave


I have the MEGA2560 board. I was wondering if it is possible to generate a 150 kHz square wave output? I have tried using the delayMicroseconds() and micros() function but the highest freq I can get is in the tens of kHz.

Does anyone have any experience with generating such high frequency signals?

Many thanks.

The simplest way would be to change the PWM frequency to 150KHz and let the timers do the work.

Tried direct port manipulation? - -

that is substantial faster than digitalWrite(pin, HIGH/LOW);

Thank you for your replies. I have tried the following bit of code:

void setup() {
  // set the digital pin as output:
  pinMode(13, OUTPUT);      
void loop()
      PORTB |= _BV(PB7);     // pin 13 high
      PORTB &= ~_BV(PB7);   // pin 13 low

It just turns digital pin 13 on and off really fast. It sort of works. I can get a really high frequency but it isn't very clean, there are a lot of jitters and the square pulses are distorted specially on the falling edge.

Applogies for being a total noob but could someone give me some noob level example code for direct port manipulation that I can play about with?

Also, I was hoping I could avoid using delays in the code since I want to be doing other things while generating the square pulse.

EDIT: I made the mistake of not setting pin digital pin 13 as output, which is the reason for the distorted square pulses I think. Code updated above.

EDIT 2: Could I somehow use one of the timers to generate a signal while the microprocessor is free to do other things? Could someone please direct me towards some fairly easy to understand material to do this.

Thanks again.

If you do not need high accuracy, if you do not have to be flexible in terms of which output pin you use, and if you don’t mind tying up a timer you can do this with four lines of code that runs only once and does not involve interrupts. Here is some old code that I reworked. It is untested but heavily commented so you should be able to get it working.

// This program uses the 'Toggle OC2A on Compare Match' mode along with the 'Clear Timer on Compare Match (CTC)' mode 
//   to generate a square wave.  The disadvantage of this technique is that the output pin is fixed by the hardware.  
//   The advantage is that this technique does not use any interrupts and does use any code (or processor time) once
//   it is set up.  It does tie up a timer (timer 2 in this case).

// The output frequency is determined by the clock frequency, the prescale factor, and the value loaded into OCR2A.
// The output frequency = (clock frequency / (2 * prescale factor * (1 + OCR2A)))
// The Arduino clock frequency is fixed at 16 MHz so the factors we have to work with are the prescale factor, and 
//   the value loaded into OCR2A.

// For any given prescale factor the maximum output frequency will occur when OCR2A is loaded with 00.
// For any given prescale factor the minimum output frequency will occur when OCR2A is loaded with 255.
//   For a prescale factor of 1, fmax = 8 MHz and fmin = 31250 Hz
//   For a prescale factor of 8, fmax = 1 MHz and fmin = 3906.3 Hz
//   For a prescale factor of 32, fmax = 250 KHz and fmin = 976.6 Hz

// Reworking the equation gives: OCR2A = (clock frequency / (output frequency * 2 * prescale factor)) -1
//   For an output frequency of 150 KHz and a prescale factor of 1, OCR2A must be loaded with 52.33 (use 52)
//     The value 52 gives a theoretical output frequency of 150.943 KHz
//   For an output frequency of 150 KHz and a prescale factor of 8, OCR2A must be loaded with 5.67 (use 6)
//     The value 6 gives a theoretical output frequency of 142.857 KHz

#define outpin 11                                  // OC2A pin - cannot be changed
#define clockFrequency 16000000                    // Arduino clock frequency
#define prescaleFactor 1                           // required in order to get reasonable accuracy

void setup ()

// Configure the 'Waveform Generation Mode' to the CTC (Clear Timer on Compare Match) mode by dealing with the WGMxx bits.
//   We need mode 2; WGM22 = 0, WGM21 = 1, and WGM20 = 0
//   This must be done several steps because the WGM bits are split between two registers
   TCCR2B &= ~(1 << WGM22);                         // clear WGM22
   TCCR2A |= (1 << WGM21);                          // set WGM21
   TCCR2A &= ~(1 << WGM20);                         // clear WGM20
// Configure the 'Compare Output Mode' to 'Toggle OC2A on Compare Match' by dealing with the COMxx bits.
//   We need COM2A1 = 0 and COM2A0 = 1  
   TCCR2A &= ~(1 << COM2A1);                        // clear COM2A1
   TCCR2A |= (1 << COM2A0);                         // set COM2A0
// Set the prescaler to divide by 1 by dealing with the CSxx bits
//   We need CS22 = 0, CS21 = 0, and CS20 = 1
   TCCR2B &= ~(1 << CS22);                          // clear CS22
   TCCR2B &= ~(1 << CS21);                          // clear CS21
   TCCR2B |=  (1 << CS20);                          // set CS20

// The previous eight instructions have been replaced by these two.  See the comments above for an explanation.
  TCCR2B = B00000001;                               // set CS20, clear CS21, CS22 and WGM22
  TCCR2A = B01000010;                               // set COM2A0 and WGM21, clear COM2A1 and WGM20

// calculate and load the timer data timer 
  OCR2A  = ((float)clockFrequency / (noteval * 2 * prescaleFactor)) -1;  

// Set up the output pin
  pinMode(outpin, OUTPUT);                          // turn on output pin   

// the timer runs with no additional code and no use of interrupts
// do whatever else you want to do here


void loop ()
// do whatever else you want to do here