05-ADC-Single-Conversation (STM32F4)

-diese Library dient zum betreiben der AD-Wandler im Single-Conversation-Mode

-die ADC-Pins die benutzt werden sollen, müssen im H-File deklariert und im C-File den entsprechenden Port-Pins zugeordnet werden.

-es kann auch eine Mittelwertbildung von dem Messwert durchgeführt werden
(die Messdauer steigt dann natürlich entsprechend an)

-es gibt zwei identische Libs einmal für ADC1 und einmal für ADC2
(sie unterscheiden sich nur in den verwendeten Variabelnnamen)

Hier eine Auswertung über die Genauigkeit :
Spannungswert über einen 100k Poti (ohne externen Kondensator)
100.000 Messungen und dann Anzeige der Min- und Max- AD-Werte
(ADC mit 12Bit, URef = 3V, 1 Digit ca 730 uV)

1
2
3
4
5
6
7
8
Ohne Mittelwerte :  814 - 1144 = +/- 165
   2 Mittelwerte :  974 - 1132 = +/- 79
   4 Mittelwerte :  990 - 1114 = +/- 62
   8 Mittelwerte : 1014 - 1101 = +/- 43
  16 Mittelwerte : 1036 - 1086 = +/- 25
  32 Mittelwerte : 1043 - 1077 = +/- 17
  64 Mittelwerte : 1052 - 1068 = +/- 8
 128 Mittelwerte : 1054 - 1066 = +/- 6

-im Beispiel wurden 3 Pins als Analog-IN definiert und per ADC1 gemessen

1
PA3, PC4, PC5

Voraussetzungen :

1
2
Benutzte Module der CooCox-IDE : GPIO, ADC
Benutzte Librarys : keine

Enumerationen (für ADC1) :

1
2
3
4
5
typedef enum {
  ADC_PA3 = 0,  // PA3
  ADC_PC4 = 1,  // PC4
  ADC_PC5 = 2   // PC5
}ADC1s_NAME_t;

:

1
2
3
4
5
6
7
8
9
10
typedef enum {
  MW_NONE =0,  // keine Mittelwerte
  MW_2,        // 2 Mittelwerte
  MW_4,        // 4 Mittelwerte
  MW_8,        // 8 Mittelwerte
  MW_16,       // 16 Mittelwerte
  MW_32,       // 32 Mittelwerte
  MW_64,       // 64 Mittelwerte
  MW_128       // 128 Mittelwerte
}ADC1s_MW_t;

Funktionen (für ADC1) :

1
2
3
void UB_ADC1_SINGLE_Init(void);                         // zum init des ADC1
uint16_t UB_ADC1_SINGLE_Read(ADC1s_NAME_t adc_name);    // zum auslesen eines ADC direkt
uint16_t UB_ADC1_SINGLE_Read_MW(ADC1s_NAME_t adc_name); // zum auslesen eines ADC mit Mittelwertbildung

Beispiel :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//--------------------------------------------------------------
// File     : main.c
// Datum    : 17.02.2013
// Version  : 1.0
// Autor    : UB
// EMail    : mc-4u(@)t-online.de
// Web      : www.mikrocontroller-4u.de
// CPU      : STM32F4
// IDE      : CooCox CoIDE 1.7.0
// Module   : CMSIS_BOOT, M4_CMSIS_CORE
// Funktion : Demo der ADC-Single-Library
// Hinweis  : Diese zwei Files muessen auf 8MHz stehen
//              "cmsis_boot/stm32f4xx.h"
//              "cmsis_boot/system_stm32f4xx.c"
//--------------------------------------------------------------
 
#include "main.h"
#include "stm32_ub_adc1_single.h"
#include "stm32_ub_led.h"
 
int main(void)
{
  uint16_t adc_wert;
 
  SystemInit(); // Quarz Einstellungen aktivieren
 
  UB_ADC1_SINGLE_Init(); // Init vom ADC1
  UB_Led_Init();         // Init der LEDs
 
  while(1)
  {
    // ADC-Kanal an PA3 messen und 3 LEDs entsprechend schalten
    adc_wert=UB_ADC1_SINGLE_Read_MW(ADC_PA3);
    if(adc_wert>1024) UB_Led_On(LED_GREEN); else UB_Led_Off(LED_GREEN);
    if(adc_wert>2048) UB_Led_On(LED_ORANGE); else UB_Led_Off(LED_ORANGE);
    if(adc_wert>3072) UB_Led_On(LED_RED); else UB_Led_Off(LED_RED);
 
    // ADC-Kanal an PC4 messen und die Blaue LED entsprechend schalten
    adc_wert=UB_ADC1_SINGLE_Read_MW(ADC_PC4);
    if(adc_wert>2048) UB_Led_On(LED_BLUE); else UB_Led_Off(LED_BLUE);
  }
}

