ESE 123 · Laboratory 7 · TA walkthrough

Assembly Language & the Buzzer

Your board gets its brain. You plug in the ATmega4809 microcontroller, solder the piezo buzzer, and write your first program in assembly language, the language of the chip itself. The first version toggles the buzzer pin so fast you can’t hear it. Adding delay loops slows it to about 440 Hz, a note you can hear. Then you prepare the surface-mount LEDs for next week.

Pre-lab 7 · handout steps 28–37

1 · Watch the chip run your program, one instruction at a time

This is a simulator of the ATmega4809 running the exact code from the handout. The processor reads one instruction, does it, adds its clock cycles to the total, and moves the program counter to the next line. Watch the registers r16 and r17, the Z (zero) flag, and pin PF6, which drives the buzzer test point BUZ. Step through slowly first, then run fast and look at the scope.


    
Plays a quiet square wave at the frequency above. Program 1 is far above human hearing (20 kHz), so it is silent.

Why Program 1 is silent

The loop is only 5 instructions: ldi, out, ldi, out (1 cycle each) and rjmp (2 cycles) = 6 cycles per wave. At 3.33 MHz that is about 556 kHz, far above the 20 kHz limit of hearing. The scope on BUZ shows it; your ears can’t.

Why the delay loop works

Each pass through bent: spends 12 nops + dec + brne. Starting r17 at 255 makes 255 passes, about 3824 cycles. Doing that once with the pin high and once with it low makes one wave of 7656 cycles: about 435 Hz, close to concert A (440 Hz).

DEC sets Z, BRNE reads it

DEC subtracts 1 and sets the zero flag only when the result is 0. BRNE (“branch if not equal”) jumps back while Z is clear and falls through once Z is set. (The pre-lab table words this backwards; the text below it is right.)

20 MHz or 3.33 MHz?

The pre-lab says 20 MHz, but the program never changes the clock settings, and the ATmega4809 starts up dividing 20 MHz by 6. Your measured frequency tells you which: 7656 cycles × 435 Hz ≈ 3.33 million cycles per second. That’s the first report question.

Pre-lab 7 · machine and assembly language

2 · From assembly to machine code, and choosing bits

The chip only understands 16-bit numbers. LDI r24,165 is assembled into 1110 1010 1000 0101: 4 bits say “LDI”, 8 bits hold the constant (split in two), and 4 bits pick the register. Only 4 bits for the register is why LDI works with r16–r31 only. Pick a register and a constant:

Which pin goes high? Click the bits


      

Bit 0 is the rightmost (least significant), bit 7 the leftmost. There is no “out immediate”, so you always load a register with LDI first, then OUT it to the port.

Pre-lab 7 looping example · handout pages 5–6

3 · Counting clock cycles in a delay loop

Most instructions take 1 cycle. BRNE takes 2 when it jumps and 1 when it doesn’t; RJMP takes 2; a label takes none. For a loop that starts with ldi rX,N and has k one-cycle instructions plus dec and brne inside, the cycle count is below. Change N and k to design your own tone.

Handout steps 1–8 and 41–52

4 · Board assembly: buzzer, R15, the microcontroller and the LEDs

Surface-mount LED orientation

The two pads are not identical: the cathode (−) pad has little “horns”. The LED’s green (or black) mark is the cathode. Green mark → horned pad. On the solder side, with the board oriented as in the handout, the six horizontal LEDs point their green marks left, the two vertical ones up.

Mixed colours look alike when unlit. DMM Shift → Cont (diode test) lights the LED so you can see its colour; swap probes if it doesn’t light (it only conducts one way).

Six LEDs count seconds, one shows USB power, one shows the alarm is armed. Some colours don’t show through some acrylic covers, so check the demo board at the back of the lab first.

Handout steps 9–34

5 · MPLAB X, step by step

    When the build fails

    Step 30 asks you to break it on purpose (type lido instead of ldi). The Output box shows an error with a hyperlink; click it to jump to the line. Common real mistakes:

    • A label not at the left margin, or missing its colon.
    • Two labels with the same name (that’s why the second loop is called relaxed).
    • LDI into r0–r15 (only r16–r31 allowed).
    • A typo in VPORTF_OUT / VPORTF_DIR.
    • No Snap listed: cancel, unplug and replug the USB cable, start the project again.

    Then measure BUZ (right edge of the board; PF6, chip pin 29) with the scope, ground clip on the GND loop.

    Keep this open during the lab

    6 · Formula sheet: what, when, and an example

    Self-check · same concepts as the pre-lab and report, new numbers

    7 · Practice questions

    Try each one before opening the answer. These are not the real assignment questions; they use the same ideas with different numbers.

      Pre-lab report and lab report

      8 · Report guide

      1. Pre-lab: a fragment that sets bit 4 of PORTD high.LDI a register with only bit 4 set, then OUT it to VPORTD_OUT.
      2. Pre-lab: set bit 4 high, delay 3 cycles, set it low, delay 1 cycle.Count cycles: each NOP is one.
      3. Pre-lab: repeat that sequence 8 times.Use the loop recipe: LDI a counter with 8, label, body, DEC, BRNE.
      4. Lab: clock cycles per second = 7656 × your measured frequency (3 pts).Expect about 3.3 million (the 20 MHz ÷ 6 default).
      5. Lab: scope image of BUZ showing the measured frequency (5 pts).
      6. Lab: screenshot of your delay-loop code (2 pts).