CloudInquirer
Jul 23, 2026

c code examples for avr

M

Mr. Maci Cole

c code examples for avr

c code examples for avr are essential for both beginners and experienced embedded developers aiming to implement efficient and reliable solutions on AVR microcontrollers. AVR microcontrollers, developed by Atmel (now part of Microchip Technology), are widely used in embedded systems due to their simplicity, low power consumption, and extensive community support. In this article, we will explore various C code examples tailored for AVR microcontrollers, covering fundamental concepts such as GPIO control, timer usage, interrupt handling, ADC conversions, and communication protocols. Whether you're just starting or looking to deepen your understanding, these examples will serve as valuable references for your embedded projects.

Understanding the AVR Architecture

Before diving into code examples, it’s important to understand the basics of AVR microcontroller architecture.

Key Features of AVR Microcontrollers

  • 8-bit RISC architecture for efficient processing
  • Multiple I/O ports for interfacing with peripherals
  • Built-in timers and counters for precise timing
  • Analog-to-Digital Converters (ADC)
  • Communication interfaces such as UART, SPI, and I2C
  • Low Power modes for energy-efficient applications

Basic C Code Examples for AVR

Here are some fundamental C code snippets demonstrating common tasks on AVR microcontrollers.

1. Setting Up GPIO Pins

Controlling General Purpose Input/Output (GPIO) pins is fundamental in embedded development.

```c

include

void setup_gpio(void) {

// Set PORTB pin 0 as output

DDRB |= (1 << DDB0);

// Set PORTD pin 2 as input

DDRD &= ~(1 << DDD2);

}

void turn_on_led(void) {

// Turn on LED connected to PORTB0

PORTB |= (1 << PORTB0);

}

void turn_off_led(void) {

// Turn off LED connected to PORTB0

PORTB &= ~(1 << PORTB0);

}

```

This simple example initializes PORTB0 as an output pin for an LED and provides functions to turn it on and off.

2. Blinking an LED with Delay

Creating a blinking LED involves toggling a GPIO pin with delays.

```c

include

include

void blink_led(void) {

DDRB |= (1 << DDB0); // Set PORTB0 as output

while (1) {

PORTB ^= (1 << PORTB0); // Toggle LED

_delay_ms(500); // Wait 500ms

}

}

```

Using `_delay_ms()` from ``, this code toggles an LED every half second indefinitely.

Using Timers for Precise Timing

Timers are crucial for creating delays, PWM signals, or measuring events.

3. Timer/Counter0 Overflow Interrupt Example

Configure Timer0 to generate an interrupt on overflow.

```c

include

include

void timer0_init(void) {

TCCR0 |= (1 << CS02); // Prescaler 256

TIMSK |= (1 << TOIE0); // Enable overflow interrupt

sei(); // Enable global interrupts

}

ISR(TIMER0_OVF_vect) {

// Code to execute on timer overflow

// e.g., toggle an LED

PORTB ^= (1 << PORTB0);

}

```

This sets up Timer0 to overflow periodically, toggling an LED each time.

Handling Interrupts

Interrupts allow your program to respond quickly to external or internal events.

4. External Interrupt on INT0 Pin

Configure an external interrupt triggered on a rising edge.

```c

include

include

void ext_interrupt_init(void) {

EICRA |= (1 << ISC01) | (1 << ISC00); // Rising edge

EIMSK |= (1 << INT0); // Enable INT0

sei(); // Enable global interrupts

}

ISR(INT0_vect) {

// Toggle LED when external interrupt occurs

PORTB ^= (1 << PORTB0);

}

```

Connect an external button or signal to the INT0 pin (PD2) to trigger this interrupt.

Analog-to-Digital Conversion (ADC)

ADC is used to read analog sensors like temperature or light sensors.

5. Reading an Analog Sensor

Sample code for initializing and reading ADC value.

