-
-
Neuer Benutzer
Öfters hier
Hallo,
eigentlich hatte ich gehofft, dass sich jemand mal äussert, ob ihr auch der Meinung seit, dass die Messung der Akkuspannung nicht funktioniert, so wie sie in der Nibobeelib implementiert ist.
Hier mal die Antworten auf die Fragen von radbruch.
Sollte nach dem Zurückschalten auf die 5V-Referenz nicht auch noch eine Dummylesung erfolgen?
Antwort:
Das wird auch gemacht. Nach der Messung der Batteriespannung in der neuen Routine, wird die Interruptgetriebene ADC Wandlung mit einem erneuten messen der Batteriespannung wieder aufgenommen. Allerdings mit der Falschen ARef Spannung. Damit ist das Ergibnis sowieso Schrott aber es wurde eine Dummy-Messung durchgeführt.
Deshalb warte ich in der Batterie-Routine bis der Kanal 4 (VBAT) dran ist, rette die Register, schreibe sie wieder zurück und mache genauso weiter als ob die Batterie-Routine nie aufgerufen worden wäre.
Wieso funktioniert delay() bei gesperrten Interrupts?
Antwort:
Die delay(..) stützt sich auf der _delay_ms aus <util/delay.h> ab. Die arbeitet mit Zeitschleifen und braucht keinen Interrupt (siehe avr-libc-users-manual).
22.28 <util/delay_basic.h>: Basic busy-wait delay loops
22.28.1 Detailed Description
#include <util/delay_basic.h>
The functions in this header file implement simple delay loops that perform a busy waiting.
They are typically used to facilitate short delays in the program execution.
They are implemented as count-down loops with a well-known CPU cycle count per loop iteration. As such, no other processing can occur simultaneously. It should be kept in mind that the functions described here do not disable interrupts.
In general, for long delays, the use of hardware timers is much preferrable, as they free the CPU, and allow for concurrent processing of other events while the timer is running. However, in particular for very short delays, the overhead of setting up a hardware timer is too much compared to the overall delay time.
Two inline functions are provided for the actual delay algorithms.
Functions
• void _delay_loop_1 (uint8_t __count)
• void _delay_loop_2 (uint16_t __count)
Wäre es nicht günstiger nur den ADC-Interrupt zu verhindern anstatt alle Interrupts zu sperren?
Antwort:
Richtig
Oh, da ist ja noch ein Klassiker: Im Datenblatt des Mega16 in der Beschreibung von ADIF (Seite 219):
Zitat:
Alternatively, ADIF is cleared by writing a logical one to the flag. Beware that if doing a Read-Modify-Write on ADCSRA, a pending interrupt can be disabled.
Bedeutet ungefähr: Wenn das Flag nicht automatisch durch den Aufruf der ISR gelöscht wird, kann man es auch "von Hand" löschen. Aber man darf dabei keine "Read-Modify-Write"-Anweisung auf das ADSRA-Register anwenden. das bedeutet, das Flag sollte so gelöschte werden:
ADCSRA = (1 << ADIF);
Das gilt auch für manche andere Flags im Zusammenhang mit den Interrupts!
Antwort:
Das oben gesagte bedeutet nur, dass man wissen muss, was man tut, bedeutet aber nicht, dass man es nicht tun darf.
Ich lösche ADIF bevor ich ADCSRA in temp1 rette. Ich lösche ADIF am Ende meiner eingefügten Batteriespannungsmessung und somit einen (eventuell) pending ADC Interrupt. Eigentlich ist das aber nur zur Sicherheit, denn in der Initialisierung der Batteriespannungsmessung wird ADIE in ADCSRA bewusst nicht gesetzt. Also sollte ADIF eigentlich gar nicht kommen. Beim Zurückschreiben von temp1 in ADCSRA weiss ich also ganz genau, was ich zurückschreibe.
Ich lösche auch ganz bewusst ADSC in ADCSRA beim zurückschreiben, damit die delay(2) auch wirklich abgearbeitet werden können, bevor ich danach mit ADSC=1 den gewohnten ADC Betrieb wieder auf nehme.
Viele Gruesse
Skroete
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
-
Foren-Regeln
Lesezeichen