Skip to content

Button with audio feedback

This example demonstrates how to use button callbacks and the PWM-based buzzer on the TI EK-TM4C1294XL LaunchPad. The example makes the buzzer emit a short tone when pressing or releasing a button (S1) using callback functions.

You will also see how to use the elapsedMillis helper class to manage time intervals efficiently.


  • EK-TM4C1294XL LaunchPad
  • Button S1 connected to PA7
  • Buzzer connected to PF1 (M0PWM1)

After completing this example, you will learn:

  1. How to configure PWM for sound generation.
  2. How to define button callbacks (attachClick, attachDoubleClick).
  3. How to use elapsedMillis for periodic updates.

Below is the complete code that you can copy and paste into your Code Composer Studio project:

#include <stdint.h>
#include <stdbool.h>
extern "C" {
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/pwm.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/fpu.h"
#include "driverlib/interrupt.h"
#include "driverlib/timer.h"
#include "inc/hw_ints.h"
}
#include "button.h"
#include "timerLib.h"
#include "elapsedTime.h"
// ============================================================================
// Globals
// ============================================================================
uint32_t gSysClk;
Timer timer;
Button btnS1(S1);
// ============================================================================
// Buzzer (PF1 → M0PWM1)
// ============================================================================
#define BUZZER_PWM_BASE PWM0_BASE
#define BUZZER_GEN PWM_GEN_0
#define BUZZER_OUTNUM PWM_OUT_1
#define BUZZER_OUTBIT PWM_OUT_1_BIT
static void Buzzer_Init(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_PWM0));
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF));
GPIOPinConfigure(GPIO_PF1_M0PWM1);
GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1);
PWMClockSet(PWM0_BASE, PWM_SYSCLK_DIV_64);
}
void Buzzer_Beep(uint32_t freq_hz, uint32_t duration_ms)
{
if (freq_hz == 0) return;
uint32_t pwmClock = gSysClk / 64;
uint32_t period = pwmClock / freq_hz;
PWMGenConfigure(BUZZER_PWM_BASE, BUZZER_GEN, PWM_GEN_MODE_DOWN);
PWMGenPeriodSet(BUZZER_PWM_BASE, BUZZER_GEN, period);
PWMPulseWidthSet(BUZZER_PWM_BASE, BUZZER_OUTNUM, period / 2);
PWMOutputState(BUZZER_PWM_BASE, BUZZER_OUTBIT, true);
PWMGenEnable(BUZZER_PWM_BASE, BUZZER_GEN);
SysCtlDelay((gSysClk / 3 / 1000) * duration_ms);
PWMOutputState(BUZZER_PWM_BASE, BUZZER_OUTBIT, false);
}
// ============================================================================
// Button Callbacks
// ============================================================================
static void onClick()
{
Buzzer_Beep(500, 60); // Grave al presionar
}
static void onDoubleClick()
{
Buzzer_Beep(1000, 60); // Agudo al soltar
}
// ============================================================================
// Button initialization
// ============================================================================
static void setupButtons()
{
btnS1.begin();
btnS1.setDebounceMs(15);
btnS1.setTickIntervalMs(20);
btnS1.setClickMs(120);
btnS1.attachClick(&onClick);
btnS1.attachDoubleClick(&onDoubleClick);
}
// ============================================================================
// Main
// ============================================================================
int main(void)
{
FPUEnable();
FPULazyStackingEnable();
gSysClk = SysCtlClockFreqSet(
SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480,
120000000
);
timer.begin(gSysClk, TIMER0_BASE);
elapsedMillis buttonCheck(timer);
Buzzer_Init();
setupButtons();
while (1)
{
if(buttonCheck > 20){
buttonCheck = 0;
btnS1.tick();
}
}
}