```c

include

void adc_init(void) {

ADMUX = (1 << REFS0); // Reference voltage on AVcc

ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Enable ADC, prescaler 128

}

uint16_t adc_read(uint8_t channel) {

ADMUX = (ADMUX & 0xF8) | (channel & 0x07); // Select channel

ADCSRA |= (1 << ADSC); // Start conversion

while (ADCSRA & (1 << ADSC)); // Wait for conversion

return ADC; // Return 10-bit ADC value

}

```

Call `adc_read(channel)` where channel is between 0 and 7 to get sensor readings.

Serial Communication: UART Example

UART enables communication with other devices like PCs or sensors.

6. Initialize UART

```c

include

void uart_init(unsigned int baud) {

unsigned int ubrr = F_CPU / 16 / baud - 1;

UBRR0H = (ubrr >> 8);

UBRR0L = ubrr;

UCSR0B = (1 << TXEN0); // Enable transmitter

UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8 data bits, 1 stop bit

}

```

7. Sending Data via UART

```c

void uart_transmit(char data) {

while (!(UCSR0A & (1 << UDRE0))); // Wait until buffer is empty

UDR0 = data; // Send data

}

void uart_print(const char str) {

while (str) {

uart_transmit(str++);

}

}

```

Use these functions to send strings or characters over UART.

Implementing PWM for Motor Control

Pulse Width Modulation (PWM) is commonly used to control motor speed or LED brightness.

8. Setting Up PWM on Timer1

Configure Timer1 for Fast PWM mode.

```c

include

void pwm_init(void) {

// Set Fast PWM mode with ICR1 as TOP

TCCR1A |= (1 << WGM11) | (1 << WGM10);

TCCR1B |= (1 << WGM13) | (1 << WGM12);

// Clear OC1A on compare match

TCCR1A |= (1 << COM1A1);

// Set prescaler to 8

TCCR1B |= (1 << CS11);

// Set ICR1 for frequency

ICR1 = 19999; // For 50Hz PWM (common for servos)

}

void pwm_set_duty_cycle(uint8_t duty) {

OCR1A = (duty ICR1) / 100; // duty in percentage

}

```

Adjust `OCR1A` to control motor speed or servo position.

Best Practices and Tips

To develop robust AVR applications, consider the following:

  • Always initialize peripherals before use to avoid undefined behavior.
  • Use macros and constants for register bits to improve code readability.
  • Implement proper debouncing for push buttons when using external interrupts.
  • Utilize interrupt vectors carefully; keep interrupt routines short.
  • Manage power consumption by utilizing sleep modes when idle.
  • Test code incrementally; verify each module before integration.

Tools and Development Environment

To develop and compile AVR C code effectively, consider these tools:

  • AVR-GCC compiler – Open-source compiler for AVR microcontrollers.
  • Atmel Studio – Integrated development environment (IDE) with simulation capabilities.
  • AVRDUDE – Command-line utility for flashing firmware onto AVR devices.
  • Programmers – Such as USBasp or AVRISP mkII for programming the microcontroller.

Conclusion

C code examples for AVR microcontrollers form the foundation of embedded development, enabling you to control hardware, handle real-time events, and communicate with peripherals. Mastering GPIO control, timers, interrupts, ADC, UART, and PWM through practical code snippets will accelerate your learning curve and empower


C Code Examples for AVR: Unlocking the Power of Microcontroller Programming

In the world of embedded systems, microcontrollers are the backbone of countless devices—from simple household appliances to complex industrial machinery. Among the myriad of microcontrollers available, AVR stands out as a popular choice due to its affordability, ease of use, and robust community support. Central to harnessing the capabilities of AVR microcontrollers is the ability to write efficient, reliable C code. This article provides an in-depth exploration of C programming for AVR, showcasing practical code examples and best practices that will empower developers—whether beginners or seasoned engineers—to craft effective embedded solutions.


Understanding the AVR Ecosystem

Before diving into code examples, it's essential to understand what makes AVR microcontrollers unique and how C programming plays a pivotal role.

