STM32F4 ADC hängt

Gast #2871772
Lesenswert?

Hallo,

Ich kämpfe hier gerade mit dem ADC im STM32F4 (Sourcen anbei).
Ich habe das ADC Beispiel aus den Standardtreibern 
(STM32F4xx_StdPeriph_Examples\ADC\VBAT_Measurement) leicht abgewandelt 
(kein VBat, sondern PC1 als Analogeingang), aber bei der 2 Konvertierung 
wird nie das EOC Bit aktiv -->

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

wird nie fertig :(.

Wär toll wenn mir jemand einen Tipp geben könnte, was ich hier falsch 
gemacht habe.

Beste Grüße, Tom
Angehängte Dateien:
Gast #2872042
Lesenswert?

hm...

lass mal die beiden Zeilen in deiner u16 ADCDriver-Funktion weg
wenn du den ContinuousMode=ENABLE hast.

ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, 
ADC_SampleTime_15Cycles);
  // Start the conversion
ADC_SoftwareStartConv(ADC1);

Im kontinuierlichen Modus muss man das nur 1 mal starten, wenn ich mich 
jetzt nicht schwer irre. Ehrlich gesagt rate ich jetzt ins Blaue. Ev. 
kennt sich da jemand besser aus.
#2872146
Lesenswert?

Hab jetzt deinen Code nicht angeschaut, aber hier mal meine Funkion zum 
initialisieren des ADC und die Zum Einlesen eines Channels des ADC3s. 
Vielleicht hilft dir das weiter. Ist allerdings ohne DMA!

An den Kommentaren nicht stören die könnten noch falsch sein!
1
void Init_ADC3()
2
{
3
  /* Enable ADC1 Clocks ****************************************/
4
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
5
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
6

7
    GPIO_StructInit(&GPIO_InitStructure);
8
    /* Configure ADC1 Channel8 pin as analog input ******************************/
9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
10
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
11
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
12
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
13
    GPIO_Init(GPIOC, &GPIO_InitStructure);
14

15

16
    /* ADC Common Init **********************************************************/
17
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
18
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
19
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
20
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_14Cycles;
21
    ADC_CommonInit(&ADC_CommonInitStructure);
22

23
    ADC_StructInit(&ADC_InitStructure);
24
    /* ADC1 Init ****************************************************************/
25
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
26
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
27
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
28
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
29
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
30
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
31
    ADC_InitStructure.ADC_NbrOfConversion = 2;
32
    ADC_Init(ADC3, &ADC_InitStructure);
33

34
    /* ADC3 regular channel11 configuration *************************************/
35
    ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 1, ADC_SampleTime_15Cycles);
36
    /* ADC3 regular channel12 configuration *************************************/
37
    ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 1, ADC_SampleTime_15Cycles);
38

39
    /* Enable ADC3 */
40
    ADC_Cmd(ADC3, ENABLE);
41
}

Hier noch die Funktion zum Auslesen des ADCs
1
uint16_t Get_Volatage(uint32_t samples)
2
{
3
  uint32_t value=0;
4
  int i=0;
5

6
  ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 1, ADC_SampleTime_15Cycles);
7

8
  for(i=0;i<samples;i++)
9
  {
10
    ADC_SoftwareStartConv(ADC3);
11

12
    while(ADC_GetFlagStatus(ADC3,ADC_FLAG_EOC) != SET)
13
    {
14

15
    }
16

17
    value += ADC_GetConversionValue(ADC3);
18
  }
19

20
  return (value/samples);
21
}

In main einfach die Init aufrufen und dann die Get_Voltage
Gast #2872642
Lesenswert?

Thomas Horn schrieb:
> @Stefan
> Ich habe jetzt deine Kode 1:1 übernommen und trotzdem hängt die
> Konvertierung.
> Mhhh...

Sicher das da nicht irgendwo anders noch was im Argen liegt? Schon mal 
debugger laufen lassen? Viell. hängt dein Programm irgendwo in einer 
default interrupt funktion oder so. Check das mal.
#2872833
Lesenswert?

