2.14) Simple C Programs: Decision Making and Code Conversion in AVR

posted by Hamid Sayyed • November 11, 2025 0 Comments

In any embedded system, decision making plays a vital role in determining how a microcontroller reacts to external conditions. Whether it is checking a switch, controlling LEDs, comparing sensor values, or executing different parts of code depending on logic — decision making is everywhere. In C programming for AVR microcontrollers, decisions are made using conditional statements like if, if-else, nested if, switch, and conditional operators. These allow the program to choose between two or more paths based on specific conditions. Along with decision making, another essential concept is code conversion — converting numeric values to their equivalent display forms such as BCD, ASCII, or seven-segment codes. This is highly useful in digital displays, embedded counters, and measuring instruments. In this post, we will study both — how decision making works in AVR C programs and how to perform code conversions efficiently.

1. Decision Making in C for AVR

The concept of decision making means executing certain statements only when a specific condition is true. The microcontroller continuously checks conditions using logic comparisons, and depending on results, it executes or skips certain parts of code. This helps in creating smart and interactive embedded systems.

StatementSyntaxPurpose
ifif(condition){...}Executes code when condition is true.
if-elseif(cond){...} else {...}Executes one of two blocks.
Nested ifif(cond1){if(cond2){...}}Tests multiple conditions.
switchswitch(value){case 1:...; break;}Executes code based on value match.
?:(condition) ? expr1 : expr2;Short form of if-else.

2. Example: Controlling LED Using Decision Statement

The following simple AVR program turns an LED ON when a button is pressed, and OFF otherwise. It uses the if statement for decision making.

#include <avr/io.h>

int main(void)
{
    DDRB = 0xFF;   // Set PORTB as output (LED)
    DDRD = 0x00;   // Set PORTD as input (Switch)

    while(1)
    {
        if(PIND & (1<<PD0))     // Check if switch connected to PD0 is pressed
            PORTB = 0xFF;        // Turn ON LED
        else
            PORTB = 0x00;        // Turn OFF LED
    }
}

This is one of the most common examples in embedded labs. Here, the microcontroller reads logic level from the input pin and decides the output accordingly.

Note: Always configure input pins properly and use pull-up resistors to avoid floating inputs during testing.

3. Using Nested and Multiple Conditions

Sometimes, the system needs to make decisions based on more than one input or condition. This is where nested if or else if chains are useful.

#include <avr/io.h>

int main(void)
{
    DDRB = 0xFF;   // Output LEDs
    DDRD = 0x00;   // Input switches

    while(1)
    {
        if(PIND & (1<<PD0))
            PORTB = 0x01;   // LED1 ON
        else if(PIND & (1<<PD1))
            PORTB = 0x02;   // LED2 ON
        else
            PORTB = 0x00;   // All OFF
    }
}

This logic allows the microcontroller to check multiple switches and light up different LEDs depending on which switch is pressed.

4. Switch Case Example

The switch-case statement is particularly useful when multiple discrete values need to be checked — for example, selecting modes or functions.

#include <avr/io.h>

int main(void)
{
    uint8_t mode = 2;
    DDRB = 0xFF;

    switch(mode)
    {
        case 1: PORTB = 0x01; break;
        case 2: PORTB = 0x03; break;
        case 3: PORTB = 0x07; break;
        default: PORTB = 0x00; break;
    }

    while(1);
}

Here, depending on the mode value, a particular pattern of LEDs glows. The switch structure is efficient and easier to read compared to multiple if-else statements.

5. Introduction to Code Conversion

In many applications, numeric data needs to be displayed in a human-readable format. For instance, a sensor value stored in binary or hexadecimal form must be converted into decimal or ASCII form for display on an LCD or seven-segment display. This process is called code conversion.

  • Binary to BCD (Binary Coded Decimal)
  • BCD to ASCII
  • Binary to ASCII

AVR C makes these conversions simple through arithmetic and ASCII manipulation. Let’s understand each type with examples.

6. Binary to BCD Conversion

Binary Coded Decimal represents each decimal digit separately. Example: Decimal 59 → BCD = 0101 1001.

#include <avr/io.h>

uint8_t binary_to_bcd(uint8_t binary)
{
    uint8_t tens = binary / 10;
    uint8_t ones = binary % 10;
    return (tens << 4) | ones;
}

int main(void)
{
    uint8_t val = 59;
    uint8_t result = binary_to_bcd(val);  // Result = 0x59
    while(1);
}

This conversion is important for seven-segment and digital clock applications where each digit is controlled individually.

7. BCD to ASCII Conversion

ASCII codes are required when displaying numbers or characters on LCDs or serial monitors. The ASCII value of digit '0' is 48 in decimal (0x30 in hexadecimal).

char bcd_to_ascii(uint8_t digit)
{
    return digit + 0x30;  // Convert numeric value to ASCII
}

For example, if digit = 7, function returns 0x37, which corresponds to ASCII '7'.

8. Binary to ASCII Conversion Example

Binary to ASCII conversion is often used when sending numerical data through UART or displaying it on LCD.

void binary_to_ascii(uint16_t value, char *buffer)
{
    buffer[3] = (value % 10) + 0x30;
    value /= 10;
    buffer[2] = (value % 10) + 0x30;
    value /= 10;
    buffer[1] = (value % 10) + 0x30;
    value /= 10;
    buffer[0] = (value % 10) + 0x30;
}

This routine separates digits and converts each to ASCII for display — an essential routine used in embedded LCD or serial communication projects.

Practical Tip: Code conversion functions are commonly used in digital voltmeters, clocks, and counters where values from ADC or timers must be displayed as readable digits.

9. Summary Table

ConceptPurposeExample
Decision MakingControl flow based on conditionif(PIND & (1<<PD0))
Switch-CaseMultiple choicesswitch(mode){...}
Binary to BCDDisplay digits individually(tens<<4)|ones
BCD to ASCIIShow number on LCDdigit + 0x30

Conclusion

Decision making and code conversion are two essential pillars of AVR C programming. Decision statements make the system intelligent and reactive, while code conversion helps interface data with humans through displays. By mastering these concepts, students can create interactive systems like counters, digital clocks, smart sensors, and control devices. Practicing both in simulation tools like Proteus or on real hardware such as ATmega16 will greatly strengthen your understanding of embedded C programming.

Comments

Post a Comment

Subscribe to Post Comments [Atom]