What Are AVR Microcontrollers?

AVR microcontrollers are a family of 8-bit RISC (Reduced Instruction Set Computing) chips developed by Atmel (now part of Microchip Technology). Known for their simplicity and performance, AVR chips like the ATmega328 (famous for powering Arduino Uno) have become staples in hobbyist and professional projects alike.

Key features include:

  • Harvard architecture (separate program and data memories)
  • Rich peripheral sets (timers, ADC, UART, SPI, I2C)
  • On-chip Flash memory for code storage
  • Low power consumption options
  • Wide community and extensive resource availability

The Role of C in AVR Development

While AVR microcontrollers can be programmed in assembly language, C offers a much more accessible and maintainable approach. It abstracts hardware complexities while providing low-level access when needed, making it ideal for embedded development.

Advantages of using C for AVR:

  • Portability across different AVR chips
  • Easier to write, read, and maintain code
  • Compatibility with many development environments and toolchains (e.g., Atmel Studio, avr-gcc)
  • Access to a rich set of libraries and example codes

Setting Up the Development Environment

To effectively program AVR microcontrollers in C, you need a suitable development environment.

Recommended Tools:

  • avr-gcc: The GNU Compiler Collection for AVR
  • AVRDUDE: Utility for programming AVR devices
  • Programmer hardware: USBasp, AVRISP mkII, or Arduino as an ISP programmer
  • IDE options: Atmel Studio (Windows), Visual Studio Code with PlatformIO, or command-line setup

Basic Workflow:

  1. Write C code using your preferred editor.
  2. Compile the code into a hex file with avr-gcc.
  3. Upload the hex file to the microcontroller using AVRDUDE.
  4. Test and debug your code.

Core C Code Examples for AVR

Let's examine some fundamental and advanced C programming techniques tailored for AVR microcontrollers. These examples are designed to be comprehensive, illustrating best practices and common use cases.

1. Blinking an LED: The Classic Hello World

Objective: Toggle an LED connected to a GPIO pin with a delay.

```c

include

include

define LED_PIN PB0

int main(void) {

// Set PB0 as output

DDRB |= (1 << LED_PIN);

while(1) {

// Turn LED on

PORTB |= (1 << LED_PIN);

_delay_ms(500);

// Turn LED off

PORTB &= ~(1 << LED_PIN);

_delay_ms(500);

}

return 0;

}

```

Explanation:

  • `DDRB` register configures the direction of port B pins. Setting `DDRB |= (1 << PB0)` makes PB0 an output.
  • `PORTB` controls the output state. Setting the bit turns the LED on; clearing turns it off.
  • `_delay_ms()` provides a simple blocking delay.

Best Practices:

  • Use macros for pin definitions for clarity.
  • Keep delays short or use timers for more precise control.

2. Using Timers for Precise Timing

Objective: Generate a PWM signal to control LED brightness.

```c

include

void timer_init(void) {

// Set timer1 to Fast PWM mode, non-inverting

TCCR1A |= (1 << COM1A1) | (1 << WGM11);

TCCR1B |= (1 << WGM12) | (1 << WGM13) | (1 << CS10);

// Set OCR1A for duty cycle

OCR1A = 128; // 50% duty cycle

}

int main(void) {

// Configure PB1 as output (OC1A)

DDRB |= (1 << DDB1);

timer_init();

while(1) {

// PWM runs automatically

// You can modify OCR1A to change brightness

}

return 0;

}

```

Explanation:

  • Timer1 is set in Fast PWM mode with ICR1 as top.
  • OCR1A controls duty cycle; changing its value adjusts brightness.
  • The PWM signal is output on PB1.

Advantages:

  • Precise, hardware-based timing reduces CPU load.
  • Useful for motor control, LED dimming, and signal generation.

3. Reading Analog Inputs with ADC

Objective: Read a potentiometer connected to an ADC pin and send the value via UART.

