====== 9 UART und Terminal ====== Bei der Programmierung wünscht man sich häufig die Möglichkeit Daten des Mikrocontrollers irgendwo darzustellen. * Wird eine reale Hardware verwendet, kann mit Hilfe des Freeware Programms [[https://www.putty.org/|PuTTY]] leicht ein Terminal für die Kommunikation mit dem PC geöffnet werden. Zusätzlich wird dann noch ein USB-to-serial Adapter benötigt. * In der Simulation SimulIDE kann ein Terminalfenster direkt im unteren Bereich angezeigt werden. - [[https://www.mikrocontroller.net/articles/AVR-Tutorial:_UART|Tutorial zu UART auf mikrocontroller.net]], weiteres [[https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART|Tutorial zu UART auf mikrocontroller.net]] - [[https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter#Data_framing|Datenpaket für RX/TX]] - [[https://de.wikipedia.org/wiki/RS-232#Leitungsl%C3%A4nge_und_%C3%9Cbertragungsrate|Leitungslänge vs. Übertragungsrate]] ===== die einfache Art der Kommunikation ===== ==== Ziele ==== Nach dieser Lektion sollten Sie: - wissen, wie eine UART Kommunikation hergestellt wird ==== Video ==== {{youtube>-tFVvbUUco4?size=700x400}} {{youtube>r_5iVt3rcwA?size=700x400}} {{youtube>hCCGMMyTtK4?size=700x400}} {{drawio>UARTRegister.svg}} --> I. Vorarbeiten # - Laden Sie folgende Datei herunter: - {{microcontrollertechnik:9_temperatureuart_1.0.0.sim1}} - {{microcontrollertechnik:9_uart.hex}} - {{microcontrollertechnik:lcd_lib_de.h}} **Beachten Sie folgendes** * Es wird nun ein ATmega328 genutzt, d.h. das Programm ist nicht mehr kompatibel mit dem MiniMEXLE! * Überprüfen Sie die Pins und Ports des Displays. * Überprüfen Sie die Taktfrequenz. <-- --> Code mit Polling # ==== Code mit Polling ==== Dieses Unterkapitel ist z.Zt. in einem provisorischem Zustand. Variante mit Polling: {{microcontrollertechnik:9_uartpolling_temperature.c}} /* ---------------------------------------------------------------------------- Experiment 9: Temperaturmessung mit UART (Polling) ============= =============================== Dateiname: 9_Temperature.c Autoren : Tim Fischer Datum : 29.10.2020 Version : 0.1 Hardware: MEXLE2020 Ver. 1.0 oder hoeher AVR-USB-PROGI Ver. 2.0 Software: Entwicklungsumgebung: AtmelStudio 7.0 C-Compiler: AVR/GNU C Compiler 5.4.0 Funktion : Thermometer mit Anzeige der aktuellen Temperatur und der Maximaltemperatur im Betriebszeitraum in °C mit 1/10 Grad. Keine Tastenbedienung Displayanzeige: Start (fuer 2s): Betrieb: +----------------+ +----------------+ |- Experiment 8 -| |Temp. 18.5°C| | Temperature | |Maximum 21.6°C| +----------------+ +----------------+ Tastenfunktion: keine Jumperstellung: keine Fuses im uC: CKDIV8: Aus (keine generelle Vorteilung des Takts) Header-Files: lcd_lib_de.h (Library zur Ansteuerung LCD-Display Ver.1.3) Module 1) Taktgenerator 2) AD-Wandlung (Takt: 100 ms) 3) Umrechnung fuer Temperatur (Takt: 100 ms) 4) Anzeigetreiber (Takt: 1 s) 1) Das Modul "Taktgenerator" erzeugt den Takt von 100 ms fuer die AD-Wandlung und Umrechnung und einen zusaetzlichen Takt von 1 s fuer die Anzeige. Verwendung von Hardware-Timer 0 und T0 Overflow-Interrupt. Frequenzen: Quarzfrequenz 12,288 MHz. Timer-Vorteiler / 8 => 1,536 MHz Hardware-Timer /256 => 6 kHz / 166 µs Software-Vorteiler / 60 => 100 Hz / 10 ms Hundertstel-Zaehler / 10 => 10 Hz / 100 ms Zehntel-Zaehler / 10 => 1 Hz / 1 s 2) Das Modul "AD-Wandlung" wird durch den Takt 100 ms aufgerufen. Der AD-Wandler wird mit einem internen Takt von 96 kHz betrieben. Im Modul wird eine einzelne AD-Wandlung des Kanals ADC0 mit 10 Bit Aufloesung gestartet. Dort ist der NTC des Boards mit Vorwiderstand als temperaturabhaengiger Spannungsteiler bzw. Potentiometer angeschlossen. Als Referenzspannung wird die 5V-Versorgung verwendet. Das Ergebnis wird in der globalen Variable ad_wert gespeichert. 3) Das Modul "Umrechnung" wird nach der AD-Wandlung alle 100 ms gestartet. Der Ergebniswert des Moduls "AD_Wandlung" wird mit Hilfe einer Tabelle in einen entsprechenden Temperaturwert umgerechnet. In der Tabelle sind Temperaturwerte ueber aequidistante (Abstand = 16) AD-Werte aufgetragen. Die Werte dazwischen werden mit linearer Interpolation ermittelt. Weiterhin wird im Modul jede aktuelle Temperatur mit der gespeicherten maximalen Temperatur verglichen und der Maximalwert optional angepasst. 4) Das Modul "Anzeigetreiber" ist an den 1 s-Takt gekoppelt. Damit wird ein zu schnelles Umschalten der Anzeigewerte vermieden. Das Modul gibt die Werte der aktuellen und der maximalen Temperatur in 1/10 °C aus. Zwischen AD-Wandlung / Umrechnung und Anzeige kann spaeter noch eine Mittelwertsbildung mit 10 Werten eingefuegt werden. Die Kopplung der Module wird ueber global definierte Variable realisiert: 1-Bit-Variable: Takt 100 ms: Taktgenerator => AD-Wandlung => Umrechnung Takt 1 s: Taktgenerator => Anzeigetreiber 16-Bit-Variable: ad-wert AD-Wandlung => Umrechnung t-wert Umrechnung => Anzeige tmax-wert Umrechnung => Anzeige // ----------------------------------------------------------------------------*/ // Deklarationen ============================================================== // Festlegung der Quarzfrequenz #ifndef F_CPU // optional definieren #define F_CPU 8000000L // Simulation mit 8 MHz Quarz #endif // Include von Header-Dateien #include // Header-Dateien zum ATmega88 #include // Header-Datei fuer Interrupts #include // Header-Datei fuer Wartezeit #include "lcd_lib_de.h" // Header-Datei fuer LCD-Anzeige #include // Konstanten #define VORTEILER_WERT 60 #define HUNDERTSTEL_WERT 10 #define ZEHNTEL_WERT 10 #define ASC_NULL 0x30 // Das Zeichen '0' in ASCII #define ASC_FULL_STOP 0x2E // Das Zeichen ':' in ASCII #define UART_BUFFER_SIZE 10 // Buffersize für übertrgene Daten #define BAUD_RATE 9600L // Berechnungen für die Baudrate #define UBRR_VAL ((F_CPU+BAUD_RATE*8)/(BAUD_RATE*16)-1) // clever runden #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD_RATE-1000) // Fehler in Promille // Überprüfung der Baudrate und ob Fehler zu groß ist #if ((BAUD_ERROR>10) || (BAUD_ERROR<-10)) #error Systematischer Fehler der Baudrate zu hoch! #endif const int TEMP[45] = {521,499,479,459,440,422,404,388,371,354, 338,323,308,293,279,264,250,236,221,207, 193,179,165,151,137,122,108,93,78,63, 48,32,15,-1,-19,-38,-56,-77,-97,-121, -145,-173,-202,-237,-278}; // Die Tabellenwerte sind in 1/10 °C angegeben // Der erste Tabellenwert entspricht einem AD-Wert // von 256. Die Abstaende der AD-Werte sind 16 // Variable unsigned char vorteiler = VORTEILER_WERT; // Zaehlvariable Vorteiler unsigned char hundertstel = HUNDERTSTEL_WERT; unsigned char zehntel = ZEHNTEL_WERT; unsigned int adcValue = 0; // Variable fuer den AD-Wandlungswert int tValue = 0; // Variable fuer die Temperatur (in 1/10 °C) int tValueMax =-300; // Variable fuer maximale Temperatur (1/10 °C) bool takt10ms; // Bit-Botschaft alle 10 ms bool takt100ms; // Bit-Botschaft alle 100 ms bool takt1s; // Bit-Botschaft alle 1s char wort[UART_BUFFER_SIZE]; // Variable für die Ein- und Ausgabe von Wörtern und Zahlen //Funktionsprototypen void initTimer0 (void); void initAdc (void); void initDisplay (void); void doAdc (void); void calculateTemp (void); void refreshDisplayTemp(int tempValue, char line, char pos); void refreshDisplay (void); void initUart(void); // Initialisierung der UART-Register void putData(char *daten); // Daten senden uint8_t getData(void); // Daten empfangen // Hauptprogramm ============================================================== int main () { uint8_t bufferFilled = 0; // Flag für vollen Puffer initDisplay(); // Initialisierung LCD-Anzeige initTimer0(); // Initialisierung von Timer0 initAdc(); // Initialisierung des AD-Wandlers initUart(); // UART initialisieren sei(); // generell Interrupts einschalten // Hauptprogrammschleife __________________________________________________ while(1) // unendliche Warteschleife mit Aufruf der // Funktionen abhaengig von Taktbotschaften { if(takt10ms) { takt10ms = 0; // Taktbotschaft zuruecksetzen if(getData()=='r') tValueMax = tValue; // wenn r eingegeben, dann ValueMax zurücksetzen if (bufferFilled==1) // Bei verfügbarer Zeichenkette { putData(wort); // Wort zurück senden bufferFilled=0; // Puffer leeren } } if(takt100ms) // Durchfuehrung der Funktion einmal pro 100ms { takt100ms = 0; // Taktbotschaft zuruecksetzen doAdc(); // Ausfuehrung des Modules der A/D-Wandlung calculateTemp(); // Ausfuehrung des Modules der Umrechnung } if(takt1s) // Durchfuehrung der Anzeige einmal pro 1s { takt1s = 0; // Taktbotschaft zuruecksetzen refreshDisplay(); // Ausfuehrung des Modules der Anzeige wort[5] = '°'; wort[6] = 'C'; wort[7] = '\n'; // ...New Line und... wort[8] = '\r'; // ...Carriage Return. wort[9] = 0; // Endzeichen bufferFilled=1; } } } // Timer-Initialisierung ============================================================== // // Initialisierung des Timer0 zur Erzeugung eines getakteten Interrupts. // Er dient dazu, die benoetigten Taktbotschaften zu erzeugen. void initTimer0() { TCCR0A |= (0< interner Takt = 96 kHz // Abfrage des ADC0 (NTC-Spannungsteiler) // Referenzspannung = analoge Versorgung Avcc void initAdc () { ADMUX |= (1<=tValueMax) // aktueller Wert mit Maximalwert { tValueMax = tValue; // vergleichen und ggf. ersetzen } } // Anzeigetreiber fuer Temperaturanzeige ============================================================== // // Beschreiben der Anzeige mit dem erstellten Temperaturwert // und mit dem maximalen Wert (wird alle 1 s aufgerufen). // // Umrechnung der Zahlenwerte (1/10 °C) in Anzeigewerte wie folgt: // Hunderter: einfache Integer-Teilung (/100). // Zehner: Modulo-Ermittlung (%100), d.h. Rest bei der Teilung durch 100 // dann nochmals Integer-Teilung (/10) dieses Restes. // Einer: Modulo-Ermittlung (%10), d.h. Rest bei der Teilung durch 10. // // Umrechnung in ASCII-Werte fuer die Anzeige durch Addition von 0x30. void refreshDisplayTemp(int tempValue, char line, char pos) { lcd_gotoxy(line, pos); // Startposition fuer Temperatur-Wert if (tempValue>=0) // zuerst Vorzeichen: ' ' oder '-' { wort[0] = ' '; } else { wort[0] = '-'; tempValue = -tempValue; // Vorzeichenumkehr bei negativer Zahl } wort[1] = tempValue/100 + ASC_NULL; tempValue = tempValue%100; wort[2] = tempValue/10 + ASC_NULL; wort[3] = ASC_FULL_STOP; wort[4] = tempValue%10 + ASC_NULL; wort[5] = 0; lcd_putstr (wort); // Hunderter ausgeben (°C Zehner) } // Anzeigefunktion ============================================================== // // Der aktuelle Temperatur und die maximale Temperatur werden ausgegeben void refreshDisplay() { refreshDisplayTemp(tValueMax, 1, 9); // maximale Temperatur ab Position 1,9 refreshDisplayTemp(tValue, 0, 9); // aktuelle Temperatur ab Position 0,9 } // Initialisierung Display-Anzeige ============================================================== // void initDisplay() // Start der Funktion { lcd_init(); // Initialisierungsroutine aus der lcd_lib lcd_displayMessage("- Experiment 9b-",0,0); // Ausgabe in erster Zeile lcd_displayMessage("UART-Temperature",1,0); // Ausgabe in zweiter Zeile _delay_ms(2000); // Wartezeit nach Initialisierung lcd_displayMessage("Temp. ßC",0,0); // Ausgabe in erster Zeile lcd_displayMessage("Maximum ßC",1,0); // Ausgabe in zweiter Zeile // "ßC" wird als °C dargestellt } // Ende der Funktion void initUart (void) // Initialisierung der UART-Register { UBRR0H = UBRR_VAL >> 8; // High-Baudraten-Register beschreiben UBRR0L = UBRR_VAL & 0xFF; // Low-Baudraten-Register beschreiben UCSR0B = (1< <-- --> Code mit Interrupt # ==== Code mit Interrupt==== Variante mit Interrupt: {{microcontrollertechnik:9_uart_temperature.c}} /* ---------------------------------------------------------------------------- Experiment 9: Temperaturmessung und UART ============= =============================== Dateiname : 9_UART_Temperature.c Autoren : Tim Fischer Datum : 01.05.2020 Version : 0.1 Hardware: MEXLE2020 Ver. 1.0 oder hoeher AVR-USB-PROGI Ver. 2.0 Software: Entwicklungsumgebung: AtmelStudio 7.0 C-Compiler: AVR/GNU C Compiler 5.4.0 Funktion : Thermometer mit Anzeige der aktuellen Temperatur und der Maximaltemperatur im Betriebszeitraum in °C mit 1/10 Grad. Keine Tastenbedienung Displayanzeige: Start (fuer 2s): Betrieb: +----------------+ +----------------+ |- Experiment 8 -| |Temp. 18.5°C| | Temperature | |Maximum 21.6°C| +----------------+ +----------------+ Tastenfunktion: keine Jumperstellung: keine Fuses im uC: CKDIV8: Aus (keine generelle Vorteilung des Takts) Header-Files: lcd_lib_de.h (Library zur Ansteuerung LCD-Display Ver.1.3) Module 1) Taktgenerator 2) AD-Wandlung (Takt: 100 ms) 3) Umrechnung fuer Temperatur (Takt: 100 ms) 4) Anzeigetreiber (Takt: 1 s) 1) Das Modul "Taktgenerator" erzeugt den Takt von 100 ms fuer die AD-Wandlung und Umrechnung und einen zusaetzlichen Takt von 1 s fuer die Anzeige. Verwendung von Hardware-Timer 0 und T0 Overflow-Interrupt. Frequenzen: Quarzfrequenz 12,288 MHz. Timer-Vorteiler / 8 => 1,536 MHz Hardware-Timer /256 => 6 kHz / 166 µs Software-Vorteiler / 60 => 100 Hz / 10 ms Hundertstel-Zaehler / 10 => 10 Hz / 100 ms Zehntel-Zaehler / 10 => 1 Hz / 1 s 2) Das Modul "AD-Wandlung" wird durch den Takt 100 ms aufgerufen. Der AD-Wandler wird mit einem internen Takt von 96 kHz betrieben. Im Modul wird eine einzelne AD-Wandlung des Kanals ADC0 mit 10 Bit Aufloesung gestartet. Dort ist der NTC des Boards mit Vorwiderstand als temperaturabhaengiger Spannungsteiler bzw. Potentiometer angeschlossen. Als Referenzspannung wird die 5V-Versorgung verwendet. Das Ergebnis wird in der globalen Variable ad_wert gespeichert. 3) Das Modul "Umrechnung" wird nach der AD-Wandlung alle 100 ms gestartet. Der Ergebniswert des Moduls "AD_Wandlung" wird mit Hilfe einer Tabelle in einen entsprechenden Temperaturwert umgerechnet. In der Tabelle sind Temperaturwerte ueber aequidistante (Abstand = 16) AD-Werte aufgetragen. Die Werte dazwischen werden mit linearer Interpolation ermittelt. Weiterhin wird im Modul jede aktuelle Temperatur mit der gespeicherten maximalen Temperatur verglichen und der Maximalwert optional angepasst. 4) Das Modul "Anzeigetreiber" ist an den 1 s-Takt gekoppelt. Damit wird ein zu schnelles Umschalten der Anzeigewerte vermieden. Das Modul gibt die Werte der aktuellen und der maximalen Temperatur in 1/10 °C aus. Zwischen AD-Wandlung / Umrechnung und Anzeige kann spaeter noch eine Mittelwertsbildung mit 10 Werten eingefuegt werden. Die Kopplung der Module wird ueber global definierte Variable realisiert: 1-Bit-Variable: Takt 100 ms: Taktgenerator => AD-Wandlung => Umrechnung Takt 1 s: Taktgenerator => Anzeigetreiber 16-Bit-Variable: ad-wert AD-Wandlung => Umrechnung t-wert Umrechnung => Anzeige tmax-wert Umrechnung => Anzeige // ----------------------------------------------------------------------------*/ // Deklarationen ============================================================== // Festlegung der Quarzfrequenz #ifndef F_CPU // optional definieren #define F_CPU 8000000L //12288000UL // MiniMEXLE mit 12,288 MHz Quarz #endif // Include von Header-Dateien #include // Header-Dateien zum ATmega88 #include // Header-Datei fuer Interrupts #include // Header-Datei fuer Wartezeit #include "lcd_lib_de.h" // Header-Datei fuer LCD-Anzeige #include // Konstanten #define VORTEILER_WERT 60 #define HUNDERTSTEL_WERT 10 #define ZEHNTEL_WERT 10 #define ASC_NULL 0x30 // Das Zeichen '0' in ASCII #define ASC_FULL_STOP 0x2E // Das Zeichen ':' in ASCII #define UART_BUFFER_SIZE 10 // Buffersize fuer uebertragene Daten #define BAUD_RATE 9600L // Berechnungen für die Baudrate #define UBRR_VAL ((F_CPU+BAUD_RATE*8)/(BAUD_RATE*16)-1) // clever runden #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD_RATE-1000) // Fehler in Promille // Überprüfung der Baudrate und ob Fehler zu groß ist #if ((BAUD_ERROR>10) || (BAUD_ERROR<-10)) #error Systematischer Fehler der Baudrate zu hoch! #endif const int TEMP[45] = {521,499,479,459,440,422,404,388,371,354, 338,323,308,293,279,264,250,236,221,207, 193,179,165,151,137,122,108,93,78,63, 48,32,15,-1,-19,-38,-56,-77,-97,-121, -145,-173,-202,-237,-278}; // Die Tabellenwerte sind in 1/10 °C angegeben // Der erste Tabellenwert entspricht einem AD-Wert // von 256. Die Abstaende der AD-Werte sind 16 // Variable unsigned char vorteiler = VORTEILER_WERT; // Zaehlvariable Vorteiler unsigned char hundertstel = HUNDERTSTEL_WERT; unsigned char zehntel = ZEHNTEL_WERT; unsigned int adcValue = 0; // Variable fuer den AD-Wandlungswert int tValue = 0; // Variable fuer die Temperatur (in 1/10 °C) int tValueMax =-300; // Variable fuer maximale Temperatur (1/10 °C) bool takt10ms; // Bit-Botschaft alle 10 ms bool takt100ms; // Bit-Botschaft alle 100 ms bool takt1s; // Bit-Botschaft alle 1s volatile uint8_t uart_rx_flag = 0; // Flag für vollständig empfangene Daten volatile uint8_t DataTransferFinished = 1; // Flag für vollständig gesendete Daten char uart_rx_buffer[UART_BUFFER_SIZE]; // Empfangspuffer char uart_tx_buffer[UART_BUFFER_SIZE]; // Sendepuffer char wort[UART_BUFFER_SIZE]; // Variable für die Ein- und Ausgabe von Wörtern und Zahlen //Funktionsprototypen void initTimer0 (void); void initAdc (void); void initDisplay (void); void doAdc (void); void calculateTemp (void); void refreshDisplayTemp(int tempValue, char line, char pos); void refreshDisplay (void); void initUart (void); // Initialisierung der UART-Register void putData(char *data); // Daten senden // Hauptprogramm ============================================================== int main () { uint8_t bufferFilled = 0; // Flag für vollen Puffer initDisplay(); // Initialisierung LCD-Anzeige initTimer0(); // Initialisierung von Timer0 initAdc(); // Initialisierung des AD-Wandlers initUart(); // UART initialisieren sei(); // generell Interrupts einschalten UDR0 = 0; // Work around für Probleme bei Simulide <= R941 : ohne diese Zeile is kein Senden möglich // Hauptprogrammschleife __________________________________________________ while(1) // unendliche Warteschleife mit Aufruf der // Funktionen abhaengig von Taktbotschaften { if(takt10ms) { takt10ms = 0; if (DataTransferFinished==1 && bufferFilled==1) // Bei abgeschlossener Sendung und verfügbarer Zeichenkette { bufferFilled=0; // Puffer leeren putData(wort); // Wort zurück senden } } if(takt100ms) // Durchfuehrung der Funktion einmal pro 100ms { takt100ms = 0; // Taktbotschaft zuruecksetzen doAdc(); // Ausfuehrung des Modules der A/D-Wandlung calculateTemp(); // Ausfuehrung des Modules der Umrechnung } if(takt1s) // Durchfuehrung der Anzeige einmal pro 1s { takt1s = 0; // Taktbotschaft zuruecksetzen refreshDisplay(); // Ausfuehrung des Modules der Anzeige wort[5] = '°'; wort[6] = 'C'; wort[7] = '\n'; // ...New Line und... wort[8] = '\r'; // ...Carriage Return. wort[9] = 0; // Endzeichen bufferFilled=1; } } } // Timer-Initialisierung ============================================================== // // Initialisierung des Timer0 zur Erzeugung eines getakteten Interrupts. // Er dient dazu, die benoetigten Taktbotschaften zu erzeugen. void initTimer0() { TCCR0A |= (0< interner Takt = 96 kHz // Abfrage des ADC0 (NTC-Spannungsteiler) // Referenzspannung = analoge Versorgung Avcc void initAdc () { ADMUX |= (1<=tValueMax) // aktueller Wert mit Maximalwert { tValueMax = tValue; // vergleichen und ggf. ersetzen } } // Anzeigetreiber fuer Temperaturanzeige ============================================================== // // Beschreiben der Anzeige mit dem erstellten Temperaturwert // und mit dem maximalen Wert (wird alle 1 s aufgerufen). // // Umrechnung der Zahlenwerte (1/10 °C) in Anzeigewerte wie folgt: // Hunderter: einfache Integer-Teilung (/100). // Zehner: Modulo-Ermittlung (%100), d.h. Rest bei der Teilung durch 100 // dann nochmals Integer-Teilung (/10) dieses Restes. // Einer: Modulo-Ermittlung (%10), d.h. Rest bei der Teilung durch 10. // // Umrechnung in ASCII-Werte fuer die Anzeige durch Addition von 0x30. void refreshDisplayTemp(int tempValue, char line, char pos) { lcd_gotoxy(line, pos); // Startposition fuer Temperatur-Wert if (tempValue>=0) // zuerst Vorzeichen: ' ' oder '-' { wort[0] = ' '; } else { wort[0] = '-'; tempValue = -tempValue; // Vorzeichenumkehr bei negativer Zahl } wort[1] = tempValue/100 + ASC_NULL; tempValue = tempValue%100; wort[2] = tempValue/10 + ASC_NULL; wort[3] = ASC_FULL_STOP; wort[4] = tempValue%10 + ASC_NULL; wort[5] = 0; lcd_putstr (wort); // Hunderter ausgeben (°C Zehner) } // Anzeigefunktion ============================================================== // // Der aktuelle Temperatur und die maximale Temperatur werden ausgegeben void refreshDisplay() { refreshDisplayTemp(tValueMax, 1, 9); // maximale Temperatur ab Position 1,9 refreshDisplayTemp(tValue, 0, 9); // aktuelle Temperatur ab Position 0,9 } // Initialisierung Display-Anzeige ============================================================== // void initDisplay() // Start der Funktion { lcd_init(); // Initialisierungsroutine aus der lcd_lib lcd_displayMessage("- Experiment 9 -",0,0); // Ausgabe in erster Zeile lcd_displayMessage("UART-Temperature",1,0); // Ausgabe in zweiter Zeile _delay_ms(2000); // Wartezeit nach Initialisierung lcd_displayMessage("Temp. ßC",0,0); // Ausgabe in erster Zeile lcd_displayMessage("Maximum ßC",1,0); // Ausgabe in zweiter Zeile // "ßC" wird als °C dargestellt } // Ende der Funktion void initUart (void) // Initialisierung der UART-Register { UBRR0H = UBRR_VAL >> 8; // High-Baudraten-Register beschreiben UBRR0L = UBRR_VAL & 0xFF; // Low-Baudraten-Register beschreiben UCSR0B = (1< <-- Unvollständige [[http://www.falstad.com/circuit/circuitjs.html?ctz=CQAgzCCMCmC0AcICcA6A7PMSnwCwFYwA2eAJkgnwAYR8RdK5JIAoAJRFlKsVn31KdS+Ip36DIICVRmyapFHQV0aVRexBFcnIjKhVtsXapA1cNFadPruaTYdyltkbp0fbtAGwCGAI2ieLI6SXDycYMSckLiGEaLcuIguViaWFrRWdFmmLAAyUcmwcZxogkWREiAAZt6eAM7QGVQsAJJuNFylVp2Cqoq0rUKGTjSQolzmKf34gxNRaKJj86J9WbOToYgd3FvWawDu3aRdSz05h3MTHRsj50dhpzt3l5AL7cvPTm68G4l3HfBRuNAZ9DMwyhtwf8ojEoONotpmm1YBsQQCTGo1siviikuM-qsBtiwclTlDCTNkZDYR0EVMDkMQCCUTQ0SxDmY8fQtuzGadJktmhyoot4St1pyrAS9kTGSClmiZZS+aK4fTZSyRd1BUqWJB8CENmBYQhwrDJMkGZrmTckOKLkaDO8CbzNfyOmBkkL3kVXJrYILXb8fh7SDyHR7Iv62RGChCPQJnkbdD66d7-a98R6SEmPW9-U90zdfh68LmhF1-VhenqiKqjHoccYpAYkFBSK7eMbDCHw5xe3H2n2A4UwE6R-Hh1CzgWuunp7cC5N54VM6m3iuyk8C2FN-3rujntO-v6XRdp8faV7XReTdTETfkifJmfBzbWapHxIs2q9wGf-+zzVi2XZIBINKumAbzblBiyJumxBAtm8i7pBsIweaOYIWGUD5mAOGFpByQwaSZbpqQdogUIlGQGBnwgtuYbbHOeThARYS+ogpD4VIVg1PUjQqCwthsVxHHdlISzaAAOnUYDCVQdhFMR4kEVJICyR2+TKYIJG6TxlT8Q0TSsVwDEcUxUgGXxtTGUJIlmShvAUfE6myc0DkuVROmSaIMl1Kw2leYxlHcbpNkCSZ2mId5MVhbxNBGYJOQOXF4nQW5dQzKl6HiSm5B+RpdS4KZEkYdo8WGbZyXNNF0HpfE1mJdVJmpfVoG6ZlRAsAAHuEaBtqQdZCPAShEG2FXaAAqgAQmwbAAHa5ApSnAdu5hcZlaClXRMG7U11QtUJfV8NxUjDSiwjnRNUjTXNi0ABKmTETluJMlURXZKWKW9r0oiIvn0FAK1uF863veptWgxVHHuFZ4XNZFQnaQQ8SwwDH2I19Hk-f9aM-F0BVA1pbiE7DhMHUlJkOmDsNfBQ9q-d5L3tsOqPMwDLifg6JyFLgZPDl5tFbvKdEIaRwzymRkE4Wujm4Yz8tjF2mGC-KKZFCmYzcyNowmsBaaupZ+plLBUDwUb8pRnDDP0aMOEogKOHkfKfrs1zdtQHzvM1hcxt0fLVye8yxvXn7IInsbrgu0Cuus57gFK5EMffHHhvh4eSsWxng5KymKcBiaxtYZbtL5sbG6l0IFlSw+QXiVGpA4sUVVIzk9dduOTexE6rfY0bOLHFuFksX7g83BZy5GxZFmD6hY9guXHFruRy9Fzi6dCBvhTbuS0+8CHOIxlvDjObDgvL+M3dauR9NXw8itPJHXyvlwXwh2EbLYsyjyQisurYi0GqN+zh-6Yg1ENbQh8oEYmmLMSykcXy7HATMP2f8T43yNkAx46tQSShAdyT4QCQ4gi-nHQuwx7zqmVFwIBE4MH0IpPAuhz9T7UPgcyEOqJYFWkXHSAhFCiEkhFleX2QxM7XwQDrWhbDA6v0gR8QOK8jYT2cnPQWdDFyWSDuRG4lZJFDxyN-bYk8THILgYAxeV8N4bgAUITRNxx48IgSHfRejei6jGM4KMEllZmmcEDDEGQqbphVt48YElmgAFkoBlk4vDUSvFlAsBiZAOJZUeJFHQlIdQqT0nEUyZ6cKyS8nDFCpk4KOSZhpIqsyMqlEskBI7J5Di4gohxLadoAAtt4AAlgtAAwrkAA0qwFpSRVx0ShN0vpgyRljJ+hJRp4A8Kwm0AADRGXqeAbYiA4i6EQAGsAya4DbJAHWpxmyPFHsA-AZZf4XPvlyPgJdDinDaWSSubz4SYTEMnXk7zXBkjDsA3BfAnTen5PAZ5r4yT1n5mI-knNVSQr8jCqe3zoZqjZCJM2mowCJk1NNKJABlAAorkKgrBDiJEQF0Wl4R-mHDxUgkMdxgJzAZXMHGdgOVfAJVuDwIApqkopTIEGcNEACqZEDKaAAFKJ4qaXv25IgPsG1+yqs1Ty+gHEpWEsQNNBVVLeQItoGixAANvTs1Zbqu4LMX7Qtut9OwDrtDSpfsKklM0SU6ptTQaVL5hUDJJQALRNSJBlXRpX0uDXKgA8pSiVXQAbSoBtNEN4bQk8RPJgCQ0cQYID+Jku0UrBAVQAFxTUzeKhyebCGwFLYQyt1aE1Jrrdg8YTb1KkCrTWhZSloUmEbVhYmVbvW+s7IqBAPFpHwE7f2HigYLh4DLYuwQs7C1IFHGUJtvox3ysVdSzg27TZlHrfu0JDTTgXsDHW69XacyARbcanVjaHYnj3X8FtorKXpjAj8A+mTX5IBNHQi9QD-3mj9KBwwkHXQAfbB0RDuJninrYie0kBaV00T9DssUzwh3dCIx7UJ2C8MLtCX8D2Ra13ZvLUB02+dTIkbw-KbJWMaqFtYwCXDhqiqyUE3UWS8kO3ODY-bfjQnpN1BJggcjAJsHZMkFTZG66kPqbpB41TLrNN4eozhfyMn3LcYM4p8TUnhNWaE4FfsZm7NJA44dNuUNG1YeQ6SJzOm33oZo4hlwlnjNZW47hjz+bAvWasyVbS+GNMIBosp5z-dtL+Zg7LLzR1dPvqSDB6DEWZPdROkgT0uEgN2DSZISawr7pLS3WBwwe6gE-vJZS2zjboPIfNBllzN4xwOBPBQJ0Vreu9zBH1tw8HzzjdxLSabU5puQgW5Rec02DRlEG4YG5AZpvnLG+OAQ839smg21EJlp3xx+O2-t5jU39v5hO6EaRD34pXcMPgMWI24PL2mwolb449l7bKeKBySA8JPtg+EHMGyRnNNxibNVvB9TJCdTM-pQzhmw6UvDsQ93qBvbeKjuZGPtlggMNmRHVBm45kkB2GJI4fF+nOU6308gqkpIKD4qMTOuwVDZ3T5gPin3c8h1xPnHOImEuF0URMul1BTYdsQRHNSRc5C8QUdJQuTYq8q5kXXITZja22NekQRuwEWKiHc4YdD9RF0g3YgMlvq60nwEXPQTDkSG6EJk-UGt4pMPPCb6i8IXdA6PI7mRIo9AR-nIHrg3uQ9e7EQ7uJ3BaTNke2HuJlZPfHKTz72kF2E8BghTecPtt-xR9tjHjWl2bdghLh79Pu2Lc14hfb-UWf1tF7nO3svXOi9V-b03oXse-H+4t2WI5nvhsB-ymCBPXwY9xMR+nqcsfIRF6no3xs8+5-sI947qfCerW9+Xxbk05isSR4PC3m-4+HewiPzhGfFuCLz-Qg+APF-X8HzDx+53d4T23eXeDsW22Oxe7+pOn+5+Y2weDsVepe8BI+x2ryMBTuP+6BMeDsL2deieYetu8+2Bk2aBXAxu2By2pk4B+EiORe1BvEKmmWrmVBNetB+UUASWXG546eOBVyN21+6BFeow2c-B-4K+egm8ghp2Yo4hZ2khEB-BAWR46e2eVy2GIhf84hIKchYhowJeXBO+-BFB+hFg0hrIU4vBOh9i0BkhzOrwdETq84zY16aAbwRhChF2Cwuh1hnuF4aA5oWhPhSBfGSh4hjOaA7mIRowXOJAURisPhKBSm3hWgSQkuVywh-4S6NevBT2RASwteFhR4A0ggthRRsS3hLhiwcSrwrhcRnhZRywXhhR5oVRfhzg142kdhEgLRu0YQ2mjBha1RlRi8UydERmVmcmgx9RAYFRVEfRPWHRrRUxrwuUounGrUcOixyu0xWsoxAmVmb6mYowLRbwwsQMMmbWhxSxdRTwcx-cJ0NSEATg62pQSgBAxMLaNWT0CxEs8wKkqxHB6xWO4RXRi8ssuxQW209x40g0jgE+rxdAVWvas080tWDkYwNELRpI4JkWsk3UHR40QxIooUvR7B3mlBdYzgVRFJsxpJ-RaJ1JWxysow2JMmJU9JtcRJiwLJkWMw+JHJohr0txXG+JeRVJSwNxn0XG9Jop9eS63JNmAxVyYpXJ5aexQmTBSp9ejYJJaxamGRIJIoBkJJDBPW9JS6VJ1G8p4xip1GVJ2CVpIm5Jtp9efwEpJp-cxhSx3Bbh-4MpIoeRqB+pXpmROR1GqRzpSh2CdpzgEEXBVsYoHJjhGJ9ewR84wJVxER84DA8YUhd+N42Zmq22GsU4BZU+MUL+hcBksB8g3hBZohuZIoJZ3uXOMURZR4dZ2erZYBdZzeRZBetZFSzZvum654dZqeDZGeWZFS1urZv2+ZFS16s5Pp0QhS8BdZBZK2H63u65I5p2CuQudBKIm6Yw8I02AOUQXkRgtMpy7YvWvui5GsuAy6E5CifZQ4R4rZ5gs2w5ees5lerZwEK2GsYAVRrZY+d535E5ZsQFyEE5zeMFJQ62AF6RDMHox2n5T2rZiOAFshqFiSb5i+EF5qUFBaSOUFB5+5SQ7YGQNCeFGY+Ed+7eSy2F44l+GoFAj+p5Q2ZuV+BFY2rgi+uo8uN+r27wK23+b5pom5NZ52VW4l2gZZKYw2HuYFFFaebFtFSy5eD2g+KCBuSynZ44PeelKlre-F-Z7CwljZsl1l8lUhcFuFDFUQF2O2ehp2JonZGsYBSy45kl450leBolcev5BBL5xB22fol5z2FBpl2wzZkVs6TFrus2XcbuSVVugOVh++L5i5kVy2uoHRdZYFHKcUtJPWwQGBmstIuAdCaUBmKQuuqQTQNFgJF5RyMQiOvlHVQMPg-gngHYHAAYwg4w55Q1lyglZg6QPCGgDuDs+AuO+Y81iw9BcgsgVS61qw2yp5ssLZpIFQVABoMqTB8UjJlUxpAJepLgfpY1+M9BF17c6ulJJIZYbp91x14hVR45EpupD1Q1UZYICi31b1lBTgSQn1rp51ZJHRxsn15kou7pXG9xYYjxsJI4OAt0CJzqSJAAIotCDcmRecSf8WSQAPb0H-w9TwDnKWjWByCg6HJ7KWC9AoAHWYa6rmJUBYBUCM05BAA|Falstad Simulation]] Bitte arbeiten Sie folgende Aufgaben durch: --> Aufgabe# Versuchen Sie die folgenden Zeitverlauf des UART Signals zu entschlüsseln - es kam vom vorliegenden Programm. \\ Welche neun Zeichen wurden gesendet? \\ {{drawio>microcontrollertechnik:UARTSignal.svg}} <--