Beschreibung :

1
2
3
4
5
6
7
8
9
Funktion :
-ADC1 wird im Single-Conversation Mode initialisiert
-es wird die Analog-Spannung an PA3 und PC4 gemessen (in der LIB definiert)
-die 4 LEDs werden ja nach Spannungswert entweder ein-
oder ausgeschaltet
 
Librarys die für das Beispiel benutzt werden :
-stm32_ub_adc1_single
-stm32_ub_led

Hier die Library zum Download :

ub_stm32f4_adc_single_v100

Hier der komplette CooCox-Projektordner zum Download :

Demo_05_ADC_Single

25 Antworten auf 05-ADC-Single-Conversation (STM32F4)

  1. Tom sagt:

    Hallo,
    Zwei kurze Fragen ;)
    Wo wird denn der Referenzwert für die ADC-Spannung angegeben?
    Und wie hoch ist die maximale Spannung die an einen Pin angelegt werden kann?

    • admin_ub sagt:

      solche sachen (und andere) stehen im Datenblatt.

      • Tom sagt:

        Hast du recht ;)
        Sorry

  2. Joerg sagt:

    Irgendwie habe ich das mit den enums nicht verstanden…

    adc_wert=UB_ADC1_SINGLE_Read_MW(ADC_PA3); ruft einen Wert ab
    wie muss es aussehen um den Aufruf mit Mittelwert zu machen?

    • admin_ub sagt:

      die Funktion “UB_ADC1_SINGLE_Read_MW” mittelt den ADC-Wert schon. Die direktmessung wäre die Funktion “UB_ADC1_SINGLE_Read”

      im ADC C-File wird ganz zu Anfang in einer Liste eingetragen wieviele Mittelwerte benutzt werden sollen…das kannst du event. noch anpassen.
      in der Demo steht da z.B. für ADC_PA3 “MW_32″ drinn …also wird der Mittelwert aus 32 Messwerten gebildet.

  3. Joerg sagt:

    von Blindheit geschlagen gewesen ;)

    Danke

  4. X_X sagt:

    Danke für die lib, die macht das alles noch ein wenig handlicher.
    Gerade habe ich aber ein Weilchen gebraucht, wo der Fehler lag, weil zwei Werte, die nacheinander gesampled wurden immer identisch waren. Die Lösung liegt in einem

    #ifdef __cplusplus
    extern “C” {
    #endif

    … tolle LIB

    #ifdef __cplusplus
    }
    #endif

    , da ich C++ programmiere.

    Eventuell könnte man das in den Standard-Lib-Rahmen aufnehmen ;)

    Gruß
    x_X

    • admin_ub sagt:

      es steht dir frei diese Änderung in allen Librarys zu machen…ich brauch die nicht, da ich in “C” programmiere :-)

  5. X_X sagt:

    wenn ich zwei kanäle nacheinander abfrage, scheint es ein übersprechen zwischen den kanälen zu geben… ist dieses phänomen bekannt?

    ich wende es so an:
    tester[7] = ((float) UB_ADC1_SINGLE_Read_MW(ADC_PC4)) / 4096.0f;

    tester[8] = ((float) UB_ADC1_SINGLE_Read_MW(ADC_PA3)) / 4096.0f;

    config:
    ADC1s_t ADC1s[] = {
    //NAME ,PORT , PIN , CLOCK , Kanal , Mittelwerte
    {ADC_PC4,GPIOC,GPIO_Pin_4,RCC_AHB1Periph_GPIOC,ADC_Channel_14,MW_32}, // ADC an PC4 = ADC12_IN14

    {ADC_PA3,GPIOA,GPIO_Pin_3,RCC_AHB1Periph_GPIOA,ADC_Channel_3 ,MW_32}, // ADC an PA3 = ADC123_IN3
    };

    • admin_ub sagt:

      ist an den beiden Pins auch was angeschlossen ? bei einem offenen Eingang kann ein übersprechen auftauchen aber sobald an allen Eingängen ein niederohmiges Signal hängt dürfte das nicht mehr sein.

  6. X_X sagt:

    Niederohmig ist vielleicht Defintionsfrage:
    Es sind 10k Potis an 3 V und GND, deren Mittelabgriffe am ADC anliegen.
    Wenn ich keine Mittelwertbildung mache, ist der erste Wert, den ich am zweiten ADC-Pin auslese quasi identisch mit dem des anderen Pins… Durch die mehrfache Auslesung bei der MW-Bildung wirds halt besser…

    • admin_ub sagt:

      bin mir nicht sicher ob der erste Wert nach dem Umschalten vom MUX verworfen werden sollte … müsste ich mal ausprobieren.

    • admin_ub sagt:

      ich bin gerade an den ADC-Libs für den STM32F429 und da ist es auch so. Wenn ein Eingang offen ist, zeigt er den gleichen Wert an wie der andere ADC mit Poti. Aber sobald an beiden ein Poti angeschlossen ist (5k || 100nF) zeigen Sie jeweils den Wert an den Sie sollen. Der Werte schwanken allerdings stark, man muß schon 64-Mittelwerte benutzen wenn man 12bit Auflösung will.

      • X_X sagt:

        Hast du mal das zuletzt ausgelesene Poti auf null gestellt, und dann am zweiten gedreht? Wenn ich das erste auf 100% stelle, ist der andere wert oberhalb von null.

        • admin_ub sagt:

          Also das geht bei mir. Aber ich komme nicht auf 0 sondern nur auf 1..3 runter (unabhängig vom anderen Kanal). Wenn dir 11bit (oder 10bit) Auflösung reichen, kannst du das Ergebnis ja nochmal durch 2 bzw 4 Teilen…dann wird das ganze vielleicht besser.

          • X_X sagt:

            Die 100 nF parallel zum Mittelabgriff scheinen der Einzige Unterschied zu sein. Das werde ich bei Gelegenheit mal testen.

  7. Joerg B sagt:

    Gibt es das Lib auch für ADC3?

  8. Frank M. sagt:

    Es empfiehlt sich, unmittelbar nach

    ADC_InitTypeDef ADC_InitStructure;

    die Funktion

    ADC_StructInit (&ADC_InitStructure);

    aufzurufen. Sonst kann es passieren, dass

    while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);

    nur einmal korrekt funktioniert und bei weiteren Aufrufen in einer Endlosschleife hängt.

    Der Grund ist, dass nicht alle Member von ADC_InitStructure in der Initialisierung vollständig beschrieben werden. Je nach Inhalt, der auf dem Stack herumliegt, tritt dann dieses Problem auf. Nachdem ich genau dieses Problem hatte, habe ich im Internet recherchiert. Dabei ist dann aufgefallen, dass viele Beispielcodes hier genau dieses Problem haben.

    Beispiel-Link:

    http://www.mikrocontroller.net/topic/273743

    • admin_ub sagt:

      danke für den Hinweis. Werd ich beim nächsten update einfügen.

  9. Flip sagt:

    Hallo,

    ichv ersuche mit dem STM32E407 mehrere analoge Eingänge zu programmieren, bekomme aber nur den Eingang “PC0″,was dem Pin “A0″ entspricht als analogen Eingang hin.

    Die Eingänge PF6 bis PF10 als die restelichen A1-A5 wollen bei mir nicht laufen. Aus was muss ich achten, wenn ich diese implementieren möchte, habe in den Datenblättern nichts brauchbares für mich gefunden.

    Danke

    Gruß Phil

    • Flip sagt:

      sry,
      habe es nach intensiverem Nachdenken hinbekommen ;-)

  10. Flo sagt:

    Hallo,

    ich versuche nun anstatt Spannungssignale, Stromewerte mittels Stromsensoren einzulesen, doch dies funktioniert bei mir nicht.

    Wie muss ich dabei vorgehen? Auf was muss ich achten?
    Und ist dies überhaupt möglich, Werte von Stromsensoren auszulesen?

    Viele Grüße und Danke
    Flori

    • admin_ub sagt:

      was ist den ein “Stromsensor” ?
      falls es kein shunt ist, sondern ein IC empfehle
      ich das datenblatt zum sensor zu lesen…da stehen nützliche infos drin.
      z.B. wie er auszulesen ist und worauf man achten muss.

      • Flo sagt:

        Ich meine, ich habe ein Stromsignal, welches ich direkt an den ADC Eingang anschließe (wo ich sonst Spannungssignale messe), aber ich bekomme keine Stromwerte angezeigt. muss ich zusätzlich Hardware kaufen, um Stromwerte einlesen zu können?

        • admin_ub sagt:

          der ADC misst Spannungen und keine Ströme.
          Und ein “Strom” fließt auch nicht irgendwie aus einem Sensor raus. Schreib doch einfach um was für einen Sensor es sich handelt (die Bezeichnung) sonst ist das hier nur ein Ratespiel und für Ratespiele bin ich zu alt.


Wie hat Dir dieser Artikel gefallen?

1 Stern2 Sterne3 Sterne4 Sterne5 Sterne (Noch keine Bewertungen)
Loading...

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert