This is an old revision of the document!


3 Levels of Programming: C++, Libraries, Assembler

Programming AVR microcontrollers can be divided into three levels: C++, libraries, and assembler. Each of these levels offers distinct benefits and is utilized according to the project's specific requirements.

  • C++ is a high-level language that allows programmers to write code in a more abstract and understandable way. Using C++ for AVR enables advanced features such as object-oriented programming, inheritance, and polymorphism. This makes the code more modular and easier to maintain. Compilers like AVR-GCC convert C++ code into machine code that the microcontroller can execute.
  • Libraries are sets of predefined functions and procedures that facilitate programming AVR microcontrollers. An example is the AVR Libc library, which provides functions for I/O, memory management, and mathematical operations. Using libraries enables rapid application development without writing code from scratch. Libraries are particularly useful in projects that require frequent use of standard functions.
  • Assembler is a low-level language that allows direct programming of the AVR microcontroller. Writing code in assembler gives full control over the hardware and allows for performance optimization. However, programming in assembler requires a deep understanding of the microcontroller's architecture and is more complex than programming in C++. An assembler is often used in critical applications where every clock cycle counts.

The choice of programming level depends on the project's specifics. C++ is ideal for creating complex applications, libraries facilitate rapid prototyping, and assembler provides maximum control and performance. Each of these levels has its place in AVR microcontroller programming.''

Some AVR assembly examples for the Arduino Uno (ATmega328P), ready to drop directly into the Arduino IDE using inline assembly - asm volatile().

Examples

Blink inbuilt LED on pin 13 (port PB5) using assembly

void setup() {
  // Set PB5 (pin 13) as output  // if DDRB (Data Direction Register B) = 1, PORTB is output 
  asm volatile("sbi 0x04, 5");   // DDRB |= (1<<5)
}
void loop() {
  asm volatile("sbi 0x05, 5");   // LED ON  (PORTB |= (1<<5))
  delay(500);
  asm volatile("cbi 0x05, 5");   // LED OFF (PORTB &= ~(1<<5))
  delay(500);
}

For Arduino Uno (ATmega328P):

  • DDRB has address 0x04
  • PORTB has address 0x05

Add two numbers using AVR registers

void setup() {
  Serial.begin(9600);
  uint8_t a = 7, b = 9, result;
  asm volatile(
    "mov r24, %1\n"   // r24 = a
    "mov r25, %2\n"   // r25 = b
    "add r24, r25\n"  // r24 = a + b
    "mov %0, r24\n"   // result = r24
    : "=r"(result)
    : "r"(a), "r"(b)
    : "r24", "r25", "cc" 
  );
  Serial.println(result);
}
void loop() {}

Read digital input (PD2, bit 2 on PORTD)

void setup() {
  Serial.begin(9600);
  asm volatile("cbi 0x0A, 2");   // DDRD &= ~(1<<2) → PD2 as input
}
void loop() {
  uint8_t value;
  asm volatile(
    "in %0, 0x09"     // Read PIND
    : "=r"(value)
  );
  Serial.println(value & (1<<2));
  delay(200);
}
en/multiasm/piot/chapter_4_9.1768823862.txt.gz · Last modified: by marcin
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0