Program description

What does it do?

The Beep program produces sound using nested for loops.

An inner for loop acts as a delay timer, while an outer for loop (containing the inner loop) controls the number of times that the inner loop runs.

New concepts

Nested for loops count within a count.

A two-parameter function call. The beep subroutine is passed two values by the calling code.

Beep programming activity

Timing-related programs which either create a timed delay or signal, or measure the duration or timing of events are very common in microcontroller circuits. If you have completed all of the previous programming assignments, you have seen three different types of time delays being used:

1. Time delay functions (demonstrated in Output), using __delay_ms(), a delay function built into MPLABX

2. Hardware timer delays using timer TMR0 (demonstrated in Chaser)

3. Software delays implemented using a for loop (demonstrated in PWM)

The Beep program uses software delay loops, similar to PWM, to create a delay between successive beeper pin oscillations. Instead of continuously looping (like PWM did), Beep repeats the delay loop a set number of times – specified in the program and counted by a second loop.

What you should know before starting

Sound waves

The beeper in the CHRP board doest not have its own oscillator circuit, and, therefore, can not make sound on its own. Instead, our processor has to feed it an oscillating signal of alternating ones and zeroes. The advantage of having to produce our own signal is that we can produce any sound we can create in a program.

The time delay between the beeper's output alternations determines the sound's frequency, or pitch. The number of cycles the ouput alternates determines the sound's duration.

In this program, we will create a Beep function that accepts two variables, time period and pitch, and produces the sound corresponding to the input.

Create the Beep program

Beep uses the same files as the Input project. The CHRP3.c file sets switch S2 up for input:


/*==============================================================================
	CHRP 3.1 (PIC16F886) hardware initialization and user functions.
==============================================================================*/

#include	"xc.h"				// XC compiler general include file

#include	"stdint.h"			// Include integer definitions
#include	"stdbool.h"			// Include Boolean (true/false) definitions

#include	"CHRP3.h"			// Include user-created constants and functions

void initPorts(void)
{
	// TODO - Initialize oscillator, ports, and add (optional) user functions.

	// Initialize user ports and peripherals.

	ANSEL = 0b00000000;			// Make all PORTA pins digital I/O
	ANSELH = 0b00000000;		// Make all PORTB pins digital I/O
	OPTION_REG = 0b01010111;	// PORTB pull-ups on, TMR0 internal div 256

	// Set port directions for I/O pins: 0 = Output, 1 = Input

	TRISA = 0b00101111;			// Set runLED, IR LEDs as outputs in PORTA
	TRISB = 0b00000011;			// Set S2 as input, other PORTB pins as output
	TRISC = 0b10110000;			// Set up receive and transmit lines for IR
								// demodulator (U5) and LED11, servo outputs

	// Set starting I/O conditions.

	PORTA = 0;					// Turn off all PORTA outputs, turn on run LED
	PORTB = 0;					// Turn off all PORTB LEDs
	PORTC = 0;					// Turn off all PORTC outputs

	// Enable interrupts, if needed.
}
		

Create the main Beep.c program file:


/*==============================================================================
	Project: Beep
	Version: 3.1				Date: November 24, 2014
	Target: CHRP3.1				Processor: PIC16F886

	A program demonstrating the use of loops to make sounds as well as global
	variables.
==============================================================================*/

#include	"xc.h"				// XC compiler general include file

#include	"stdint.h"			// Include integer definitions
#include	"stdbool.h"			// Include Boolean (true/false) definitions

#include	"CHRP3.h"			// Include user-created constants and functions

/*==============================================================================
    Beep function. Produces the selected number of half-cycles of a wave with
    a specified time period.
==============================================================================*/

void beep(unsigned char period, unsigned char cycles)
{
	unsigned char i;
	unsigned char t;
	for (i = cycles; i != 0; i --)		// number of beeper pin output flips
	{
		BEEPER = !BEEPER;				// flip beeper pin and
		for (t = period; t != 0; t --);	// wait for period to end
	}
}

/*==============================================================================
	Main program code
==============================================================================*/

int main(void)
{
	// Initialize I/O and peripherals for PORTB output
	initPorts();

	while(1)
    {
		if (S2 == 0)
			beep(60,200);			// Beep for 200 counts of 60 loop delays
	}
}

		

Download the program into the CHRP and verify its operation. Pressing pushbutton S2 will produce a short beep.

How the program works

The beep function


void beep(unsigned char period, unsigned char cycles)
		

The beep function accepts two parameters from the function call (period and cycles). Both the parameters in the beep function, and the two variables passed in the function call are separated by commas. Any number of variables can be passed to a function as a list of comma-separated parameters.


	unsigned char i;
	unsigned char t;
		

Within the function, the characters i and t are local variables used as a loop index counter and time period counter, respectively.

The line:


		BEEPER = !BEEPER;				// flip beeper pin and
		

inverts the BEEPER I/O pin, allowing the loop code to be shortened by not having to specifically make the beeper's I/O pin high and then low. The ! (not) modifier flips the pin to the opposite state.


		for (t = period; t != 0; t --);	// wait for period to end
		

After toggling the beeper's I/O pin, the time period for loop creates a delay before toggling the pin back, producing an audible oscillation.

This inner loop time-delay cycle is repeated for the number of cycles specified in the outer loop:


	for (i = cycles; i != 0; i --)		// number of beeper pin output flips
		

Test your knowledge

  1. How can multiple variables be passed as parameters to a single function? How are they separated?
  2. A complete sound wave consists of a both the high and low parts of a wave. How many complete sound waves will the example code produce? Explain.
  3. Use the simulator to determine the time period of the sound wave produced. What is the sound frequency and duration.
  4. If the beep period is changed while the number of cycles stays constant, will the duration of the sound change? Why?

Apply your skills

  1. Create musical notes by looking up their frequencies and using precise delays created by the __delay_us() time delay function to delay for the high and low periods of the note waves. Enable each of the six buttons on the CHRP3 to play a different note.
  2. How long can the duration of a note be in the example code? Modify the cycles variable to be an intteger type. How long can an integer note duration be? Modify your code for the previous question to equalize the length of each note.
  3. Create a program to play a song.