0
0
Power-electronicsProgramBeginner · 2 min read

Embedded C Program to Generate Square Wave Signal

Use a GPIO pin toggle with a delay loop in Embedded C like while(1) { PORT |= (1 << PIN); delay(); PORT &= ~(1 << PIN); delay(); } to generate a square wave.
📋

Examples

InputToggle GPIO pin 0 with 500ms delay
OutputSquare wave output on pin 0 with 1Hz frequency (0.5s HIGH, 0.5s LOW)
InputToggle GPIO pin 1 with 100ms delay
OutputSquare wave output on pin 1 with 5Hz frequency (0.1s HIGH, 0.1s LOW)
InputToggle GPIO pin 2 with 1ms delay
OutputSquare wave output on pin 2 with 500Hz frequency (1ms HIGH, 1ms LOW)
🧠

How to Think About It

To generate a square wave, you repeatedly switch a digital output pin ON and OFF with equal time intervals. This creates a signal that alternates between high and low states, forming a square wave. The delay between toggles controls the wave frequency.
📐

Algorithm

1
Set the GPIO pin as output.
2
Enter an infinite loop.
3
Set the pin HIGH to start the wave.
4
Wait for a fixed delay time.
5
Set the pin LOW to complete the wave cycle.
6
Wait for the same fixed delay time.
7
Repeat the loop to continue the square wave.
💻

Code

embedded_c
#include <avr/io.h>
#include <util/delay.h>

int main(void) {
    DDRB |= (1 << PB0); // Set pin PB0 as output
    while(1) {
        PORTB |= (1 << PB0);  // Set PB0 HIGH
        _delay_ms(500);      // Delay 500 ms
        PORTB &= ~(1 << PB0); // Set PB0 LOW
        _delay_ms(500);      // Delay 500 ms
    }
    return 0;
}
Output
Square wave generated on pin PB0 with 1Hz frequency (0.5s HIGH, 0.5s LOW)
🔍

Dry Run

Let's trace the square wave generation on pin PB0 with 500ms delay.

1

Set pin PB0 as output

DDRB |= (1 << PB0); sets the data direction register to output for pin PB0.

2

Set pin HIGH

PORTB |= (1 << PB0); sets pin PB0 HIGH (logic 1).

3

Delay 500ms

_delay_ms(500); pauses program for 500 milliseconds.

4

Set pin LOW

PORTB &= ~(1 << PB0); clears pin PB0 to LOW (logic 0).

5

Delay 500ms

_delay_ms(500); pauses program for 500 milliseconds.

6

Repeat loop

The loop repeats steps 2-5 indefinitely to generate continuous square wave.

StepPin PB0 StateDelay(ms)
1Output mode set0
2HIGH (1)0
3HIGH (1)500
4LOW (0)0
5LOW (0)500
6Repeat0
💡

Why This Works

Step 1: Pin Setup

We set the GPIO pin as output using DDRB |= (1 << PB0); so it can send signals.

Step 2: Toggle Pin HIGH

Setting the pin HIGH with PORTB |= (1 << PB0); starts the square wave's high phase.

Step 3: Delay for Timing

The _delay_ms() function creates a pause to keep the pin state stable for half the wave period.

Step 4: Toggle Pin LOW

Setting the pin LOW with PORTB &= ~(1 << PB0); completes the wave cycle's low phase.

🔄

Alternative Approaches

Using Timer Interrupt
embedded_c
#include <avr/io.h>
#include <avr/interrupt.h>

ISR(TIMER0_COMPA_vect) {
    PORTB ^= (1 << PB0); // Toggle pin PB0
}

int main(void) {
    DDRB |= (1 << PB0); // Set PB0 as output
    TCCR0A = (1 << WGM01); // CTC mode
    OCR0A = 249; // Compare value for 1ms at 16MHz/64
    TIMSK0 = (1 << OCIE0A); // Enable compare interrupt
    TCCR0B = (1 << CS01) | (1 << CS00); // Prescaler 64
    sei(); // Enable global interrupts
    while(1) {}
    return 0;
}
This method uses hardware timer interrupts for precise square wave timing without blocking CPU.
Using PWM Hardware
embedded_c
#include <avr/io.h>

int main(void) {
    DDRB |= (1 << PB1); // Set PB1 as output (OC1A)
    TCCR1A = (1 << COM1A0) | (1 << WGM10); // Toggle OC1A on compare match, 8-bit PWM
    TCCR1B = (1 << WGM12) | (1 << CS10); // CTC mode, no prescaler
    OCR1A = 128; // 50% duty cycle
    while(1) {}
    return 0;
}
Using PWM hardware generates square wave automatically with less CPU usage but requires timer setup.

Complexity: O(1) time, O(1) space

Time Complexity

The program runs in an infinite loop toggling a pin with fixed delays, so time per cycle is constant, O(1).

Space Complexity

Only a few variables and registers are used, so space complexity is O(1).

Which Approach is Fastest?

Hardware timer or PWM methods are faster and more precise than software delay loops, which waste CPU cycles.

ApproachTimeSpaceBest For
Software Delay LoopO(1)O(1)Simple, low precision
Timer InterruptO(1)O(1)Precise timing, efficient CPU use
PWM HardwareO(1)O(1)Automatic waveform, minimal CPU
💡
Use hardware timers for accurate square wave generation instead of software delay loops.
⚠️
Beginners often forget to set the GPIO pin as output before toggling it, causing no signal output.