Skip to main content

Lab 7: Tone Generation

Build on buzzer control to generate specific musical tones with defined frequencies. Learn the mathematical relationship between delay and frequency.

Learning Objectives

By the end of this lab, you will:

  • 🎯 Understand frequency and pitch relationships
  • 🎯 Calculate delays from desired frequencies
  • 🎯 Generate musical scale tones
  • 🎯 Implement note structures with duration
  • 🎯 Create programmable tone sequences

Prerequisites

  • ✅ Complete Lab 6 (buzzer control)
  • ✅ Understand delay timing
  • ✅ Basic music knowledge (optional but helpful)

Hardware Required

ComponentDetails
MicrocontrollerSTM32F407VG
BuzzerActive buzzer
ConnectionGPIO to buzzer

Theory: Frequency Calculation

Frequency and Delay

For a square wave:
Frequency (Hz) = 1 / (2 × Delay_in_seconds)

Or rearranged:
Delay = CPU_cycles / (2 × Desired_Frequency_Hz)

Common musical frequencies (Hz):
C4: 262 Hz
D4: 294 Hz
E4: 330 Hz
F4: 349 Hz
G4: 392 Hz
A4: 440 Hz (reference pitch)
B4: 494 Hz
C5: 523 Hz

Musical Scale Relationship

Each octave doubles the frequency:

  • A4 = 440 Hz
  • A5 = 880 Hz (double)

Each semitone multiplies by 2^(1/12) ≈ 1.0595

Demo

Tone Generation and Music

Precise tones play in sequence: create musical patterns

Example: Musical Note

// Structure for musical note
struct Note {
int frequency; // Hz
int duration_ms; // How long to play
};

Note song[] = {
{262, 500}, // C4 for 500ms
{294, 500}, // D4
{330, 500}, // E4
{349, 500}, // F4
{392, 1000}, // G4 long
};

Complete Code Example

#define RCC_BASE 0x40023800UL
#define RCC_AHB1ENR *(volatile unsigned int*)(RCC_BASE + 0x30U)

#define GPIO_D_BASE 0x40020C00UL
#define GPIOD_MODER *(volatile unsigned int*)(GPIO_D_BASE + 0x00U)
#define GPIOD_ODR *(volatile unsigned int*)(GPIO_D_BASE + 0x14U)

// Musical note frequencies (Hz)
#define C4 262
#define D4 294
#define E4 330
#define F4 349
#define G4 392
#define A4 440
#define B4 494
#define C5 523

struct Note {
int freq;
int duration;
};

void delay_us(int microseconds) {
for (volatile int i = 0; i < microseconds; i++);
}

void play_tone(int frequency, int duration_ms) {
// Calculate delay between toggles
int delay_us = 500000 / frequency; // Adjust for your CPU speed
int cycles = duration_ms * 1000 / (2 * delay_us);

for (int i = 0; i < cycles; i++) {
GPIOD_ODR |= (1U << 12); // ON
delay_us(delay_us);
GPIOD_ODR &= ~(1U << 12); // OFF
delay_us(delay_us);
}
}

int main(void) {
RCC_AHB1ENR |= (1U << 3);
GPIOD_MODER &= ~(3U << 24);
GPIOD_MODER |= (1U << 24);

// Define a simple melody (do-re-mi)
Note melody[] = {
{C4, 500}, // Do
{D4, 500}, // Re
{E4, 500}, // Mi
{0, 500}, // Rest (0 = no sound)
};

while (1) {
for (int i = 0; i < 4; i++) {
if (melody[i].freq > 0) {
play_tone(melody[i].freq, melody[i].duration);
} else {
// Rest - just delay
for (volatile int j = 0; j < 150000000; j++);
}
}
}

return 0;
}

Expected Output

Play sequence:
├─ C4 (Middle C) clear tone for 500ms
├─ D4 (Re) slightly higher for 500ms
├─ E4 (Mi) higher still for 500ms
├─ Silence for 500ms
└─ Repeat

Result: Recognizable musical phrase

Musical Scale Example

// Play major scale C to C
int scale[] = {C4, D4, E4, F4, G4, A4, B4, C5};

for (int i = 0; i < 8; i++) {
play_tone(scale[i], 250); // 250ms each note
}

Common Mistakes

IssueSolution
Tones sound wrongCheck frequency calculations - may need scaling
Tones blend togetherAdd silence between notes (rest)
CPU can't keep upSimplify calculation, adjust timing
Unrecognizable melodyVerify note sequence and durations

Key Takeaways

Important:

  1. Frequency formula: f = 1 / (2 × delay)
  2. Musical scale follows mathematical relationships
  3. Note durations control rhythm
  4. Rests (0 frequency) provide silence
  5. Tempo = 1 / duration (faster if duration smaller)

Challenge Exercises

Challenge 1: Famous Melody

Implement "Twinkle Twinkle Little Star" or "Happy Birthday".

Challenge 2: Tempo Control

Play same melody at different speeds (fast/normal/slow).

Challenge 3: Scale Generator

Play all notes from C4 to C5 with calculated frequencies.

Next Steps

🚀 Ready for Lab 8? Learn timer-based LED blinking for precise timing without software delays!

Prerequisites for Lab 8: Understanding frequency and timing