school


# ADC-USART/LCD-Interrupt-Mode

#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "lcd.h"  // Für LCD-Ausgabe (optional)
 
volatile uint16_t adc_value = 0;  // Globaler ADC-Wert
volatile uint8_t new_data = 0;    // Flag, um neue Daten zu signalisieren
 
void USART_init(uint16_t ubrr) {
    UBRR0 = ubrr;                      // Baudrate setzen
    UCSR0B |= (1 << TXEN0);            // Transmitter aktivieren
    UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01);  // 8 Datenbits, 1 Stoppbit
}
void USART_send_char(uint8_t data) {
    while (!(UCSR0A & (1 << UDRE0)));  // Warten, bis das Register leer ist
    UDR0 = data;
}
void USART_send_string(const char *str) {
    while (*str) {
        USART_send_char(*str);
        str++;
    }
}
void ADC_init() {
    ADMUX |= (1 << REFS0) | (1 << MUX2) | (1 << MUX0);  // Referenzspannung und Kanal ADC5 (PC5)
    ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Prescaler 128 (125 kHz)
    ADCSRA |= (1 << ADIE) | (1 << ADEN);  // ADC-Interrupt und ADC aktivieren
}
ISR(ADC_vect) {
    adc_value = ADC;  // ADC-Wert speichern
    new_data = 1;     // Flag setzen, um neue Daten zu signalisieren
}
int main(void) {
    char buffer[16];  // Puffer für den formatieren String
    float voltage;
    // USART und ADC initialisieren
    USART_init(103);  // 9600 Baud bei 16 MHz
    ADC_init();
    // LCD initialisieren (falls verwendet)
    lcd_init(LCD_DISP_ON);
    sei();  // Interrupts global aktivieren
    // Start der ersten ADC-Konvertierung
    ADCSRA |= (1 << ADSC);
    while (1) {
        if (new_data) {
            // Spannung berechnen
            voltage = (adc_value * 5.0) / 1023.0;
            // Wert in String umwandeln
            sprintf(buffer, "Volt: %.2fV\n", voltage);
            // USART-Ausgabe
            USART_send_string(buffer);
            // Optional: Ausgabe auf dem LCD
            lcd_clrscr();
            lcd_puts(buffer);
            new_data = 0;  // Flag zurücksetzen
            // Nächste ADC-Konvertierung starten
            ADCSRA |= (1 << ADSC);
        }
    }
    return 0;
}

# ADC-USART/LCD-Polling-Mode

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h> 
 
uint16_t ADC_read() {
	// Start conversion
	ADCSRA |= (1 << ADSC);
	// warten bis Konvertierung fertig ist
	while (ADCSRA & (1 << ADSC));
	// ADC-Wert
	return ADC;
}
void USART_send_char(uint8_t data) {
	// Warten, bis das UDR0-Register leer ist
	while (!(UCSR0A & (1 << UDRE0)));
	UDR0 = data;
}
void USART_send_string(uint8_t *str) {
	while (*str) {
		USART_send_char(*str);
		str++;
	}
}
int main(void) {
	// USART konfigurieren: 9600 Baud, 8 Datenbits, 1 Stoppbit
	UBRR0 = 103;
	UCSR0B |= (1 << TXEN0);
	UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01);
	
	// ADC auf analoge Eingaben von PORTC5 hören lassen
	ADMUX |= (1 << REFS0) | (1 << MUX2) | (1 << MUX0);
	// ADC prescaler auf 128 (16MHz Taktfreq., ADC Takt auf 125kHz)
	ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
	while (1) {
		// ADC-Wert einlesen
		uint16_t adc_value = ADC_read();
		
		// Spannung berechnen
		float voltage = (adc_value * 5.0) / 1023.0;
		
		// Float-Wert in String umwandeln
		// Floating-Point Error "?"
		uint8_t buffer[16];
		sprintf(buffer, "Volt: %.2fV\n ", voltage);
		// String über USART senden
		USART_send_string(buffer);
		_delay_ms(1000);
	}
	return 0;
}


# Digital I/O

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include "lcd.h"
 
int main(void)
{
	// PB0 als Ausgang setzen
	DDRB |= (1 << DDB0);
	// Pull-up Widerstand von Button - bleibt HIGH, solange nicht gedrückt wird
	PORTB |= (1 << PORTB1);
 
    while (1) 
    {				
		// PINB - aktuellen Zustand von Port B lesen
		// wenn PINB == 0, LED leuchtet; PINB & (1 << PINB1) == 1; 
		if (!(PINB & (1 << PINB1)))
		{
			PORTB |= (1 << PORTB0);
		} 
		else 
		{ 
			//PORTB = PORTB & ~(1 << PORTB0);
			PORTB &= ~(1 << PORTB0); 
		}
		_delay_ms(100);
    }
	return 0;
}
 

# LCD


# Timer

#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "lcd.h"
 
// Globale Variable zum Speichern des ADC-Werts
volatile uint16_t adc_value = 0;
// ADC-Interrupt Service Routine
ISR(ADC_vect) {
    adc_value = ADC; // Speichere den ADC-Wert in der globalen Variable
}
// Timer0 Overflow Interrupt Service Routine
ISR(TIMER0_OVF_vect) {
    // Der Timer löst automatisch den ADC-Start aus, kein manuelles Starten nötig.
}
 
void ADC_init(void) {
    // ADC konfigurieren: AVcc als Referenz, Kanal ADC5 (PC5)
    ADMUX |= (1 << REFS0) | (1 << MUX2) | (1 << MUX0);
    // ADC aktivieren, Auto Trigger Modus, Interrupt erlauben, Prescaler auf 128
    ADCSRA |= (1 << ADEN) | (1 << ADATE) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
    // Trigger-Quelle: Timer0 Overflow
    ADCSRB = (0 << ADTS2) | (0 << ADTS1) | (1 << ADTS0);
    // Erste Konvertierung starten
    ADCSRA |= (1 << ADSC);
}
void Timer0_init(void) {
    // Timer0 konfigurieren: Normal Mode, Prescaler 1024
    TCCR0A = 0x00; // Normal Mode
    TCCR0B |= (1 << CS02) | (0 << CS01) | (1 << CS00); // Prescaler auf 1024
    
    // Timer Overflow Interrupt aktivieren
    TIMSK0 |= (1 << TOIE0);
}
int main(void) {
    // LCD initialisieren
    lcd_init(LCD_DISP_ON);
    lcd_clrscr();
    // ADC und Timer0 initialisieren
    ADC_init();
    Timer0_init();
 
    // Globale Interrupts aktivieren
    sei();
    char buffer[16];
    while (1) {
        // ADC-Wert auf LCD ausgeben
        float voltage = (adc_value * 5.0) / 1023.0;
        sprintf(buffer, "Volt: %.2fV", voltage);
        lcd_clrscr();
        lcd_puts(buffer);
        _delay_ms(500);
    }
}