Forum: Mikrocontroller und Digitale Elektronik STM32F1: ADC Wandler verhalten sich komisch


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Christian J. (Firma: privat) (christianj)


Lesenswert?

Moin,

ich blicke nicht ganz durch, warum sich die beiden Kanäle "vertauschen", 
die ich auslese. Einmal einen LDR (Kanal 0, PA0) und einmal einen 
Widerstandsteilerfür die Batteriespannung (Kanal 8, PB0).

Die richtigen Werte kommen nur raus, wenn die eine Routine ihren Wert 
ausliest und direkt danach schonmal den anderen Kanl vorwählt und die 
Sample startet. Stellt man den Code um, dass jede Routine erst ihren 
Kanal wählt, dann startet, dann wartet sind die Ergebnisse vertauscht.

Mit den Samplezeiten habe ich gespielt, je länger man die macht desto 
ruhiger werden die Werte, je kleiner, desto mehr Rauschen ist drauf.

Ich möchte einfach nur ein Multi-Channel, Single Sampling machen. Keine 
Scans usw.

Es scheint so als würde das Anwählen des Kanals Zeit brauchen, dabei 
müsste das doch sofort passieren.

Das hier würde nicht funzen, bei Val steht dann der Wert drin, der an 
dem anderen Kanal anliegt.
1
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);     
2
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
3
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
4
uint16_t val = ADC_GetConversionValue(ADC1);


1
void Init_LDR()
2
{
3
    GPIO_InitTypeDef    GPIO_InitStructure;
4
    ADC_InitTypeDef     ADC_InitStructure;
5
6
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);                       // GPIOA Clock enable
7
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);                       // ADC Clock enable
8
9
    // ADC Clock auf unter 14 Mhz bringen
10
    RCC_ADCCLKConfig(RCC_PCLK2_Div8);
11
12
    /* ADC Pins konfigurieren A0 und B0----------------------------------------*/
13
    GPIO_InitStructure.GPIO_Pin              = LDR_Pin;                        // AN1 Pin (PA0) aktivieren
14
    GPIO_InitStructure.GPIO_Mode             = GPIO_Mode_AIN;                  // Analog Input
15
    GPIO_InitStructure.GPIO_Speed            = GPIO_Speed_50MHz;
16
    GPIO_Init(GPIOA, &GPIO_InitStructure);
17
18
    GPIO_InitStructure.GPIO_Pin              = VOLT_Pin;                     // AN1 Pin (PA0) aktivieren
19
    GPIO_InitStructure.GPIO_Mode             = GPIO_Mode_AIN;                  // Analog Input
20
    GPIO_InitStructure.GPIO_Speed            = GPIO_Speed_50MHz;
21
    GPIO_Init(GPIOB, &GPIO_InitStructure);
22
23
    /* ADC1 configuration ------------------------------------------------------*/
24
    ADC_InitStructure.ADC_Mode               = ADC_Mode_Independent;           // ADC1 werkelt allein
25
    ADC_InitStructure.ADC_ScanConvMode       = DISABLE;                        // Nur 1 Kanal, keine Scans
26
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;                        // ständige Wandlungen aus
27
    ADC_InitStructure.ADC_ExternalTrigConv   = ADC_ExternalTrigConv_None;      // Start mit Software, nicht durch Hardware
28
    ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;            // Bits rechts ausrichten im Half-Word
29
    ADC_InitStructure.ADC_NbrOfChannel       = 1;                              // 1 Kanal sampeln
30
    ADC_Init(ADC1, &ADC_InitStructure);
31
32
    ADC_Cmd(ADC1, ENABLE);
33
34
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_41Cycles5);     // PA0
35
    /* Enable ADC1 reset calibaration register */
36
    ADC_ResetCalibration(ADC1);
37
    /* Check the end of ADC1 reset calibration register */
38
    while(ADC_GetResetCalibrationStatus(ADC1));
39
    /* Start ADC1 calibaration */
40
    ADC_StartCalibration(ADC1);
41
    /* Check the end of ADC1 calibration */
42
    while(ADC_GetCalibrationStatus(ADC1));
43
    /* Keine Triggerung durch Events etc */
44
    ADC_ExternalTrigConvCmd(ADC1, DISABLE);
45
46
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
47
}
48
49
/* Holt einen AD Wert aus dem LDR und triggert neue Wandlung an */
50
uint16_t GetLDRValue()
51
{
52
    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
53
    uint16_t val = ADC_GetConversionValue(ADC1);
54
    ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_55Cycles5);     // PB0
55
    /* Nächste Wandlung starten */
56
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
57
    return(val);
58
}
59
60
/* Liest die Batteriespannung aus */
61
uint16_t GetBattValue()
62
{
63
    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
64
    uint16_t val = ADC_GetConversionValue(ADC1);
65
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);     // PB0
66
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
67
    return(val);
68
}

: Bearbeitet durch User
von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

Christian J. schrieb:
> Es scheint so als würde das Anwählen des Kanals Zeit brauchen, dabei
> müsste das doch sofort passieren.

Das umschalten erfolgt auch sofort. Das Umladen der S&H-Stufe aber 
nicht. Jenachdem wie hochohmig deine Quelle ist kann das schon etrwas 
dauern.

Kap. 2.3 und 4.4:

https://www.st.com/resource/en/application_note/cd00004444-understanding-and-minimising-adc-conversion-errors-stmicroelectronics.pdf

Noch viel mehr Infos zum ADC:

https://www.st.com/resource/en/application_note/cd00211314-how-to-get-the-best-adc-accuracy-in-stm32-microcontrollers-stmicroelectronics.pdf

von Christian J. (Firma: privat) (christianj)


Lesenswert?

Irgend W. schrieb:
> Das umschalten erfolgt auch sofort. Das Umladen der S&H-Stufe aber
> nicht. Jenachdem wie hochohmig deine Quelle ist kann das schon etrwas
> dauern

Danke! War um die Uhrzeit wohl nicht mehr drin :-) Sample & Hold.... da 
ich ohnehin nur 1x Sec messe werde ich die Messungen einfach switchen in 
der Routine, die zusammen gefasst wird zu einer. Läuft ja ohnehin ohne 
die CPU, die dann auch nicht warten muss.

: Bearbeitet durch User

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]
  • [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.

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