```c

include

include

void adc_init(void) {

ADMUX = (1 << REFS0); // Use AVcc as reference

ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Enable ADC, prescaler 128

}

uint16_t adc_read(uint8_t channel) {

ADMUX = (ADMUX & 0xF8) | (channel & 0x07); // Select ADC channel

ADCSRA |= (1 << ADSC); // Start conversion

while (ADCSRA & (1 << ADSC)); // Wait for completion

return ADC;

}

void uart_init(unsigned int ubrr) {

UBRR0H = (ubrr >> 8);

UBRR0L = ubrr & 0xFF;

UCSR0B = (1 << TXEN0);

UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8 data bits, 1 stop bit

}

void uart_transmit(char data) {

while (!(UCSR0A & (1 << UDRE0)));

UDR0 = data;

}

void uart_print_uint16(uint16_t value) {

char buffer[6];

itoa(value, buffer, 10);

for(int i = 0; buffer[i] != '\0'; i++) {

uart_transmit(buffer[i]);

}

}

int main(void) {

adc_init();

uart_init(103); // 9600 baud for 16MHz clock

while(1) {

uint16_t adc_value = adc_read(0); // Read channel 0

uart_print_uint16(adc_value);

uart_transmit('\n');

_delay_ms(500);

}

return 0;

}

```

Explanation:

  • ADC initialization sets reference voltage and prescaler.
  • ADC reading involves selecting the channel, starting conversion, and reading the result.
  • UART setup enables serial communication.
  • The main loop reads analog input, converts the value to string, and transmits it.

Use Cases:

  • Sensor data acquisition
  • User input via potentiometer or sensor

4. Interrupt-Driven Event Handling

Objective: Detect a button press with an external interrupt and toggle an LED.

```c

include

include

define BUTTON_PIN PD2

define LED_PIN PB0

volatile uint8_t button_pressed = 0;

ISR(INT0_vect) {

button_pressed = !button_pressed;

if (button_pressed) {

PORTB |= (1 << LED_PIN);

} else {

PORTB &= ~(1 << LED_PIN);

}

}

void interrupt_init(void) {

EICRA |= (1 << ISC01); // Falling edge triggers INT0

EIMSK |= (1 << INT0); // Enable INT0

sei(); // Enable global interrupts

}

int main(void) {

DDRB |= (1 << LED_PIN); // LED output

DDRD &= ~(1 << BUTTON_PIN); // Button input

PORTD |= (1 << BUTTON_PIN); // Enable pull-up resistor

interrupt_init();

while(1) {

// Main loop can perform other tasks

}

return 0;

}

```

Explanation:

  • External interrupt INT0 is configured to trigger on falling edge (button press).
  • ISR toggles the LED state.
  • Global interrupt enable (`sei()`) is essential.

Use Cases:

  • Event detection
  • Real-time control

Additional Tips and Best Practices

Modular Code: Break down your code into functions for initialization, peripheral control, and main logic. This enhances readability and maintainability.

Use of Libraries: Leverage

QuestionAnswer
What is a simple example of blinking an LED using C on an AVR microcontroller? A basic example involves configuring a pin as an output and toggling it with delays. For instance: ```c include <avr/io.h> include <util/delay.h> int main(void) { DDRB |= (1 << DDB0); // Set PB0 as output while (1) { PORTB ^= (1 << PORTB0); // Toggle PB0 _delay_ms(500); // Wait 500ms } return 0; } ```
How do I configure ADC input on an AVR microcontroller using C? To configure ADC, set the ADMUX and ADCSRA registers. Example: ```c include <avr/io.h> void ADC_init() { ADMUX = (1 << REFS0); // Use AVcc as reference ADCSRA = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0); // Enable ADC, prescaler 8 } uint16_t ADC_read(uint8_t channel) { ADMUX = (ADMUX & 0xF8) | (channel & 0x07); // Select channel ADCSRA |= (1 << ADSC); // Start conversion while (ADCSRA & (1 << ADSC)); // Wait for completion return ADC; // Return ADC value } ```
Can you provide a C example for UART serial communication on AVR? Yes, here's an example to initialize UART and send a string: ```c include <avr/io.h> void UART_init(unsigned int baud) { UBRR0H = (baud >> 8); UBRR0L = baud & 0xFF; UCSR0B = (1 << TXEN0); // Enable transmitter UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8 data bits } void UART_send_char(char data) { while (!(UCSR0A & (1 << UDRE0))); UDR0 = data; } void UART_send_string(const char str) { while (str) { UART_send_char(str++); } } int main() { UART_init(9600); UART_send_string("Hello AVR UART\r\n"); while (1) {} } ```
How do I implement PWM on an AVR microcontroller using C? To generate PWM, set up a timer in Fast PWM mode. Example for Timer/Counter0: ```c include <avr/io.h> void PWM_init() { DDRD |= (1 << PD6); // Set PD6 as output (OC0) TCCR0A = (1 << WGM00) | (1 << WGM01) | (1 << COM01); // Fast PWM, non-inverting TCCR0B = (1 << CS00); // No prescaling } void PWM_set_duty(uint8_t duty) { OCR0A = duty; // Set duty cycle (0-255) } int main() { PWM_init(); while (1) { for (uint8_t duty = 0; duty < 255; duty++) { PWM_set_duty(duty); _delay_ms(10); } } } ```
What is an example of implementing a delay function in C for AVR? You can use the _delay_ms() function from util/delay.h. Example: ```c include <util/delay.h> int main() { while (1) { // Do something _delay_ms(1000); // Delay 1 second } } ``` > Note: Ensure your delay is within the maximum delay supported by the function, or use multiple calls for longer delays.
How can I read a push button input with C on an AVR? Configure the pin as input with pull-up resistor enabled. Example: ```c include <avr/io.h> int main() { DDRC &= ~(1 << PINC0); // Set PC0 as input PORTC |= (1 << PINC0); // Enable pull-up while (1) { if (!(PINC & (1 << PINC0))) { // Button pressed } } } ```
How do I toggle an LED connected to an AVR pin in C? Set the pin as output and toggle its state: ```c include <avr/io.h> int main() { DDRB |= (1 << DDB0); // Set PB0 as output while (1) { PORTB ^= (1 << PORTB0); // Toggle LED _delay_ms(500); } } ```
What is an example of using interrupts on an AVR microcontroller with C? Example of external interrupt on INT0: ```c include <avr/io.h> include <avr/interrupt.h> ISR(INT0_vect) { // Interrupt service routine PORTB ^= (1 << PORTB0); // Toggle LED } void interrupt_init() { EICRA |= (1 << ISC01); // Trigger on falling edge EIMSK |= (1 << INT0); // Enable INT0 } int main() { DDRB |= (1 << DDB0); // Set PB0 as output interrupt_init(); sei(); // Enable global interrupts while (1) {} } ```
Can you provide a complete C example for setting up and using a timer interrupt on AVR? Yes, here is an example using Timer/Counter1 overflow interrupt: ```c include <avr/io.h> include <avr/interrupt.h> volatile uint8_t overflow_count = 0; ISR(TIMER1_OVF_vect) { overflow_count++; if (overflow_count >= 61) { // Approximately 1 second if prescaler is set // Do something every second overflow_count = 0; PORTB ^= (1 << PORTB0); // Toggle LED } } void timer_init() { TCCR1B |= (1 << CS12); // Prescaler 256 TIMSK1 |= (1 << TOIE1); // Enable overflow interrupt } int main() { DDRB |= (1 << DDB0); // Set PB0 as output timer_init(); sei(); // Enable global interrupts while (1) {} } ```

Related keywords: AVR programming, embedded C, microcontroller code, AVR assembly, AVR development, C language AVR, AVR tutorials, AVR project code, AVR firmware, AVR example projects