This is my playground for AVR programming where I rewrite my old AVR programs and practice bare-metal embedded programming skills. It could be beneficial for you as well.
To prepare your build environment first read this tutorial:
All of the programs in this repository are written for Atmega328 on Arduino Uno / Nano but without using Arduino Core and just in bare-metal. I used the Arduino bootloader on Atmega328 and AVRDUDE to write my programs on Atmega328. So there is no need for any external programmer.
Note that Atmega328 is an old device and NOT RECOMMENDED FOR NEW DESIGNS. I am using it only to practice programming.
Almost all projects are configured for 16MHz external crystal on Arduino board. You can see each project's configuration in src/my/project_config.h
Blinky is the "Hello World!" of embedded systems :)
Redirect STDIO streams to UART0 input and output so that you can write to serial port using printf()
and read using scanf()
Note 1: The implementation of printf() and scanf() is about 5KB in size, which is a problem for memory constrained systems.
Note 2: that if you are using Arduino Uno / Nano board, you do not need any external serial port to communicate with Atmega328, you can use the Arduino USB serial port to test the program. Just connect your board using USB port to your PC.
Implement precise timing functions millis()
, micros()
, precise_delay_ms()
, precise_delay_us()
Test HY-SRF05 ultrasonic sensor using my precise_timing
library.
Test a 20PPR incremental (quadrature) rotary encoder. A quadrature encoder gives 4x resolution using this method. External interrupts (INT0 and INT1) are used for decoding the encoder signals.
Emulate a 20PPR incremental (quadrature) rotary encoder using TIMER0 and TIMER2 outputs and decode the generated signals. Decoded speed should be 91 RPM (122 pulses per second).
Use ADC to measure VCC voltage without using any I/O pin or any external component.
- AN2447: Measure VCC/Battery Voltage Without Using I/O Pin on tinyAVR and megaAVR
- AVR126: ADC of megaAVR® in Single-Ended Mode
Capacitance meter for 470uF to 18pF range with the highest accuracy for small capacitors.
Low power control of an LED using a button. Exits Sleep on button press, turns on an LED and goes back to Sleep. On button release, exits Sleep, turns off the LED and goes back to Sleep.
- AVR® Low Power Sleep Modes
- Getting Started with GPIO
- AVR®: Using Pin Change Interrupts
- <avr/interrupt.h>: Interrupts
Testing software reset using watchdog timer. Configured watchdog timer for a timeout of 4 seconds. Reset the watchdog timer 5 times when it reaches 3.9 seconds to avoid triggering a MCU reset. Eventually, triggered the MCU reset by allowing the watchdog timer to reach its timeout.
- Software Reset
- AVR® Watchdog Timer
- <avr/wdt.h>: Watchdog timer handling
- AVR132: Using the Enhanced Watchdog Timer
Determining the reset source (cause) of the MCU during startup.
- ATmega48A/PA/88A/PA/168A/PA/328/P Datasheet
- Introduction to Bare Metal Programming in Arduino Uno
- Developing with the 8-bit AVR® MCU
- Fundamentals of Microcontrollers - Arduino bare-metal breakdown
- Using Standard IO streams in AVR GCC
- avr-libc - <stdio.h>: Standard IO facilities
- How do I create a static library for the AVR Atmega328p?
- avr-libc - A simple project
- avr-libc - How to Build a Library
- avr-millis-function
- Nested Interrupts
- avr_insights