Forum: Mikrocontroller und Digitale Elektronik STM32 zwei ADC channels auslesen ohne DMA


von Sebastian T. (sebastian_tsch)


Lesenswert?

Hi,

Ich versuche mit einem STM32f303x und den HAL libraries zwei Channels 
des ADC's auszulesen. Mit DMA geht alles wunderbar, aber wie man das 
ohne DMA per software macht, da blicke ich im Moment noch nicht durch. 
Ich muss zwei Strommessungen in Echtzeit machen und genau dann, wenn ich 
die brauche. Wie genau kann ich die Werte eines Channels des ADC mit den 
HAL libraries abfragen?

von Robin S. (der_r)


Lesenswert?

Schau mal hier:

https://developer.mbed.org/teams/Senior-Design-Sound-Monitor/code/STM32L4xx_HAL_Driver/docs/80ee8f3b695e/group__ADC__Exported__Functions__Group2.html

Ist zwar nicht für deinen Controller, aber die HAL-Befehle gleichen sich 
in der Regel.

Du musst deine beiden Channel z.B. als regular Channels hinzufügen, dann 
die Wandlung aller Regular Channel (=regular group) starten, auf den 
Abschluss der Wandlung warten (ohne Interrupt mittels der 
PollForConversion-Funktion beispielsweise) und schließlich den Wert 
abholen.



Noch besser natürlich den EOC (End of Conversion) Interrupt statt der 
Warterei benutzen.

von Sebastian T. (sebastian_tsch)


Lesenswert?

Ok, danke dir. Ich verstehe aber noch nicht ganz wie ich jetzt die Werte 
für beide Channels abholen kann. Zuerst starte ich ja die conversion mit
1
HAL_ADC_Start(&hadc2);

Dann muss ich warten, bis die conversion abgeschlossen ist (Interrupt 
oder Polling).

Mit folgender Funktion sollte ich irgendwie die Werte abholen können:
1
uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef * hadc);

Diese Funktion gibt mir aber nur einen uint32_t zurück und keine Adresse 
für die Werte. Jemand eine Idee?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sebastian T. schrieb:
> Diese Funktion gibt mir aber nur einen uint32_t zurück und keine Adresse
> für die Werte. Jemand eine Idee?

 Wenn du mit:
1
 HAL_ADC_Start(&hadc2);
 adc2 startest, dann solltest du auch diese Werte abholen.

 Etwa so:
1
  HAL_ADC_Start(&hadc2);
2
  if (HAL_ADC_PollForConversion(&hadc2, 5) == HAL_OK) {
3
      uint16_t  Wert = HAL_ADC_GetValue(&hadc2);
4
  }

 P.S.
 Wert ist im Register DR.

von Nico W. (nico_w)


Lesenswert?

Sebastian T. schrieb:
> Ich muss zwei Strommessungen in Echtzeit machen und genau dann, wenn ich
> die brauche.

Warum glaubst du dass genau das mit DMA nicht gehen sollte? Warum soll 
das genau ohne gehen?

Echtzeit bedeutet pünktlich. Nicht sofort.

Der DMA sollte das sogar noch schneller können. Der startet schon die 
nächste Wandlung bevor der ADC überhaupt weiß das er fertig ist, bzw. du 
im Interrupt angekommen bist.

von nur malso (Gast)


Lesenswert?

um mal den alten Thread hoch zu holen,
gibt es eine Möglichkeit per polling mehrere Channel aus zu lesen?

wie das ganze mittels DMA funktioniert weiß ich,
aber es muss doch auch anders funktionieren (vermeintlich einfacher).

wenn ich

  HAL_ADC_Start(&hadc2);
  if (HAL_ADC_PollForConversion(&hadc2, 5) == HAL_OK) {
      uint16_t  Wert1 = HAL_ADC_GetValue(&hadc2);
  }
  if (HAL_ADC_PollForConversion(&hadc2, 5) == HAL_OK) {
      uint16_t  Wert2 = HAL_ADC_GetValue(&hadc2);
  }
  HAL_ADC_Stop(&hadc2);

benutze, dann wird die zweite if abfrage nie erfüllt, sprich Wert2 
bekommt keinen Wert zugewiesen.

nutze ich hingegen (auch schon mehrfach im Netz gesehen)
  HAL_ADC_Start(&hadc2);

  HAL_ADC_PollForConversion(&hadc2, 5);
  uint16_t  Wert1 = HAL_ADC_GetValue(&hadc2);

  HAL_ADC_PollForConversion(&hadc2, 5);
  uint16_t  Wert2 = HAL_ADC_GetValue(&hadc2);

  HAL_ADC_Stop(&hadc2);

so bekommen Wert1 und Wert2 den gleichen Wert zugewiesen.

es ist auch egal ob "ContinuousConvMode" an ist oder nicht.

Also frage in die Runde, ist dieses wirklich nur mit DMA zu lösen?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Meiner Erfahrung nach (kein Anspruch auf Allwissen) ist die DMA am 
einfachsten. Man konfiguriert ADC und DMA, startet das ganze und holt 
sich dann die Werte, wenn man sie braucht. Und das ganze läuft so gut im 
Hintergrund, das es die wahre Freude ist.

von Haas (Gast)


Lesenswert?

Das hier ist eine Möglichkeit:

  hadc.Instance->CHSELR = 1 << 1;  // ADC Channel 1
  HAL_ADC_Start(&hadc);
  Wert1 = HAL_ADC_GetValue(&hadc);

  hadc.Instance->CHSELR = 1 << 2; // ADC Channel 2
  HAL_ADC_Start(&hadc);
  Wert2 = HAL_ADC_GetValue(&hadc);

Grüße

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.