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); } }