HW9 - Buzzzzz

Note

Notes on setting up the VM for AVR projects can be found in the Appendix; See AVR Assembly Setup

In this lab, we will explore the use of the timer to control a Piezo buzzer. We will use the polling scheme we went over. (Interrupts will happen in the next lab)

The buzzer looks like this:

../_images/PiezoBuzzer.jpg

The particular device we will use was obtained from Jameco Electronics. (Search for part number 2098523 for details)

A Piezo buzzer is a simple device that vibrates each time a voltage changes across the pins of the buzzer. What this means is that if we turn on and off an output pin fast enough, we will hear a sound. How fast? Well, the particular buzzer we are using runs best at 4 kilohertz (4000 times a second or so). Make that your target speed.

We will use the timer to control this device. You will need to look over today’s lecture notes to set up the code to run this lab. The circuit for this lab is super simple. Just hook up the two power lines and connect one pin of the buzzer to ground, and the other pin to an output pin of your choice. The code will need to turn this output pin on and off fast enough to generate a sound.

Hooking up this device is simple. You plug it into the breadboard so the leads are on either side of the gutter that runs down the middle of the board. One side of the buzzer will be connected to an output pin on the Arduino, and the other pin will be connected to a ground pin on the Arduino.

Starting Point

Here is a sample “C” program that you can use as a starting point. This one will blink the LED on the Arduino at a reasonable rate. If you compare this code with the assembly code from the lecture, you wll see the same logic at work.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <avr/io.h>

int state = 1;
char ticks = 0;

void toggleLED(void);

int main(void) {
    DDRB = (1 << 5);        // set pin 5 to output
    TIMSK0 = 0;             // no interrupts
    TCCR0B = 5;             // divide clock by 1024

    while(1) {
        while((TIFR0 & 0x01) == 0) {}    // loop until flag is set

        TIFR0 = 1;              // clear the flag
        ticks++;
        if(ticks == 60) {
            ticks = 0;
            toggleLED();
        }
    }
}

void toggleLED(void) {
    if(state == 1) {
        PORTB = 0;
        state = 0;
    } else {
        PORTB = (1 << 5);
        state = 1;
    }
}

        

Here is the Makefile for thisproject:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# source files
TARGET	:= $(shell basename $(PWD))
CSRCS	:= $(wildcard *.c)
COBJS	:= $(CSRCS:.c=.o)
SSRCS	:= $(wildcard *.S)
SOBJS	:= $(SSRCS:.S=.o)
OBJS	:= $(COBJS) $(SOBJS)

LST	:= $(TARGET).lst

# define the processor here
MCU		:= atmega328p
FREQ	:= 16000000L

# define the USB port on your system (this works on Linux)
PORT	:= /dev/ttyACM0
PGMR	:= arduino

# tools
GCC		:= avr-gcc
OBJDUMP	:= avr-objdump
OBJCOPY	:= avr-objcopy
DUDE	:= avrdude

UFLAGS	:=  -v -D -p$(MCU) -c$(PGMR)
UFLAGS		+= -P$(PORT)
UFLAGS		+= -b115200

CFLAGS	:=  -c -Os -mmcu=$(MCU)
CFLAGS		+= -DF_CPU=$(FREQ)

LFLAGS	+= -mmcu=$(MCU)

.PHONY all:
all:	$(TARGET).hex $(LST)

# implicit build rules
%.hex:	%.elf
	$(OBJCOPY) -O ihex -R .eeprom $< $@

%.elf:	$(OBJS)
	$(GCC) $(LFLAGS) -o $@ $^ 

%.o:	%.c
	$(GCC) -c $(CFLAGS) -o $@ $^

%.o:	%.S
	$(GCC) -c $(CFLAGS) -o $@ $<

%.lst:	%.elf
	$(OBJDUMP) -C -d $< > $@

# utility targets
.PHONY:	load
load:
	$(DUDE) $(DUDECONF) $(UFLAGS) -Uflash:w:$(TARGET).hex:i

.PHONY:	clean
clean:
	$(RM) *.hex *.lst *.o *.elf

To compile this program, just run these commands:

  • make clean
  • make
  • make load

You should see your LED blinking.

Convert to Buzz

For your next step, convert this code so it toggles PORTD, pin 7. You will need to speed up the loop so it makes some noise. That will take some experimenting to get things set up right. You will know when this is working.

Connect your buzzer so one pin is connected to Pin 7 on the Arduino (PB7 on the chip), and the other is connected to ground (GND on the Arduino)

Convert to Assembly

For the last step, we will rewrite this as an assembly language program. I will make this easy. You can reverse engineer the code from the last step, and write a fully commented program that works the same way. Your should be able to figure out what the code is doing from your “C” source code.

Note

You can use the notes to see example code that does run.

Run this command to get an assembly language output file. You will need the new Makefile system we went over in class for this to work:

  • make buzz.s (assuming your TARGET setting is buzz)

This will be the file with assembly code in it.

Note

The code will not show register names, only the final numbers. You will need to figure out which registers are being used by referring to your “C” code, or the header files for the Arduino which can be could in /usr/lib/avr/include/avr/. The iom328p.h file has definitions for many of the registers in our chip.