For those who don’t like to waste timers
or use interrupt programming, here is an
example of a useful button and buzzer combo.
This turns the O into a three-button organ!
(Seven notes are possible, but
with fat fingers, hard to play).
Cheers, Jim
Code with tabs can be downloaded at
uoxray.uoregon.edu/orangutan/button.c
/*
button and buzzer examples for the Orangutan/WinAVR
These routines do not use the timers or interrupts
sjames_remington at yahoo dot com
*/
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
// function prototypes
unsigned char button(unsigned char wait);
void buzzer(unsigned int frequency, unsigned int duration);
/*
button(wait);
returns a value corresponding to a button press
4 = rightmost button (next to power switch)
2 = center button
1 = leftmost
if wait is nonzero, wait until a button is pressed and debounce
otherwise, read and return immediately
*/
#define BTNS (7<<3)
unsigned char button(unsigned char wait)
{
volatile unsigned char save_DDRB, btn_value;
save_DDRB = DDRB; //save state of DDRB for LCD display and/or motors
DDRB |= 0; //set PORTB all input
PORTB &= ~BTNS; //turn off pullups as required
btn_value = PINB & BTNS; //read the button pins
if(wait==0) {
DDRB = save_DDRB;
return (btn_value>>3);
} //return immediately if wait=0
while( (PINB & BTNS) == 0); //otherwise, wait until a button is pressed
do {
btn_value=(PINB & BTNS); //read the buttons again
_delay_ms(20); //wait 20 ms
}
while (btn_value != (PINB & BTNS)); //keep reading until stable
DDRB=save_DDRB; //restore DDRB
return (btn_value>>3); //return values in range 1-7
}
/*
buzzer(frequency, duration);
Sound a tone, this time without interrupts. CPU intensive!
call arguments:
frequency is in Hz, usable range 100-10,000 Hz
duration is in milliseconds
This routine uses _delay_loop_2() to generate timing (4 cpu cycles per loop)
For correct operation, be sure to define F_CPU in Hz!
*/
void buzzer(unsigned int frequency, unsigned int duration)
{
unsigned int wait_units, loops, i;
DDRB |= 1; //make PORTB.0 output
wait_units = F_CPU/(8UL * (long int) frequency); //half of the tone period, in delay loop units
loops = duration*F_CPU/(8000UL*wait_units); //number of loops to execute
for (i=1; i<=loops; i++) { //sound the buzzer
PORTB |= 1; //on
_delay_loop_2(wait_units); //wait 1/2 tone period
PORTB &= ~1; //off
_delay_loop_2(wait_units); //wait 1/2 tone period
}
}
int main(void)
{
unsigned char pressed;
buzzer(800,1000); //beep @ 800 Hz for 1 second
while(1) {
pressed=button(1); //wait till one or more buttons pressed
if (pressed&1) buzzer(400,200); //play a tone
if (pressed&2) buzzer(500,200);
if (pressed&4) buzzer(600,1000);
}
}