Hallo Leute,
ich habe festgestellt das ich ein kleines Problem habe. Ich habe die
Aufgabe ein ADXL202JE Beschleunigungssensor mit einem 80C535
Mikroprozessor einzulessen. Das mache ich mit dem Timer 2 und dem Timer
1, weil de Timer 0 für die Baudrate der seriellen Schnittstelle schon
benutzt wird. Und wenn ich die Achsen einzeln einlese (also nur die X
Achse oder nur die Y Achse) geht das sehr gut. Aber jetzt wenn ich die
zusammen einlessen will, dh erst die X Achse und dan die Y Achse gehts
sehr schlecht da kommen immer die 3 oder 4 Werte als Unendlich raus.
Könnte es sein das die zwei Timer zusammen nicht gehen können
oder müssen?? Ich lese die werte mit der Capture Unit CC0 und CC1 ein
und beim Timer 1 als "gated mode". Könnte mir vieleicht jemand helfen,
ein Tipp oder eine Internet Seite, oder ein Beispielprogramm in C??
Bitte, bitte
Interrupts haben Prioritäten und da du kein Programm zur Verfügung
stellst ist Hilfe nicht möglich.
Beschreibe mal etwas ausführlicher was du wie machst.
Das ist nur ein Teil des Programms. Nur das Teil mit dem einlesen
und dem bearbeiten. Ich kann euch nicht das ganze geben. Das ist
gegenüber meiner Firma wiederrechtlich. Und als *.C kann ich das nicht
speichern weil das so nicht gehen kann.
Andy wrote:
>> Das ist nur ein Teil des Programms. Nur das Teil mit dem einlesen> und dem bearbeiten. Ich kann euch nicht das ganze geben. Das ist> gegenüber meiner Firma wiederrechtlich. Und als *.C kann ich das nicht> speichern weil das so nicht gehen kann.
Nun, ich will ja keine Hilfe, kann mir also völlig wurscht sein.
Aber wenn Du Hilfe zu einer Software willst, mußt Du schon ein error-
und warningfreies kompilierbares Programm schicken.
Natürlich soll es nicht unnötig aufgebläht sein, sondern nur soviel
Code, daß der Fehler immer noch auftritt.
Die Firmengeheimnisse solltest Du daher rausnehmen, uns interessiert ja
nur der Fehler.
Und damit hast Du nämlich überhaupt erstmal die Gewißheit, daß der
Fehler wirklich in dem geposteten Code liegt und nicht in den
Firmengeheimnissen.
Sehr oft wurde hier schon völlig unschuldiger Code gepostet und alle
zerbrachen sich tagelang den Kopf, was daran wohl falsch sein könnte.
Also den Code soweit wie möglich kürzen, dann nochmal testen, ob der
Fehler immer noch drin ist und dann posten.
Peter
> Ich kann euch nicht das ganze geben. Das ist gegenüber meiner Firma
wiederrechtlich.
Dafür habe ich vollstes Verständnis.
> Und als *.C kann ich das nicht speichern weil das so nicht gehen kann.
Den verstehe ich nicht.
Aber mal im ernst, ab und zu nehme ich mir die Zeit hier Fragen zu
beantworten und Hilfe zu leisten. Aber versetz dich mal in meine Lage,
hättest du Lust bei diesem Ratespiel mitzumachen ??
Machs wie Peter es gesagt hat und dann sehen wir mal.
Der Fehler beim Programm ist jetzt das die Zwei Timer nicht
zusammen gehen. Wenn ich die Achsen einzeln einlese (d.h die eine Achse
wegkommentiere) gehts einwandfrei, aber sobald ich die zusammenstelle
kommen die Werte entweder konstant oder verfälscht raus. Und bei einer
Neigung von 180° oder 90° sind die Werte unendlich.
Ich brauch Hilfe
Allgemein:
Warumm nimmst Du int für Flags, da reicht doch dicke char oder noch
besser bit.
Wenn Du Variablen >1Byte in Interrupts und im Main zugreifst, mußt Du
sie im Main atomar (unter Interruptsperre) zugreifen, sonst gibts
Bytesalat.
Wenn Du nen Timer schreibst, mußt Du ihn anhalten, sonst gibts
Bytesalat.
Wenn Du ihn liest, mußt Du ihn anhalten oder mit Trick 17 auslesen.
Hast Du nen Ablaufplan für das Programm ?
Oder erzähl mal was da und wie es gemessen wird (Zeiten, Frequenzen,
welcher Wertbereich).
Wenn Du was auskommentierst, mußt Du auch konkret sagen was.
Üblicher Weise mit "#if 0" und "#endif" und Kommentar dazu, was es
ändert.
Peter
Was ich in diesem Programm mache ist nach dem Application Note vom
Sensor beschrieben:
http://www.analog.com/UploadedFiles/Application_Notes/320058905AN604.pdf
Ich messe mit dem Timer 2 (CC0 und CC1) die X-Achse, und zwar mit dem
CC1 (steigende Flanke) wird die Zeit T2 (das für beide Achsen gleich
ist) gemessen und mit dem CC0 (zuerst steigende dann fallende Flanke)
die Impulsbreite T1. Mit dem Timer 1 wird im "gated mode" automatisch
die Impulsbreite gemessen.
Wass im Programm abgeht ist folgendes:
-beim drücken von "a" werden erstmal alle Register und Laufvariablen
gelöscht und die Priorität der Interrupt erhöht
-die Schleife " while (e <= 999) " ist da um 1000 Werte zu messen weil
ich die ja als Array speichere und die sind nur 1000.
-dan wird erst die Y-Achse gemessen mit dem Timer 1
-die 3 Schleifen "while (test_Y == 0)", "while (test_T2 == 0)" und
"while (test_X == 0)" sind dazu da um zu überwachen das erst wenn die
Interruptroutine zuende ist er die Schleife verlässt und nicht zwei
Interrupt auf einmal kommen.
-In den Interrupt Routinen werden erstmal die Timer gestoppt dan die
Register eingelesen und dan die Routine verlassen.
- als zweites wird die Periodendauer T2 für beide Achsen gemessen
- als drittes wird die Impulsbreite T1 für dei X Achse gemessen
- dann werden die Werte einfach in float umgewandelt :
X = T1_X; // Dateikonvertierung in Gleitkommazahl
Y = T1_Y; // für die Division
Z = T2;
weil sonst geht die Division nicht
- dann werden die in den g Wert umgerechnet mit der Formel ausm
Application Note : g = (T1/T2 - 50%)/12.5%
- dann werden die ausgegeben
Das Problem ist jetzt wenn ich beide Timer im Programm benutzte geht das
nicht oder geht sehr schlecht (d.h Werte sind unkorekt), aber wenn ich
eine Achse auskommentiere wie z.B:
/
//Mit dem Timer 1 wird die Impulsbreite für die Y-Achse gemessen.
//
while (test_Y == 0)
{
IE1 = 0;
TMOD = TMOD | 0x90;
TR1 = 1;
EX1 = 1;
}
//
//Timer 2 in "capture mode",bei CC1 wird die Zeit T2 für beide Achsen
//messen.
//
while (test_T2 == 0) // Prüfen ob ISR nicht durchlaufen wurde
{
if (IEX4 == 1) // Wenn die positive Flanke erkannt wurde
{
IEX4 = 0;
CCEN = 0x04; // CC1 capture on rising edge
T2CON = 0x41; // startet der Timer 2 in "capture mode" //bei
1MHz
EX4 = 1; // External interrupt enable for CC1
}
}
//
// Timer 2 in "capture mode", bei CC0 wird die Impulsbreite für die
X-Achse gemessen
//
/* while (test_X == 0) // Das ist auskommentiert
{ // d.h es wird nur die Y Achse eingelesen
if (IEX3 == 1)
{
IEX3 = 0;
CCEN = 0x01; // CC0 wird erst auf steigende Flanke gestellt
T2CON = 0x01; // zur Impulserkennung und dann auf fallende um
EX3 = 1; // den Impuls zu messen.
}
}
*/ // bis hier auskommentiert
dann gehts einwandfrei aber nur eine Achse halt und ich muss beide
messen wenn möglich im selben Lauf
Der Prozessor läuft mit 12MHz d.h der Timer mit 1MHz
Die Periodendauer der beiden Achsen ist (ungefähr) Konstant und hat den
Wert um die 7230 (Dezimal) die anderen zwei Zeiten variiren von 1500 bis
4-5000 je nach Neigung. Dann kommt der BeschlWert so zwischen 2 und -2 g
raus. Aber wenn die beiden Timer zusammmen funktioniren geht es nicht
mehr , dann kommt nur Misst raus.
Andy
Du hast da ne ziemlich verquere Logik zwischen den Interrupts und
irgendwelchen Loops im Main.
Versuch das mal aufzudröseln.
Mach also die Messungen entweder nur in Interrupts oder nur im Main,
aber nicht son Mischmasch. Ich seh da jedenfalls nicht durch.
Und nimm für Flags bits und keine ints, das kostet nur unnötig Code und
kann knirschen, wenns nicht atomar ist.
Peter
Und wie macht man Bits deklarieren?? Das finde ich nirgends im Net
Ich kann das nicht im main machen weil dieser Sensor eine zusatzoption
ist an der Maschine. Der soll nicht immer eingelesen werden. Nur wenn
man das will und wenn man "a" drückt.
Die messungen sind doch in der Interruptroutine. Die werden im Programm
dan nur noch verarbeitet.
Andy wrote:
> Und wie macht man Bits deklarieren?? Das finde ich nirgends im Net
Doch, auf der Keil-Webseite oder in Deine Keil C51 Handbuch.
bit ist ein Typ wie char, int usw.
> Ich kann das nicht im main machen weil dieser Sensor eine zusatzoption> ist an der Maschine. Der soll nicht immer eingelesen werden. Nur wenn> man das will und wenn man "a" drückt.>> Die messungen sind doch in der Interruptroutine. Die werden im Programm> dan nur noch verarbeitet.
Ne, da wird irgendwie haufenweise enabled und disabled, gesetzt und
gelöscht usw.
Und dabei hast Du irgendwas verwuselt (sich widersprechende Sachen
gemacht).
Wenn Du mal ne Ablaufplan machst, könntest Du auch herausfinden was.
Laß doch die Interrupts frei laufen und wennse was raushaben, wird das
in ne Variable geschrieben und ein Flag gesetzt.
Und solange das Flag gesetzt ist, wird kein neuer Wert geschrieben,
damit die Werte konsistent bleiben.
Und wenn das Main neue Werte haben will, löscht es das Flag, wartet, bis
es wieder gesetzt ist und liest die Werte aus.
Peter
Das mit dem Interrupts frei laufen lassen klappt irgendwie nicht. Der
springt niemals in die Interruptroutine. Der macht das ganze Programm
durchlaufen ohne einmal die Routine zu besuchen. Kann das mit der
Priorität zusammenhängen ??
Danke für den Tipp mit dem bit, hab ein bisschen Platzt gespart.
Ich kenne mich mit dem T2 des 80535 nicht aus, da der abweichend zu
sämtlichen anderen 8052-ern ist.
Mein Vorschlag, den einen Eingang an INT0, den anderen an INT1 und dann
abwechselnd mal T0 in Gate-Mode zur High-messsung und T1 zur
Periodenmessung und dann umgekehrt.
Peter
Timer 0 kann ich nicht nutzen der ist ja für die Baudrate der
Schnittstelle. Sonst würde ich das schon längst gemacht haben. Aber ich
finde nirgends ein Hinweiss über Timer 2 als Baudratengenerator, damit
ich Timer davon erlöse. Aber wenn ich das noch richtig weis hat der
Timer 2 keine interne Weiterleitung sondern wird nur als Prescaler für
T1 und T0 benutzt, oder??
Ja hab den Baudratengenerator gefunden im Datenblatt. Aber wieder mal
Pech, der Generator in sich ist der Timer 0, nur anders angesprochen.
Habs versucht und wenn ich den Timer 0 dann anspreche geht gar nichts
mehr. Das ist ja richtig Pech im Unglück. Da kommen Werte raus die kann
man als Umsatzzahlen für Siemens annehmen. Und die Schnittstelle spinnt
vollkommen.
................. :-((
Andy wrote:
> Ja hab den Baudratengenerator gefunden im Datenblatt. Aber wieder mal> Pech, der Generator in sich ist der Timer 0, nur anders angesprochen.> Habs versucht und wenn ich den Timer 0 dann anspreche geht gar nichts> mehr.
Ne, das glaub ich Dir nicht.
Der Baudratengenerator ist definitiv extra.
Da machst Du was in der Programmierung falsch.
Wenn Du noch irgendwo nen Link zum Datenblatt dieses Oldies findest,
könnt ich ja mal reingucken.
Verwendet habe ich ihn noch nie.
Peter
Link habe ich leider nicht ich habe die auch bekommen als pdf. Ich werde
Dir den Dattenblatt als Anhang senden (oder brauchst Du den User's
Manual ??) Aber ich werde wieter versuchen vieleicht habe ich ein Fehler
im Code.
Danke
Du könntest recht haben, ich sehe nirgends die Baudratenregister S0RELL
(0AAh), S0RELH (0BAh).
Ich hab nur ein 517 Manual, da stehen sie drin.
Ist ja dann wirklich total blöd.
Peter
Ich gebe Dir trotzdem noch den User's Manuall vieleicht steht da was
drin was ich übersehen habe, oder nicht verstanden, aber der ist ganz
kommisch, der Prozessor irgendwie. Die BAudratengenerator Kontrollbits
sind nicht in diesem Seriell Channel control register sondern, eins im
PCON und eins im ADCON.
http://www.keil.com/dd/docs/datashts/infineon/80x515_um.pdf
Andy
D.h der ist unabhängig von dem Timer 0. Das ist egal weil ich brauch ja
9600. D.h ich kann jetzt en timer 0 erlössen. Aber ich habs versucht und
der Spinnt einbischen. Ich versuche was anderes. Danke
Andrei
Ohhh ich werde noch verückt mit diesem Sensor. Jetzt habe ich es endlich
geschaft in zum laufen zu brigen und er misst mir nicht die
Beschleunigung sondern die Drehung des Sensors zur Basisposition. Gibst
da irgend so ein Trick das man anwenden muss oder eine Formel, oder muss
man irgendwo 2 mal klopfen etc. Bitte rettet den Sensor den ich schmeiss
in glich zum Fenster raus.
Ok ich hab jetzt die Strategie geandert. Ich habe jetzt die analogen
Ausgänge eingelesen aber ich brauch jetzt ein Algoritmus um den
digitalen Wert vom AD- Wandler in einem g-Wert umzuwandeln. Wer kann mir
helfen. Google spuckt nur irrelevantz raus.
Andy