====== 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}}
<--