80. Simultaneous Square Wave Generation

The Square Wave Generation Challenge

  • Generating a high-frequency square wave is simple.
  • Generating two different high-frequency square waves simultaneously without CPU load is harder.
  • Software-based toggling fails at hundreds of kHz due to:
    • CPU execution jitter
    • Interrupt latency
    • Main loop blocking

The Robust Approach

Use two independent hardware timers configured in Output Compare or PWM mode so that:

  • Each timer runs autonomously
  • Each toggles its assigned output pin directly in hardware
  • No CPU intervention is needed for timing

Understanding the Key Timer Parameter

Different microcontrollers use different names for the same concept:

  • STM32: Auto-Reload Register (ARR)
  • AVR: Output Compare Register (OCRnA/B)
  • PIC: Period Register (PRx)
  • NXP/Freescale: MOD register

Generic term: Timer Period Register or Maximum Count Value – the value at which the timer counter resets back to zero.

Operation:

  1. Timer counts from 0 to the Maximum Count Value.
  2. When it reaches this value:
    • It resets to 0
    • Optionally toggles the output pin if in toggle mode
  3. Smaller value → faster counting → higher output frequency.
     

Frequency Calculation (Prescaler = 0)

Timer Frequency:

Timer_Freq = Timer_Clock / (Max_Count_Value + 1)


Output Frequency in Toggle Mode:

Output_Freq = Timer_Freq / 2

(Reason: Two toggles make one full waveform cycle)


Why Two Timers Instead of One?

  • All channels in a single timer share the same Maximum Count Value → same base frequency
  • You can only adjust the duty cycle per channel, not the base frequency.
  • Simulating different base frequencies via interrupts would require servicing every 1–2 µs at these frequencies — impractical when the CPU is busy.


Calculation Example

Given:

  • Timer clock = 64 MHz
  • Prescaler = 0
  • Output mode = Toggle


Formula:

Max_Count_Value = (Timer_Clock / (2 × Desired_Freq)) − 1


For 307 kHz:

Max_Count_Value = (64,000,000 / (2 × 307,000)) − 1 ≈ 103


For 570 kHz:

Max_Count_Value = (64,000,000 / (2 × 570,000)) − 1 ≈ 55


Final Configuration

  • Timer A → Max Count = 103 → 307 kHz output
  • Timer B → Max Count = 55 → 570 kHz output

Both timers run independently and continuously, generating precise square waves without affecting the main loop’s performance.

 

So, by considering the above points, we can implement the task.

Below are the solutions to the given task using different microcontrollers

  1. STM32
  2. ESP32
  3. Arduino UNO

Submit Your Solution

Note: Once submitted, your solution goes public, helping others learn from your approach!