getadc() bringt manchmal falsches Ergebnis

  • 1
  • 2
  • 3
  • 4
  • Page 2 of 4
tschaggelar2
 
Avatar
 
Subject:

Re: getadc() bringt manchmal falsches Ergebnis

 · 
Posted: 11.09.2007 - 19:17  ·  #9
Man koennte sonst auch den ADC im Systick starten, und mit dem ADC Interrupt lesen.

Rene
Gunter
Administrator
Avatar
Gender:
Location: Frankfurt Main / Germany
Posts: 1697
Registered: 02 / 2003
Subject:

Re: getadc() bringt manchmal falsches Ergebnis

 · 
Posted: 11.09.2007 - 19:39  ·  #10
Hallo Rolf,

ich dachte eigentlich daran, nur 1mal am Anfang das Busy zu lesen und
dann ggf. bei dieser SysTick-Runde den ADC zu vergessen ...

Gruß
Gunter
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: getadc() bringt manchmal falsches Ergebnis

 · 
Posted: 11.09.2007 - 20:33  ·  #11
Hallo Gunter,

klar, aber was heist "vergessen" in ASM? Nämlich trotzdem abfragen ob vergessen
oder nicht :ja:

rolf
Gunter
Administrator
Avatar
Gender:
Location: Frankfurt Main / Germany
Posts: 1697
Registered: 02 / 2003
Subject:

Re: getadc() bringt manchmal falsches Ergebnis

 · 
Posted: 11.09.2007 - 20:49  ·  #12
Hallo Rolf,

ohne wirklich vom AVR-ASM Ahnung zu haben:

ADC Status Register am Anfang laden, Busy ausmaskieren und Push (oder in Register sichern).
Falls busy --> ersten Teil des ADC-Handling überspringen.
Rest vom SysTick erledigen
Pop und wenn <> busy dann ADC starten

IMHO wären das doch nur wenige Statements -
oder ist der Systick so stark optimiert, dass was deratiges nicht infrage kommt?

Gruß
Gunter
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: getadc() bringt manchmal falsches Ergebnis

 · 
Posted: 11.09.2007 - 21:08  ·  #13
Hallo Gunter,

klar geht das. Aber hier zählt jeder Maschinen Zyklus, da der Tick oft mit grosser
Rate laufen soll und hier immer die Ints gesperrt sind. Ein paar Push/Pop sollten
keine grosse Rolle spielen, aber es sind ja einer Unmenge solcher Ops im Tick
möglich und ich vermeide jeden unnötigen Code hier. Dazu kommt noch der
Stackverbrauch. Es addiert sich und addiert sich....

Ich sehe da lieber zu dass das ganze System nicht an den Anschlag kommt.
Hier in diesem Fall vermutlich zu viele Ints (evtl. unvermeidlich) und zu hohe
SysTick Rate. Letztere sollte m.E. etwas entspannt werden können.

rolf
bovist
Benutzer
Avatar
Gender:
Age: 64
Homepage: shop.keyboardpartn…
Posts: 34
Registered: 03 / 2006
Subject:

Re: getadc() bringt manchmal falsches Ergebnis

 · 
Posted: 13.09.2007 - 15:40  ·  #14
Hallo Rolf,

mein Workaround sieht jetzt so aus und funtioniert einwandfrei:

Code

procedure onsystick;
begin
  asm;  //  auf AD-Wandlung warten, falls Systick "überfahren" wurde
    ADC10endLoop1:
    in _ACCB, ADCSRA
    sbrc _ACCB,6 // auf Bit 6 low warten
    rjmp ADC10endLoop1
  endasm;
...
end;


OnSysTick wird ja zum Glück aufgerufen, bevor der Timer-Interrupt die ADC-Register ausliest. Sollte der ADC zufällig noch nicht fertig sein, weil der letzte Systick "überfahren" wurde (d.h. beispielsweise weil der Receive-Interrupt dicht war und ein Systick unmittelbar dem nächsten folgt), wartet die kleine Schleife auf das Ende der Wandlung - und nur dann (sonst ist der ADC ja ohnehin fertig). Dieser eine Systick-Interrupt dauert dann halt 100us länger (bei einem Prescaler von 128), sonst bleibt alles wie es war.

Ansonsten: Großes Lob für den AVRCo und den super Support -- muss einfach mal gesagt werden!
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: getadc() bringt manchmal falsches Ergebnis

 · 
Posted: 13.09.2007 - 16:02  ·  #15
Hallo Carsten,
danke für das dicke Lob :unknown:

Der Workaround ist natürlich optimal, mal abgesehen von der u.U. nicht tragbaren
SysTick bzw. Interrupt Sperrzeit Verlängerung dadurch. Wenn dies aber in diesem
Fall nicht weiter stört...
Könnte ja sein, dass z.B. dadurch der UART-Int bei hohen Baudrates ausgebremst
wird.

rolf
bovist
Benutzer
Avatar
Gender:
Age: 64
Homepage: shop.keyboardpartn…
Posts: 34
Registered: 03 / 2006
Subject:

Re: getadc() bringt manchmal falsches Ergebnis

 · 
Posted: 13.09.2007 - 16:22  ·  #16
Rolf,

Die Lösung ist eigentlich ein Kompromiss. Baudrate ist 38400, mehr gibt der 16-MHz-Quarz ohnehin nicht her. Damit dauert ein Zeichen 260 us, der Receive-IRQ wird also mit ebendieser Rate angestoßen, wenn ein Befehls-String eintrifft. Mir kommt es in diesem Fall weniger darauf an, dass das Hauptprogramm genügend Rechenzeit erhält, sondern eher auf die Fehlerfreiheit bei den Messergebnissen.

Es ist natürlich theoretisch nach wie vor möglich, dass ein Receive-Zeichen verlorengeht, weil ausnahmsweise die erwähnte Schleife abgearbeitet wurde und noch ein paar SysTimer aktualisiert werden mussten; ist bei mir aber auch mit heftigen Tests noch nicht vorgekommen.

Denke aber, dass der SysTick selbst im Worst Case nicht länger als 200 us braucht (davon 100 für meine ADC-Scheife; eher weniger, wenn der ADC schon "angefangen" hatte). Gibt es Anhaltswerte, wieviel us/Zyklen ein SysTimer oder SysTimer8 zum Update braucht? Kann mir nicht vorstellen, dass es beim Byte-Timer mehr als 20 Befehle sind.
  • 1
  • 2
  • 3
  • 4
  • Page 2 of 4
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 15 · Cache Hits: 14   116   130 · Page-Gen-Time: 0.027871s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI