www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik free running


Autor: espoir (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich wollte der free running benutzen, aber mein Englisch nicht so gut
und komme ich nicht zu recht, ich weisse nicht welsche register und so
einsetzen.
ich benutze den ATtiny45, C-programmierung.
die Sachen steht 137-140

Danke euch

Autor: TravelRec. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Free Running ist in den seltensten Fällen sinnvoll - das gezielte
Starten und Auslesen des A/D Converters halte ich persönlich für
vernünftiger - muß aber nicht so sein.

Autor: espoir (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo travelRec,

ja das problem, ich lese aus ein einzige Kanal von AD-Wandler, und ich
warte eine Zeit dazwischen, aber leider klppt nicht.
mit Brack-point fonktinniert schon aber mit normal Lauf wird immer
gleich wert gespeichert.
ich habe dise Frage schon gestellet aber bis jetzt habe ich kein Lösung
gekriegt, das wegen habe ich an free running gedacht.

Danke

Autor: TravelRec. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was genau klappt denn nicht? Der ADC wird gestartet, wenn das Bit6 in
ADCSRA gesetzt wird und wenn es wieder 0 wird, ist der Wert in ADCH und
ADCL gültig. Zudem kann nach erfolgter Wandlung ein Interrupt ausgelöst
werden und dann startet man den ADC eben wieder neu. Das manuelle
Starten im Programm hat den Vorteil, daß man dann immer genau weiß was
der ADC macht und wann man mit einem gültigen Rückgabewert rechen kann
- besonders bei zeitkritischen Sachen.

Autor: espoir (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo TravelRec,

ja! ich lese den Werte an AD-Wandler, und zwischen zwei messungen soll
ich einige Zeit Warten.
Als Algurithmus habe ich so gemacht:
ADC_init(): in dieser fkt wird AD-Wandler eingeschaltet(Enable),und den
Kanal ausgewählt.
Spannug_Umsetzer(): in dieser fkt wird AD_Wandler gestartet,prescaler
auswählen, durch ein While-Schleife wird gewartet, bis das Bit ADSC auf
Null wieder gesetz,dann liefert die fkt den ADCL+(ADCH<<8)zurück.
in main fkt, rufe ich den fkt Spannung_unsetzen() auf, und zwar in eine
for-Schleife (läuft 20 mal), um das Ergebniss in einem Feld zu
speicheren.
das Problem wird in alle Element die gleiche Wert gespeichert. obwohl
mit Breack- Point funktionniert schon.
ich verstehe auch nicht so ganz, was du mit nach erfolgter Wandlung ein
Interrupt auslösen, wie fonktionniert das.

Danke

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bitte poste doch mal den Code, sonst kann Dir hier niemand wirklich
helfen (außer mit Vermutungen).

Du solltest übrigens, wenn Du schon in C programmierst, nicht ADCL und
ADCH separat einlesen, sondern das 16-Bit-Register ADC (bzw. ADCW bei
manchen Compilern) benutzen. Das ist jedenfalls anwendungssicherer als
das was Du oben geschrieben hast...

Der ADC besitzt einen Interrupt, den man zur Auswertung des Ergebnisses
benutzen kann. Wie das mit den Interrupts funktioniert, steht in der
Doku und im Tutorial auf dieser Seite...

Autor: espoir (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Danke erst mal,
an diesem Prroblem Stehe schon seit 2 Wochen, d.h. habe alle meine
ideen ausprobiert, mit Interrupt verstehe das nicht so ganz, ob
wirklich wirckung hat.
Am besten schicke ich dir meinen code die Sachen Konkret zu
diskutieren.
übrigens ich lese nicht den ADCL und ADCH separat.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
unsigned int digital_wert,i;

   digital_wert =5.4894 * Druck;
   digital_wert = digital_wert + 57.294;


Wie soll das gehen?
Integer-Zahlen kennen keine Nachkommastellen!

Autor: espoir (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
diese fkt hat nicht mit meine Frage zu tun, intersirt mich jetzt nur
adc_init,spannug umsetzen und die for schleife.
und ich glaube du weisst nicht mal meine Frage!
und nur als Erklärung, wenn man solche deklaration machen, d.h. er
kriegt nicht ein Nachkommazahlen sondern ein Ganz Zahal.
und wie habe ich gesagt das war nicht die Frage.

Danke

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> while(count<time);

Was soll das bewirken? Da Du augenscheinlich nicht mit Interrupts
arbeitest macht es keinen Sinn, eine Warteschleife zu machen mit einem
Vergleich zweier Variablen, die sich überhaupt nicht ändern können. Da
gibts nämlich nur zwei Möglichkeiten:

1. Die Bedingung ist zum Zeitpunkt der while()-Anweisung falsch, was
dazu führt, dass die Schleife gar nicht durchlaufen wird, also völlig
wirkungslos bleibt.
2. Die Bedingung ist wahr, was dazu führt, dass die Schleife nie wieder
verlassen wird, da sich ja keine der beiden Variablen ändern kann.

Das kann so schon mal nicht funktionieren. Abgesehen davon sehe ich
nirgends eine Anweisung, die count inkrementiert...

Und wie oben schon gesagt: Auf jeden Fall sicherstellen, dass ADCL und
ADCH in der richtigen Reihenfolge ausgelesen werden. Das geht am Besten
mit Zugriff auf das entsprechende 16-Bit-Register.

Für Wartezeiten solltest Du Bibliotheksfunktionen benutzen. Dafür gibts
die schließlich. Bitte schreib noch, welchen Compiler Du nutzt (ich
tippe mal auf AVR-GCC...)

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
BTW: Das was Du machen willst ist eigentlich ein klarer Fall für den ADC
Auto Trigger, am besten über ein Compare-Ereignis vom Timer, der im
CTC-Modus laufen sollte. Das geht am Besten, wenn Du den Timer nicht
für andere Zwecke bereits verplant hast (Das Programm sieht jedenfalls
nicht danach aus). Stelle den Timer so ein, dass er jeweils nach der
gewünschten Wartezeit ein Compare-Ereignis macht und frage den
AD-Wandler mit dem dazugehörigen Interrupt ab. Musst dann nur dran
denken, in der AD-Wandler-Interrupt-Routine das Compare-Flag zu
löschen. Dann kannste Dir den ganzen Mist mit Wartezeiten über
Zeitschleifen (die oft vom Compiler wegoptimiert werden) sparen und
kriegst auf jeden Fall ein sinnvolles Ergebnis.

Autor: espoir (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo johnny,
nur um klar zu sein.
>>void int_timer0(void)
{
  //PORTB=0x17;
  count++;
  TCNT0 = 173;
  TCCR0B = (1<<CS02)|(1<<CS00);
}
in diese fkt wird ein interrupt nach 10 ms ausgelöst, aber ich brauche
ein verschiedene zeit, dafür habe ich die fkt wait,also als parameter
gebe ich ein timer ab, und dann läuft in while schleifebis count=time
ist,bei auslösung den interupt wird den cout incremebtiert.
ADCL und ADCH sind schon in richtige Reihen folege, weil das schon mit
beack-point fonktionniert.
als compiler benutze ich den iccavr, und der mikrocontroller ATtiny45.
das probleme ist bei normal Lauf wird im feld(alle element) die gleiche
werte gespeichert.
mit dein 2. antwort komme ich jetzt nicht so Klar.

danke dir für deine Geduld

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kenne mich zwar nicht mit iccavr aus, aber wenn

void int_timer0(void)
{
  //PORTB=0x17;
  count++;
  TCNT0 = 173;
  TCCR0B = (1<<CS02)|(1<<CS00);
}

eine Interrupt-Routine sein soll, würde ich vermuten, dass da noch ein
#pragma fehlt.
In der main.c steht dann ja auch

//void int_timer0(void);
//#pragma interrupt_handler int_timer0:iv_TIMER0_OVF

wobei das ja auskommentiert ist.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Rahul: Ich selber benutze dieses #pragma nicht. Ich mache das immer mit
INTERRUPT(...._INT){..}

@espoir:
"übrigens ich lese nicht den ADCL und ADCH separat."
Sondern? Genau das machst du doch hier
Ergebnis=(ADCL+(ADCH<<8));

Wiegesagt:
Ergebnis = ADC;
 müsste genausogut funktionieren.
Unter Umständen sogar besser..

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah so. Hab das glatt übersehen, weil die ISR-Syntax vom ICCAVR
anscheinend ein wenig zu unauffällig ist... Wenn Du eine feste Zeit
erzeugen willst (eben z.B. die 10ms) dann betreibe den Timer doch im
CTC-Modus. Er wird dann bei Auftreten eines Compare-Ereignisses
automatisch zurückgesetzt. Du brauchst dann keinen Reload-Wert in TCNTx
zu schreiben. Außerdem kannst Du das Compare-Ereignis dann auch noch als
Auto-Trigger-Quelle für den ADC nutzen.

Ich habe allerdings gerade bei einem Blick ins Datenblatt festgestellt,
dass da anscheinend ein Fehler drin ist. In der Tabelle für die Auto
Trigger-Quellen steht nicht, WELCHER der beiden Timer den ADC triggern
kann. Am besten ausprobieren.

Wenn Du längere Zeiten brauchst oder es unbedingt ohne Auto Trigger
machen willst, dann deklariere eine globale Zählvariable, die in der
Timer Compare ISR inkrementiert und abgefragt wird. Dann könntest Du
z.B. wenn Du alle 50 ms einen Wert einlesen willst, alle 5 Interrupts
den ADC manuell starten. Die Auswertung sollte aber dann mit dem ADC-
Interrupt geschehen. Der ADC muss dazu natürlich für 'Single
Conversion' konfiguriert sein.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit 'übersehen' meinte ich natürlich den Interrupt....

Autor: espoir (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke euch alle, hat schon mit Ergebniss = ADC; geklaapt.
viel,viel................Dank

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wahrscheinlich hat der Compiler deinen Code so übersetzt, dass ADCH und
ADCL in falscher Reihenfolge eingelesen wurden. (Ja, da gibts ne
Reihenfolge, die einzuhalten ist).

Super.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, deshalb war das ja so ziemlich das erste, was ich vermutet habe
(siehe Posting von 12:06). Ist eigentlich ein Fehler, den viele am
Anfang machen (entweder, weil sie das Datenblatt nicht gründlich genug
gelesen haben oder weil sie tatsächlich glauben, dass der C-Compiler
immer schön von links nach rechts übersetzt; dem ist aber überhaupt
nicht so... In diesem Fall wird nämlich vermutlich zuerst der Inhalt
der inneren Klammer übersetzt und genau das ist der springende Punkt)
Aber auf mich hört ja keiner:-(

Autor: Dennis Kleine-Beck (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, ICC ist da etwas eigenwillig.
Alternativ hätte es mit

unsigned int ADC_temp=0;

ADC_temp = ADCL;            // read out ADCL register
ADC_temp += (ADCH << 8);    // read out ADCH register

geklappt.

Dennis

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ja, ICC ist da etwas eigenwillig...

Ich denke mal, dass das nicht ICC-spezifisch ist. Andere Compiler
machen das u.U. genauso. Dafür gibts ja die 16-Bit-Zugriffe. Da weiß
man, dass irgendjemand sich da mal Gedanken zu gemacht hat und dass das
sicher funktioniert.

Autor: Dennis Kleine-Beck (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Da weiß man, dass irgendjemand sich da mal Gedanken zu gemacht hat

Dein Wort in Gottes Ohr! ;-)

Du hast Recht! Zur Vollständigkeit sei noch angemerkt, dass (mit
ICCAVR)

ADC_temp = ADC;

ganze 10 Bytes weniger Programmcode benötigt, als mein Bsp. mit

ADC_temp = ADCL;            // read out ADCL register
ADC_temp += (ADCH << 8);    // read out ADCH register

Dennis

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.