Register-level ATmega32 firmware spanning external interrupts, hardware timers, matrix keypad input, SRAM buffering, ADC temperature sensing, PWM generation, and servo control — written in AVR assembly and C, with no HAL or abstraction layer.
Reconstructed and corrected from completed ATmega32/STK500 laboratory experiments and surviving project materials.
| # | Module | Key techniques | Lang |
|---|---|---|---|
| 6 | External Interrupts | INT0/INT1/INT2 vector table, fixed hardware priority, SREG + full register save/restore in every ISR | asm |
| 7 | Timers & Keypad | Timer0 normal mode (prescaler 1024), TCNT0 preload math, 4×4 matrix keypad scan, ASCII multi-tap lookup table, 64-byte SRAM message buffer, live delay adjustment via interrupts | asm |
| 8 | PWM & ADC | Fast PWM on OC0, 7-position servo control, free-running ADC, LM34 temperature sensor, temperature-band-to-angle mapping | asm + C |
Each lab folder has its own README.md with wiring diagrams, register-level
math, build steps, and a changelog versus the original experiment.
- Direct peripheral control — every peripheral (timer, ADC, interrupt controller, PWM) configured by writing named bit fields into I/O registers; no libraries involved
- Interrupt-driven timing — Lab 7 Part 3 adjusts inter-character playback delay live (0.5 s – 5 s) via INT0/INT1 while a message plays back from SRAM
- Correct ISR discipline — all ISRs push and restore SREG plus every clobbered register; nested interrupt edge cases documented
- Derived timing constants — TCNT0 preloads and OCR0 compare values
calculated from first principles (
(OCR0+1) × 64 µsat 1 MHz / prescaler 64), then verified empirically against the actual hardware - Boundary conditions guarded — SRAM buffer rejects input past 64 bytes;
#with an empty buffer is ignored rather than reading uninitialized memory
| Part | Role |
|---|---|
| ATmega32A | Target MCU |
| STK500 | Development board — LEDs on PORTA/PORTB, switches on PORTD |
| JTAGICE mkII | On-chip debugger and programmer |
| 4×4 matrix keypad | Input for Labs 7 and 8 |
| Hobby servo | Output actuator for Lab 8 |
| LM34 temperature sensor | ADC input (PA0) for Lab 8 Part 6 |
Atmel Studio 7 / Microchip Studio
- New Project → AVR Assembler (or GCC C Executable) → device ATmega32
- Add the relevant source file from the lab folder
- Lab 7 only: set
PART_SELECTto1,2, or3near the top of the file - Build → F7, then Tools → Device Programming → JTAGICE mkII → Program Flash
Command line
avra -I /usr/share/avra Lab6_Interrupts/lab6_interrupts.asm
avra -I /usr/share/avra Lab7_Timers_Keypad/lab7_timers_keypad.asm
avr-gcc -mmcu=atmega32 -DF_CPU=1000000UL -Wall -Wextra -Os \
-c Lab8_PWM_ADC/lab8_part6_adc_servo.cCI assembles and compiles every source file (all three PART_SELECT
configurations for Lab 7) on every push — green badge above means everything
builds clean.
All timing constants assume 1 MHz (ATmega32 default internal RC fuse setting). Scale delay-loop counts and timer preloads by 8 if running at 8 MHz, or set the CLKDIV8 fuse to stay at 1 MHz.