Forum: Mikrocontroller und Digitale Elektronik AD-Wandler STM32


von Paul (Gast)


Lesenswert?

Hallo,
ich versuche mit einem STM32F103 einen 4 Kanaligen AD-Wandler in betrieb 
zu nehmen. Dazu soll der DMA genutz werden. Allerdings habe ich nun das 
Problem, das nur in ADC_values[0] ein sinnvoller Wert. Sieht hier 
irgendjemand wo das Problem liegen könnte?

#define UEW_24V               GPIO_Pin_0
#define UEW_24V_Channel       ADC_Channel_0
#define UEW_7V5               GPIO_Pin_1                  ///<PA1 
ADC12_IN1
#define UEW_7V5_Channel       ADC_Channel_1
#define UEW_5V                GPIO_Pin_2                  ///<PA2 
ADC12_IN2
#define UEW_5V_Channel        ADC_Channel_2
#define UEW_3V3               GPIO_Pin_3                  ///<PA3 
ADC12_IN3
#define UEW_3V3_Channel       ADC_Channel_3
#define UEW_GPIO_PORT         GPIOA                       ///< 
Verwendeter Port mit AD-Wandler

/**
 * @brief Auswahl moeglicher AD-wandler Kanaele
 */
typedef enum {
  AN_UEW_24V,     ///< AD-Wert 24V
  AN_UEW_7V5,     ///< AD-Wert 7,5V
  AN_UEW_5V,      ///< AD-Wert 5V
  AN_UEW_3V3,     ///< AD-Wert 3,3V
  MAX_ANALOG      ///< Anzahl Analoger Eingaenge
} analog_t;

volatile uint16_t ADC_values[MAX_ANALOG];       ///< Array mit Werten 
des AD-Wandlers

/*********************************************************************** 
************  Beginn der Initialisierung 
*************************************/

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ANALOG, ENABLE);
  RCC_ADCCLKConfig(RCC_PCLK2_Div6);
  // GPIO Pins für ADC konfigurieren
  GPIO_InitStructure.GPIO_Pin = UEW_24V | UEW_3V3 | UEW_5V | AN_UEW_7V5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // Analog Mode
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(UEW_GPIO_PORT, &GPIO_InitStructure);

  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;       // ENABLE = 
Multiple Channels
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = MAX_ANALOG;
  ADC_Init(ADC1, &ADC_InitStructure);

  // ADC1 regular channel12 configuration
  ADC_RegularChannelConfig(ADC1, UEW_24V_Channel, 1, 
ADC_SampleTime_41Cycles5);
  ADC_RegularChannelConfig(ADC1, UEW_7V5_Channel, 2, 
ADC_SampleTime_41Cycles5);
  ADC_RegularChannelConfig(ADC1, UEW_5V_Channel,  3, 
ADC_SampleTime_41Cycles5);
  ADC_RegularChannelConfig(ADC1, UEW_3V3_Channel, 4, 
ADC_SampleTime_41Cycles5);

  // Enable ADC1 reset calibration register
  ADC_ResetCalibration(ADC1);
  ADC_StartCalibration(ADC1);
  // Enable ADC1
  ADC_Cmd(ADC1, ENABLE);
  // Enable ADC1 DMA
  ADC_DMACmd(ADC1, ENABLE);

  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    // DMA Configuration
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  // reset DMA channel
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_values;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_PeripheralDataSize = 
DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = MAX_ANALOG;
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  // Enable DMA1 Channel Transfer Complete interrupt
  DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
  //    Enable DMA1 Channel Transfer Complete interrupt
  DMA_Cmd(DMA1_Channel1, ENABLE); //Enable the DMA1 - Channel1
  DMA_Cmd(DMA1_Channel1, ENABLE); //Enable the DMA1 - Channel1

von TripTrab (Gast)


Lesenswert?

Ohne dass ich mich im Detail mit den einzelnen Funktionen beschäftigt
hatte:
Ich würde mir mal mit den zeitlichen Abhängigkeiten der
DMAEnable, ADCEnable und ADC_SoftwareStartConv Kommandos ansehen.

>Allerdings habe ich nun das Problem, das nur in ADC_values[0] ein >sinnvoller 
Wert

WANN stellst Du das fest? Im DMA1 Channel Transfer Complete interrupt?

von pegel (Gast)


Lesenswert?

MAX_ANALOG

kommt mehrfach vor, aber was steht drin?

von Paul (Gast)


Lesenswert?

Ich habe gerade erst mit dem STM32 angefangen und bin daher ncht sicher 
ob ich noch den NVIC für den DMA zu initialisieren muss.

TripTrab schrieb:
> WANN stellst Du das fest? Im DMA1 Channel Transfer Complete interrupt?

ich habe einen kontinuierlichen Funktionsaufruf alle paar Millisekunden 
in dem ich den Inhalt des Arrays (ADC_values) prüfe

von Paul (Gast)


Lesenswert?

pegel schrieb:
> MAX_ANALOG
>
> kommt mehrfach vor, aber was steht drin?


MAX_ANALOG kommt aus dem folgenden enum. Steht also 4 drin.


1
 typedef enum {
2
  AN_UEW_24V,     ///< AD-Wert 24V
3
  AN_UEW_7V5,     ///< AD-Wert 7,5V
4
  AN_UEW_5V,      ///< AD-Wert 5V
5
  AN_UEW_3V3,     ///< AD-Wert 3,3V
6
  MAX_ANALOG      ///< Anzahl Analoger Eingaenge
7
} analog_t;

von pegel (Gast)


Lesenswert?

Paul schrieb:
> enum. Steht also 4 drin

Alles klar.
Ist das ein fertiges Board oder selbst gemacht?
Nicht das PA2 und PA3 für USART benutzt wird.

von Paul (Gast)


Lesenswert?

Ist ein Nucleo Board

von pegel (Gast)


Lesenswert?

Wenn du nichts umgelötet hast, ist das UART zum ST-Link.

von TripTrab (Gast)


Lesenswert?

AN3116: STM32’s ADC modes and their applications

kennst Du?

von pegel (Gast)


Lesenswert?

Es gibt auch ein Beispiel für 3 ADC mit DMA unter:

STM32F10x_StdPeriph_Lib_V3.5.0/Project/STM32F10x_StdPeriph_Examples/ADC/ 
3ADCs_DMA

von TripTrab (Gast)


Lesenswert?

>Ich habe gerade erst mit dem STM32 angefangen und bin daher ncht sicher
>ob ich noch den NVIC für den DMA zu initialisieren muss.

Na selbstverständlich!

von Paul (Gast)


Lesenswert?

was ich nicht ganz verstehe, ist wie das erste element des Arrays 
richtig beschrieben werden kann. Das wird doch wenn ich das richtig sehe 
über
1
 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_values;
eingeleitet. Was muss ich dem DMA für weitere ANgaben machen ,das er das 
Array mit den Werten der anderen ADC s füllt?

von pegel (Gast)


Lesenswert?

siehe 13:41

von Paul (Gast)


Lesenswert?

Das Beispiel unterscheidet sich darin, das hier unterschiedliche ADCs 
verwendet werden. Ich will ja den ADC1 mit 4 Kanälen betreiben

von TripTrab (Gast)


Lesenswert?

>Das Beispiel unterscheidet sich darin, das hier unterschiedliche ADCs
>verwendet werden. Ich will ja den ADC1 mit 4 Kanälen betreiben

Vielleicht trifft das Deinen Geschmack besser:

http://www.embedds.com/multichannel-adc-using-dma-on-stm32/

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.