Forum: Mikrocontroller und Digitale Elektronik Brobleme beim rechnen nit uint32_t


von m. S. (marek)


Lesenswert?

Hallo @all,

ich hab ein Problem, ich benutze zwei Timer vom ATmega8 die mir 
überläufe zählen sollen. Das funktioniert auch soweit.
Die eine Variable ist uint32_t k und die andere ist uint32_t j.
Die Überläufe sollen dafür verwendet werden die Phasen differenz 
zwischen zwei signalen zu ermittel.
Die Berechnung lautet wie folgt:

char s[20];
uint32_t T0,T2;
double PHI;

T0 = (k << 8) + TCNT0; //Wert für die ganze periode (T) << 8 = *256
T2 = (j << 8) + TCNT2; //Wert für die delta t
PHI = ((T2 +0.0)/T0)*360.0;

wenn ich mir mit
uart_puts( ultoa( k, s , 10));
k ausgeben lasse kriege ich auch einen Vernünftigen wert z.b. 208
( (16Mhz/(208 * 256)) = 300Hz der frequenz die ich auch anlege mal per 
hand gerechnet.)

uart_puts(ultoa(j, s, 10));
lifert z.b. einen Wert von 4 somit kann ich mir mal schnell ausrechnen
(((4*256)/(208*256))*360)= 6,92° Phasenverschiebung)

wenn ich mir das aber mit
uart_puts( dtosrtf(PHI, 10, 4, s));

Kommt was anderes raus auch wenn ich mir nur mal die Werte für k und j 
ausgeben lasse alleine kriege ich die 208 und die 4  wenn ich noch PHI 
ausgeben lasse dann sehen die Werte plötzlich ganz anders aus.

uatr_puts(...)  hier entnommen:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART

Ich weis das sind hier nur mal code auszüge. Initiealisierungen und so 
weiter solten eigentlich soweit stimmen.

Vielleicht hatte ja schon jemand ein ähnliches problem oder weis rat ich 
würde mich freunen danke schon mal.

mfg
m.s.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du benutzt Variablen sowohl im Interrupthandler als auch in der 
main-Schleife. volatile ist hier das Stichwort.

Außerdem ist der Atmega8 ein 8-Bit-µC, muss also jede 32-Bit-Operation 
aufwendig mit mehreren Befehlen nachbilden. Davon weiß aber der 
Interrupthandler nichts, es kann also sein, daß während des Zugriffes 
auf die 32-Bit-Variable sich bereits Teile davon ändern. Stichwort hier 
ist atomare Operation.

von m. S. (marek)


Lesenswert?

Erst mal danke für die schnelle Antwort.

vor der berechnung schalte ich die interrupts an INT0 und INT1 ab mit 
hilfe von GIMSK &= ~((1<<INT0) | (1<<INT1)); nach der ausgabe schalte 
ich sie wider ein mit GIMSK |= (1<<INT0) | (1<<INT1);.
Vor der Ausgbae werden auch noch die TIMER angehalten so das es 
eigentlich zu keinen weiteren überläufen kommen kann. Die variablen k 
und j sowie T0 und T2 hatte ich als extern deklarirt. Werde das mal 
morgen mit volatile überprüfen ob es daran gelegen hat ansonsten werde 
ich mal die kompletten interrupts ausschalten vor der Ausgabe und dSie 
nach der asugabe wider einschalten.

mfg
m.s.

von m. S. (marek)


Lesenswert?

Hi Rufus,

danke noch mal es lag tatsechlich daran das ich nicht die kompletten 
interrupts ausgeschaltet habe sondern nur einen Teil davon. Jetzt wird 
vor der ausgabe cli(); und nach der ausgabe sli(); gesetzt und es geht. 
wobei mich das etwas iretiert da es eigentlich laut meinem Verständnis 
zu keinen problemen kommen solte wenn ich die Interrupts an INT0 und 
INT1 ausschalte und die Timmer nicht laufen kann es ja auch nicht zu 
überlauf Interrupts kommen. Naja ist j auch egal man steckt halt nicht 
drinne und weis nicht immer ganz was da alles passiert.

mfg
m.s.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.