Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
microcontrollertechnik:8_temperatur [2023/10/30 00:10] – mexleadmin | microcontrollertechnik:8_temperatur [2024/04/23 01:23] (aktuell) – mexleadmin | ||
---|---|---|---|
Zeile 13: | Zeile 13: | ||
* Eine [[https:// | * Eine [[https:// | ||
- | </ | + | </ |
===== Video ===== | ===== Video ===== | ||
+ | {{youtube> | ||
+ | |||
+ | <WRAP hide> | ||
{{youtube> | {{youtube> | ||
+ | </ | ||
</ | </ | ||
+ | <WRAP > | ||
+ | < | ||
+ | </ | ||
+ | {{drawio> | ||
+ | </ | ||
===== Messsignal-Digitalisierung und Auswertung ===== | ===== Messsignal-Digitalisierung und Auswertung ===== | ||
Zeile 243: | Zeile 252: | ||
- {{microcontrollertechnik: | - {{microcontrollertechnik: | ||
- {{microcontrollertechnik: | - {{microcontrollertechnik: | ||
+ | |||
+ | \\ \\ | ||
+ | <callout type=" | ||
+ | |||
+ | **Beachten Sie, folgendes** | ||
+ | * Es wird nun ein ATmega328 genutzt, d.h. das Programm ist nicht mehr kompatibel mit dem MiniMEXLE! | ||
+ | * Das Display ist nunan einem anderen Port um den Analog-Digial-Wandler am Port C zu nutzen. \\ Deshalb muss der Treiber '' | ||
+ | * Zeile 26: ''# | ||
+ | * Zeile 39: ''# | ||
+ | * Zeile 40: ''# | ||
+ | * Zeile 44: ''# | ||
+ | * Zeile 46: ''# | ||
+ | |||
+ | </ | ||
+ | \\ \\ | ||
+ | |||
+ | |||
<-- | <-- | ||
Zeile 255: | Zeile 281: | ||
<-- | <-- | ||
- | --> III. Eingabe in Atmel Studio # | + | --> III. Eingabe in Microchip |
- | Beachten Sie, dass nun ein ATmega328 genutzt wird, d.h. das Programm ist nicht mehr kompatibel mit dem MiniMEXLE! | ||
<WRAP group>< | <WRAP group>< | ||
/* ---------------------------------------------------------------------------- | /* ---------------------------------------------------------------------------- | ||
- | + | ||
- | | + | |
| | ||
+ | |||
| | ||
+ | | ||
+ | | ||
+ | Prof. G. Gruhler | ||
+ | D. Chilachava | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | AVR-USB-PROGI Ver. 2.0 | ||
- | Autoren : Peter Blinzinger | + | Software: |
- | Prof. G. Gruhler (Hochschule Heilbronn, Fakultaet T1) | + | |
- | D. Chilachava (Georgische Technische Universitaet) | + | |
- | | + | |
- | Datum : 01.05.2020 | + | |
- | | ||
- | |||
- | | ||
- | AVR-USB-PROGI Ver. 2.0 | ||
- | |||
- | | ||
- | C-Compiler: | ||
- | |||
| | ||
- | Maximaltemperatur im Betriebszeitraum in °C mit 1/10 Grad. | + | |
- | Keine Tastenbedienung | + | Keine Tastenbedienung |
- | + | ||
- | | + | |
- | +----------------+ +----------------+ | + | |
- | |- Experiment 8 -| |Temp. | + | |
- | | Temperature | + | |
- | +----------------+ +----------------+ | + | |
- | + | ||
- | | + | |
- | + | ||
- | | + | |
- | + | ||
- | Fuses im uC: CKDIV8: Aus (keine generelle Vorteilung des Takts) | + | Fuses im uC: |
- | + | ||
- | | + | |
- | + | ||
- | | + | |
- | 2) AD-Wandlung (Takt: 100 ms) | + | 2) AD-Wandlung (Takt: 100 ms) |
- | 3) Umrechnung fuer Temperatur | + | 3) Umrechnung fuer Temperatur |
- | 4) Anzeigetreiber (Takt: 1 s) | + | 4) Anzeigetreiber (Takt: 1 s) |
+ | |||
1) Das Modul " | 1) Das Modul " | ||
- | | + | |
- | + | ||
- | Verwendung von Hardware-Timer 0 und T0 Overflow-Interrupt. | + | Verwendung von Hardware-Timer 0 und T0 Overflow-Interrupt. |
- | Frequenzen: Quarzfrequenz | + | Frequenzen: Quarzfrequenz |
- | Timer-Vorteiler / 8 => | + | Timer-Vorteiler |
- | Hardware-Timer | + | Hardware-Timer |
- | Software-Vorteiler | + | Software-Vorteiler |
- | Hundertstel-Zaehler / | + | Hundertstel-Zaehler / 10 => 10 Hz / 100 ms |
- | Zehntel-Zaehler / 10 => | + | Zehntel-Zaehler |
+ | |||
2) Das Modul " | 2) Das Modul " | ||
Der AD-Wandler wird mit einem internen Takt von 96 kHz betrieben. | Der AD-Wandler wird mit einem internen Takt von 96 kHz betrieben. | ||
- | | + | |
Aufloesung gestartet. Dort ist der NTC des Boards mit Vorwiderstand | Aufloesung gestartet. Dort ist der NTC des Boards mit Vorwiderstand | ||
als temperaturabhaengiger Spannungsteiler bzw. Potentiometer angeschlossen. | als temperaturabhaengiger Spannungsteiler bzw. Potentiometer angeschlossen. | ||
Als Referenzspannung wird die 5V-Versorgung verwendet. | Als Referenzspannung wird die 5V-Versorgung verwendet. | ||
Das Ergebnis wird in der globalen Variable tValue gespeichert. | Das Ergebnis wird in der globalen Variable tValue gespeichert. | ||
+ | |||
3) Das Modul " | 3) Das Modul " | ||
Der Ergebniswert des Moduls " | Der Ergebniswert des Moduls " | ||
einen entsprechenden Temperaturwert umgerechnet. In der Tabelle sind | einen entsprechenden Temperaturwert umgerechnet. In der Tabelle sind | ||
Temperaturwerte ueber aequidistante (Abstand = 16) AD-Werte aufgetragen. | Temperaturwerte ueber aequidistante (Abstand = 16) AD-Werte aufgetragen. | ||
- | | + | |
Weiterhin wird im Modul jede aktuelle Temperatur mit der gespeicherten | Weiterhin wird im Modul jede aktuelle Temperatur mit der gespeicherten | ||
- | | + | |
+ | |||
4) Das Modul " | 4) Das Modul " | ||
zu schnelles Umschalten der Anzeigewerte vermieden. Das Modul gibt die | zu schnelles Umschalten der Anzeigewerte vermieden. Das Modul gibt die | ||
Werte der aktuellen und der maximalen Temperatur in 1/10 °C aus. | 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: | ||
+ | => Umrechnung | ||
+ | Takt | ||
+ | |||
+ | 16-Bit-Variable: | ||
+ | t-wert | ||
+ | tmax-wert | ||
- | Die Kopplung der Module wird ueber global definierte Variable realisiert: | ||
- | |||
- | | ||
- | | ||
- | Takt | ||
- | |||
- | 16-Bit-Variable: | ||
- | t-wert Umrechnung => Anzeige | ||
- | tmax-wert Umrechnung => Anzeige | ||
- | |||
// ----------------------------------------------------------------------------*/ | // ----------------------------------------------------------------------------*/ | ||
+ | |||
// Deklarationen ============================================================== | // Deklarationen ============================================================== | ||
+ | |||
// Festlegung der Quarzfrequenz | // Festlegung der Quarzfrequenz | ||
- | #ifndef F_CPU // optional definieren | + | #ifndef F_CPU |
- | #define F_CPU 12288000UL // Atmega328 mit 12,288 MHz Quarz | + | #define F_CPU 12288000UL |
- | #endif | + | # |
+ | |||
// Include von Header-Dateien | // Include von Header-Dateien | ||
- | #include < | + | #include < |
- | #include < | + | #include < |
- | #include < | + | #include < |
- | #include " | + | #include " |
+ | |||
// Konstanten | // Konstanten | ||
- | # | + | # |
- | # | + | # |
- | # | + | # |
#define ASC_NULL | #define ASC_NULL | ||
#define ASC_FULL_STOP | #define ASC_FULL_STOP | ||
- | + | ||
- | const int TEMP[45] | + | const int |
- | 338, | + | 338, |
- | 193, | + | 193, |
- | 48, | + | 48, |
- | -145, | + | -145, |
- | + | ||
- | // Die Tabellenwerte sind in 1/10 °C angegeben | + | // Die Tabellenwerte sind in 1/10 °C angegeben |
- | // Der erste Tabellenwert entspricht einem AD-Wert | + | // Der erste Tabellenwert entspricht einem AD-Wert |
- | // von 256. Die Abstaende der AD-Werte sind 16 | + | // von 256. Die Abstaende der AD-Werte sind 16 |
+ | |||
// Variable | // Variable | ||
- | unsigned char vorteiler = VORTEILER_WERT; // Zaehlvariable Vorteiler | + | unsigned char softwarePrescaler |
- | unsigned char hundertstel = HUNDERTSTEL_WERT; | + | unsigned char cycle10msCount |
- | unsigned char zehntel | + | unsigned char cycle100msCount |
- | + | ||
- | unsigned int adcValue = 0; // Variable fuer den AD-Wandlungswert | + | unsigned int adcValue |
- | int tValue = 0; // Variable fuer die Temperatur (in 1/10 °C) | + | int |
- | int tValueMax =-300; | + | int |
- | + | ||
- | bool takt10ms; // Bit-Botschaft alle 10 ms | + | bool |
- | bool takt100ms; // Bit-Botschaft alle 100 ms | + | bool |
- | bool takt1s; // Bit-Botschaft alle 1s | + | bool |
+ | |||
// | // | ||
void initTimer0 (void); | void initTimer0 (void); | ||
Zeile 402: | Zeile 428: | ||
void refreshDisplayTemp(int tempValue, char line, char pos); | void refreshDisplayTemp(int tempValue, char line, char pos); | ||
void refreshDisplay (void); | void refreshDisplay (void); | ||
+ | |||
// Hauptprogramm ============================================================== | // Hauptprogramm ============================================================== | ||
int main () | int main () | ||
{ | { | ||
- | initDisplay(); | + | |
- | initTimer0(); | + | initTimer0(); |
- | initAdc(); | + | initAdc(); |
- | + | ||
- | sei(); // generell Interrupts einschalten | + | sei(); |
- | + | | |
- | // Hauptprogrammschleife __________________________________________________ | + | // Hauptprogrammschleife __________________________________________________ |
- | + | ||
- | while(1) // unendliche Warteschleife mit Aufruf der | + | while(1) |
- | // Funktionen abhaengig von Taktbotschaften | + | // Funktionen abhaengig von Taktbotschaften |
- | { | + | { |
- | if(takt100ms) // Durchfuehrung der Funktion einmal pro 100ms | + | if(cycle100msActive) // Durchfuehrung der Funktion einmal pro 100ms |
- | { | + | { |
- | takt100ms | + | |
- | doAdc(); // Ausfuehrung des Modules der A/ | + | doAdc(); |
- | calculateTemp(); | + | calculateTemp(); |
- | } | + | } |
- | + | ||
- | if(takt1s) // Durchfuehrung der Anzeige einmal pro 1s | + | if(cycle1sActive) |
- | { | + | { |
- | takt1s | + | |
- | refreshDisplay(); | + | refreshDisplay(); |
- | } | + | } |
- | } | + | } |
} | } | ||
- | + | ||
+ | |||
// Timer Initialisierung ============================================================== | // Timer Initialisierung ============================================================== | ||
// | // | ||
Zeile 439: | Zeile 465: | ||
void initTimer0() | void initTimer0() | ||
{ | { | ||
- | TCCR0A |= (0<< | + | |
- | | (0<< | + | | (0<< |
- | TCCR0B |= (0<< | + | TCCR0B |
- | | (1<< | + | | (1<< |
- | TIMSK0 |= (1<< | + | TIMSK0 |
} | } | ||
+ | |||
// ADC-Initialisierung ============================================================== | // ADC-Initialisierung ============================================================== | ||
// | // | ||
Zeile 454: | Zeile 480: | ||
void initAdc() | void initAdc() | ||
{ | { | ||
- | ADMUX |= (1<< | + | |
- | + | ||
- | ADCSRA |= (1<< | + | ADCSRA |
- | | (1<< | + | | (1<< |
- | | (1<< | + | | (1<< |
- | | (1<< | + | | (1<< |
- | (void) ADCH; // erster Wert ist " | + | (void) ADCH; // erster Wert ist " |
} | } | ||
- | + | ||
+ | |||
// Timer-Service Routine ============================================================== | // Timer-Service Routine ============================================================== | ||
// | // | ||
Zeile 470: | Zeile 496: | ||
// werden von Timer 0 ausgeloest (Interrupt Nr. 1) | // werden von Timer 0 ausgeloest (Interrupt Nr. 1) | ||
// | // | ||
- | // Veraenderte Variable: | + | // Veraenderte Variable: |
- | // hunderstel | + | // hunderstel |
- | // zehntel | + | // zehntel |
// | // | ||
- | // Ausgangsvariable: | + | // Ausgangsvariable: |
- | // takt100ms | + | // takt100ms |
- | // takt1s | + | // takt1s |
+ | |||
ISR (TIMER0_OVF_vect) | ISR (TIMER0_OVF_vect) | ||
{ | { | ||
- | --vorteiler; // Vorteiler dekrementieren | + | |
- | if (vorteiler==0) // wenn 0 erreicht: 10ms abgelaufen | + | if (softwarePrescaler==0) // wenn 0 erreicht: 10ms abgelaufen |
- | { | + | { |
- | vorteiler | + | |
- | takt10ms | + | |
- | --hundertstel; // Hundertstelzaehler dekrementieren | + | --cycle10msCount; // Hundertstelzaehler dekrementieren |
- | + | ||
- | if (hundertstel==0) // wenn 0 erreicht: 100ms abgelaufen | + | if (cycle10msCount==0) // wenn 0 erreicht: 100ms abgelaufen |
- | { | + | { |
- | hundertstel | + | |
- | takt100ms | + | |
- | --zehntel; | + | --cycle100msCount; |
- | + | ||
- | if (zehntel==0) // Zehntelzaehler dekrementieren | + | if (cycle100msCount==0) |
- | { | + | { |
- | zehntel | + | |
- | takt1s | + | |
- | } | + | } |
- | } | + | } |
- | } | + | } |
} | } | ||
+ | |||
// ADWandlung ============================================================== | // ADWandlung ============================================================== | ||
// | // | ||
Zeile 508: | Zeile 534: | ||
void doAdc() | void doAdc() | ||
{ | { | ||
- | ADCSRA |= (1<< | + | |
- | while (ADCSRA & (1<< | + | while (ADCSRA & (1<< |
- | + | ||
- | adcValue = ADCL + (ADCH<< | + | adcValue = ADCL + (ADCH<< |
// | // | ||
// | // | ||
} | } | ||
+ | |||
// Umrechnung ============================================================== | // Umrechnung ============================================================== | ||
// | // | ||
Zeile 521: | Zeile 547: | ||
void calculateTemp () | void calculateTemp () | ||
{ | { | ||
- | unsigned char index; // Tabellenindex fuer Temperaturtabelle | + | |
- | unsigned char steps; // Abstand zum naechstkleineren Wert | + | unsigned char steps; |
- | // der AD-Werte der Temperaturtabelle | + | // der AD-Werte der Temperaturtabelle |
- | + | | |
- | index = (adcValue-256)/ | + | index |
- | steps = (adcValue-256)%16; | + | steps |
- | + | | |
- | tValue = steps * (TEMP[index+1] - TEMP[index])/ | + | tValue = steps * (TEMP[index+1] - TEMP[index])/ |
- | // Temperaturwert berechnen | + | // Temperaturwert berechnen |
- | + | ||
- | if(tValue> | + | if(tValue> |
- | { | + | { |
- | tValueMax = tValue; // vergleichen und ggf. ersetzen | + | tValueMax = tValue; |
- | } | + | } |
} | } | ||
+ | |||
// Anzeigefunktion ============================================================== | // Anzeigefunktion ============================================================== | ||
// | // | ||
Zeile 542: | Zeile 568: | ||
void refreshDisplay() | void refreshDisplay() | ||
{ | { | ||
- | refreshDisplayTemp(tValue, | + | |
- | refreshDisplayTemp(tValueMax, | + | refreshDisplayTemp(tValueMax, |
} | } | ||
+ | |||
// Anzeigetreiber fuer Temperaturanzeige ============================================================== | // Anzeigetreiber fuer Temperaturanzeige ============================================================== | ||
// | // | ||
Zeile 554: | Zeile 580: | ||
// Hunderter: einfache Integer-Teilung (/100). | // Hunderter: einfache Integer-Teilung (/100). | ||
// Zehner: Modulo-Ermittlung (%100), d.h. Rest bei der Teilung durch 100 | // Zehner: Modulo-Ermittlung (%100), d.h. Rest bei der Teilung durch 100 | ||
- | // dann nochmals Integer-Teilung (/10) dieses Restes. | + | // |
// Einer: | // Einer: | ||
// | // | ||
Zeile 560: | Zeile 586: | ||
void refreshDisplayTemp(int tempValue, char line, char pos) | void refreshDisplayTemp(int tempValue, char line, char pos) | ||
{ | { | ||
- | lcd_gotoxy(line, | + | |
- | if (tempValue> | + | if (tempValue> |
- | { | + | { |
- | lcd_putc(' | + | lcd_putc(' |
- | } | + | } |
- | else | + | else |
- | { | + | { |
- | lcd_putc(' | + | lcd_putc(' |
- | tempValue = -tempValue; | + | tempValue = -tempValue; |
- | } | + | } |
- | lcd_putc | + | lcd_putc |
- | tempValue = tempValue%100; | + | tempValue = tempValue%100; |
- | lcd_putc | + | lcd_putc |
- | lcd_putc | + | lcd_putc |
- | lcd_putc | + | lcd_putc |
} | } | ||
+ | |||
// Initialisierung Display-Anzeige ============================================================== | // Initialisierung Display-Anzeige ============================================================== | ||
// | // | ||
- | void initDisplay() // Start der Funktion | + | void initDisplay() |
{ | { | ||
- | lcd_init(); | + | |
- | + | | |
- | lcd_displayMessage(" | + | lcd_displayMessage(" |
- | lcd_displayMessage(" | + | lcd_displayMessage(" |
- | + | ||
- | _delay_ms(2000); | + | _delay_ms(2000); |
- | + | ||
- | lcd_displayMessage(" | + | lcd_displayMessage(" |
- | lcd_displayMessage(" | + | lcd_displayMessage(" |
- | // " | + | // " |
- | } // Ende der Funktion | + | } |
</ | </ | ||
</ | </ | ||
Zeile 603: | Zeile 628: | ||
- Hier wird wieder geprüft ob die Frequenz des Quarz bereits eingestellt wurde und - falls nicht - dessen Frequenz eingestellt. \\ \\ | - Hier wird wieder geprüft ob die Frequenz des Quarz bereits eingestellt wurde und - falls nicht - dessen Frequenz eingestellt. \\ \\ | ||
- Die Header-Dateien entsprechen denen der letzten Programme. \\ \\ \\ \\ \\ | - Die Header-Dateien entsprechen denen der letzten Programme. \\ \\ \\ \\ \\ | ||
- | - Die Konstanten entsprechen denen der letzten Programme. \\ \\ \\ \\ | + | - Die Konstanten entsprechen denen der letzten Programme. |
- Es wird eine zusätzliches Array '' | - Es wird eine zusätzliches Array '' | ||
- | - Bei den Variablen entsprechen einige denen der letzten Programme. | + | - Bei den Variablen entsprechen einige denen der letzten Programme. \\ \\ \\ \\ |
- Die Variable '' | - Die Variable '' | ||
- Die Variable '' | - Die Variable '' | ||
- Die Variable '' | - Die Variable '' | ||
- | - Bei den Funktionsprototypen sind einige bekannte Unterprogramme vorhanden. Details werden weiter unten erklärt. \\ \\ \\ \\ | + | - Bei den Funktionsprototypen sind einige bekannte Unterprogramme vorhanden. Details werden weiter unten erklärt. |
'' | '' | ||
- Das Hauptprogramm ähnelt sehr stark dem [[4_up_down_counter|Up/ | - Das Hauptprogramm ähnelt sehr stark dem [[4_up_down_counter|Up/ | ||
- | - In der Endlosschleife sind auf der ersten Ebene wieder nur If-Abfragen zu den Flags '' | + | - In der Endlosschleife sind auf der ersten Ebene wieder nur If-Abfragen zu den Flags '' |
- Alle $100~\rm ms$ (bzw. wenn das entsprechende Flag gesetzt wird) wird das Flag zurückgesetzt und das Unterprogramm '' | - Alle $100~\rm ms$ (bzw. wenn das entsprechende Flag gesetzt wird) wird das Flag zurückgesetzt und das Unterprogramm '' | ||
- | - Alle $1~\rm s$ (bzw. wenn das entsprechende Flag gesetzt wird) wird das Flag zurückgesetzt und das Unterprogramm '' | + | - Alle $1~\rm s$ (bzw. wenn das entsprechende Flag gesetzt wird) wird das Flag zurückgesetzt und das Unterprogramm '' |
'' | '' | ||
- | - Die Timer Initialisierung ist dem Programm [[4_up_down_counter|Up/ | + | - Die Timer Initialisierung ist dem Programm [[4_up_down_counter|Up/ |
'' | '' | ||
Zeile 633: | Zeile 658: | ||
\\ | \\ | ||
'' | '' | ||
- | - Die Timer-Service Routine ist dem Programm [[4_up_down_counter|Up/ | + | - Die Timer-Service Routine ist dem Programm [[4_up_down_counter|Up/ |
'' | '' | ||
Zeile 640: | Zeile 665: | ||
- Das Register '' | - Das Register '' | ||
- immer erst ADCL auslesen, dann ADCH. | - immer erst ADCL auslesen, dann ADCH. | ||
- | - immer auch ADCH auslesen, selbst wenn es nicht benötigt wird. \\ | + | - immer auch ADCH auslesen, selbst wenn es nicht benötigt wird. \\ \\ |
'' | '' | ||
Zeile 647: | Zeile 672: | ||
- '' | - '' | ||
- In '' | - In '' | ||
- | \\ \\ \\ \\ \\ | + | \\ \\ \\ \\ \\ |
'' | '' |