Benutze Eclipse CDT, arm-none-eabi-gcc . Breakpoints for und nach dem 
while. Wenn ich dann unterbreche, dann steckt der µC in der 
ADC_GetFlagStatus. Außerdem sehe ich  im ADC1->SR2 bzw ADC3->SR2 das das 
EOC nicht hochgeht.
Ich habe sicherheitshalber auch mal alle andere Sachen aus dem Programm 
rausgeschmissen, keine Änderung.
#2873417
Lesenswert?

Hallo,
Ich habe für die Clock-Einstellung das ST Tool (so ein Excel-sheet) 
benutzt.
Naja, Prozessor läuft, Baudraten sind richtig, I2C Zeiten stimmen und in 
den Inits werden AHB1 bzw. AHB2 Takte eingestellt.
Und.... die erste Konvertierung funktioniert.
Im SR steht 0x30 , also OVR und STRT sind gesetzt. Könnte das etwas 
bedeuten, muss ich die evt. vorher löschen?
#2873459
Lesenswert?

Ja, wird in der startup_stm32f4xx.s aufgerufen (sonst würden ja auch die 
anderen Zeiten zB. (serielle Baudraten) nicht stimmen.
1
/* Call the clock system intitialization function.*/
2
  bl  SystemInit   
3
/* Call static constructors */
4
    bl __libc_init_array
5
/* Call the application's entry point.*/
6
  bl  main
7
  bx  lr    
8
.size  Reset_Handler, .-Reset_Handler
#2998086
Lesenswert?

Also das gleiche Problem hatte ich auch mal. Ich habe den ADC nicht im 
continouous mode laufen gehabt sondern zum einzeln anstossen.

Damit das mehr als nur einmal funktioniert musste ich vor dem erneuten 
Startem von ADC und DMA alle Flags löschen:
1
ADC_ClearFlag((ADC_TypeDef*)(AdcPort), ADC_FLAG_AWD | ADC_FLAG_EOC | ADC_FLAG_JEOC | ADC_FLAG_JSTRT | ADC_FLAG_STRT | ADC_FLAG_OVR);
2

3
DMA_ClearFlag(DmaChannelAddr, DMA_FLAG_TCIF0);
4
DMA_ClearFlag(DmaChannelAddr, DMA_FLAG_HTIF0);
5
DMA_ClearFlag(DmaChannelAddr, DMA_FLAG_TEIF0);

Erst danach ging es, was etwas merkwürdig ist, da die DMA-Flags garnicht 
aktiviert waren und nur für Interrupts gedacht sind die ich auch nicht 
genutzt habe.

Ich glaube es kam hauptsächlich auf die DMA-Flags an, die ADC-Flags 
wurden nur zur Sicherheit mit gelöscht.
#2998261
Lesenswert?

Hallo,
@Ingo
Nein, ich hatte auf den Teil dann erst mal in der SW verzichtet und bin 
seitdem nicht mehr zum Testen gekommen.

@Star Keeper
Das wäre ja recht komisch, wenn die DMA Flags diesen Einfluss auf den 
ADC haben.
Ich muss im Laufe des Monats mal wieder an den STM32 ran, dann werde ich 
das auch mal in meine SW einbauen. Ich melde dann, wie es gewirkt hat.

Beste Grüße, Tom
Gast #2998890
Lesenswert?

So, ich hab den Fehler:
1
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
2
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
3

4
  ADC_InitTypeDef       ADC_InitStructure;
5
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
6
  GPIO_InitTypeDef      GPIO_InitStructure;
7

8
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
9
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
10
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
11
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
12
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
13
  GPIO_Init(GPIOC, &GPIO_InitStructure);
14

15
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
16
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;
17
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
18
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
19
  ADC_CommonInit(&ADC_CommonInitStructure);
20

21
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_8b;
22
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
23
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
24
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
25
  ADC_InitStructure.ADC_ExternalTrigConv = 0;
26
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
27
  ADC_InitStructure.ADC_NbrOfConversion = 1;
28
  ADC_Init(ADC3, &ADC_InitStructure);
29

30
  ADC_EOCOnEachRegularChannelCmd( ADC3, ENABLE );
31
  ADC_RegularChannelConfig(ADC3, ADC_Channel_13, 1, ADC_SampleTime_3Cycles);
32
  ADC_Cmd(ADC3, ENABLE);
Ganz wichtig ist offensichtlich, dass alle Mitglieder der Struct 
initialisiert werden. Nehme ich
1
ADC_InitStructure.ADC_ExternalTrigConv = 0;
raus, gehts nicht mehr. Ich hoffe jemand kann was damit anfangen.
Ich wüsste gern mal wo sowas geschrieben steht!!!

Ingo
Gast #2998896
Lesenswert?

Achso, wichtig ist das der ADC bereits initialisiert ist bevor man ihn 
benutzt. Das ist z.B. nicht der Fall, wenn der ADC durch Timerinterrupts 
getriggert wird. Hierzu sollte man sich ein Flag erstellen, welches nach 
der ADC-Initialisierung gesetzt wird. Erst wenn das Flag gesetzt ist, 
darf man auf den ADC zugreifen.



Ingo
Gast #2998943
Lesenswert?

Was bezeichnest Du als "Initialisierung"?
(Einschalten der Clks, GPIO vorbereiten, Modes einstellen...,
oder bereits das Starten eine Wandlung?)
Warum initialisiert man ihn nicht bereits nach dem Hochfahren
des Systems (einmalig)?

ADC_InitTypeDef       ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
GPIO_InitTypeDef      GPIO_InitStructure;

Gibt es vielleicht etwas wie InitStructureAdc(&InitStructure)?
(bei Windows wird so etwas benutzt)
Oder vielleicht hilft auch einfach ein
memset(&InitStructure, 0, sizeof(InitStructure));
damit die ganzen Felder einen Default-Wert (?) haben?
Gast #2999009
Lesenswert?

> Ja, genau das.

A oder B?

> Macht man doch

Wenn man den ADC initialisiert, bevor ein Timer überhaupt laufen kann
oder zuschlagen kann, braucht man an dieser Stelle auch nicht
aufpassen oder ein Flag, um sich dies zu merken?

Sollte nicht erst einmal alles vorbereitet werden
und am Schluss gibt es ein "GO", mit dem das System zum Laufen
gebracht wird? Sonst hat man ja eine Unmenge an Fälle, die
man behandeln muss...
#2999048
Lesenswert?

Es gibt für jedes Struct der STM32Lib auch eine Funktion die dieses 
struct initialisiert. Diese Funktion sollte man natürlich benutzen, wenn 
man nicht selber alle Werte setzt. Woher soll die Library denn nun 
wissen welche Teile des struct korrekte Werte enthalten und welche 
nicht...
Gast #2999264
Lesenswert?

Helfender schrieb:
> Wenn man den ADC initialisiert, bevor ein Timer überhaupt laufen kann
> oder zuschlagen kann, braucht man an dieser Stelle auch nicht
> aufpassen oder ein Flag, um sich dies zu merken?

Also ich persönlich initialisiere hier z.B. ein neben einem EAGOGM163, 
einen U2270, ein MCP3901, einen Pegelwandler und ein Modem, sowie 
diverse Peripherie des Controllers. Beim LCD z.B. läuft der Systick 
Timer schon, damit ich schöde Delays sauber einhalten kann. Es war wie 
gesagt nur eine Möglichkeit, letztendlich kann das jeder machen wie er 
will...

Star Keeper schrieb:
> Es gibt für jedes Struct der STM32Lib auch eine Funktion die dieses
> struct initialisiert. Diese Funktion sollte man natürlich benutzen, wenn
> man nicht selber alle Werte setzt.

Meinst du die DeInit?

Ingo

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren