Forum: Mikrocontroller und Digitale Elektronik STM32F2 ADC Continous Scan mit DMA, Softwareproblem


von Alex K. (shadow851)


Lesenswert?

Hi Leute,

ich versuche aktuell auf einem STM32F205VG mit ADC1 im continuous scan 
modus zwei pins und den Temperatursensor einzulesen. Die Daten sollen 
via DMA in ein struct kopiert werden.

Folgenden Quelltext hab ich mir aus den Herstellerbeispielen zusammen 
gestellt und inzwischen auch einiges an Zeit mit Fehlersuche verbraten, 
da das struct sich einfach nicht füllen will. Wenn jemand von euch den 
Fehler sieht wärs super.

Da das einlesen von mehreren Pins erfolglos war habe ich die (mMn) 
zuständigen Stellen auskommentiert um mit den eingefügten Pendants es 
erstmal mit einem Pin zum Laufen zu kriegen, wieder erfolglos...

#define HMI_GIER_PORT          GPIOA
#define HMI_GIER_PIN          GPIO_Pin_5
#define HMI_GIER_CLK          RCC_AHB1Periph_GPIOA
#define HMI_GIER_ADC_CHANNEL      ADC_Channel_5
#define HMI_THROTTLE_PORT        GPIOC
#define HMI_THROTTLE_PIN        GPIO_Pin_1
#define HMI_THROTTLE_CLK        RCC_AHB1Periph_GPIOC
#define HMI_THROTTLE_ADC_CHANNEL    ADC_Channel_11

#define HMI_ADC              ADC1
#define HMI_ADC_CLK            RCC_APB2Periph_ADC1

#define HMI_DMA              DMA2
#define HMI_DMA_CHANNEL          DMA_Channel_0
#define HMI_DMA_STREAM          DMA2_Stream0
#define HMI_DMA_CLK            RCC_AHB1Periph_DMA2
#define HMI_ADC_DR_Address        ((uint32_t)HMI_ADC+0x10)

...

typedef struct {
  uint8_t    start;
  uint16_t  gier;
  uint16_t  throttle;
  uint16_t  cpu_temp;
  uint8_t    stop;
} SENSORS_t;
__IO SENSORS_t SENSOR_States;

...

/*!< Enable ADC1, DMA2 and GPIO clocks */
  RCC_AHB1PeriphClockCmd(HMI_DMA_CLK | HMI_GIER_CLK | HMI_THROTTLE_CLK, 
ENABLE);
  RCC_APB2PeriphClockCmd(HMI_ADC_CLK, ENABLE);

  /*!< DMA2 Stream0 configuration */
  DMA_DeInit(HMI_DMA_STREAM);
  DMA_InitStructure.DMA_Channel = HMI_DMA_CHANNEL;
  DMA_InitStructure.DMA_PeripheralBaseAddr = 
(uint32_t)HMI_ADC_DR_Address;
  DMA_InitStructure.DMA_Memory0BaseAddr = 
(uint32_t)&(SENSOR_States.gier);
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  //DMA_InitStructure.DMA_BufferSize = 3;
  DMA_InitStructure.DMA_BufferSize = 1;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  //DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = 
DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(HMI_DMA_STREAM, &DMA_InitStructure);
  DMA_Cmd(HMI_DMA_STREAM, ENABLE);

  /*!< Configure pins as analog input */
  GPIO_InitStructure.GPIO_Pin = HMI_GIER_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(HMI_GIER_PORT, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = HMI_THROTTLE_PIN;
  GPIO_Init(HMI_THROTTLE_PORT, &GPIO_InitStructure);

  /*!< TempSensor and VrefInt Init */
  ADC_TempSensorVrefintCmd(ENABLE);

  /*!< ADC Common Init */
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
  ADC_CommonInitStructure.ADC_DMAAccessMode = 
ADC_DMAAccessMode_Disabled;
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = 
ADC_TwoSamplingDelay_20Cycles;
  ADC_CommonInit(&ADC_CommonInitStructure);

  /*!< ADC1 Init */
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  //ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = 
ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  //ADC_InitStructure.ADC_NbrOfConversion = 3;
  ADC_InitStructure.ADC_NbrOfConversion = 1;
  ADC_Init(ADC1, &ADC_InitStructure);

  /*!< ADC1 regular channel configuration */
  ADC_RegularChannelConfig(ADC1, HMI_GIER_ADC_CHANNEL, 1, 
ADC_SampleTime_3Cycles);
  //ADC_RegularChannelConfig(ADC1, HMI_THROTTLE_ADC_CHANNEL, 2, 
ADC_SampleTime_3Cycles);
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, 3, 
ADC_SampleTime_3Cycles);

  /*!< Enable DMA request after last transfer (Single-ADC mode) */
  ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);

  /*!< Enable ADC1 DMA */
  ADC_DMACmd(ADC1, ENABLE);

  /*!< Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);

  /*!< Start ADC1 Software Conversion */
  ADC_SoftwareStartConv(ADC1);

Danke für eure Hilfe im Voraus,
Alex

von Hans (Gast)


Lesenswert?

Lass DMA mal weg...dann gehts.

von Alex K. (shadow851)


Lesenswert?

Ohne DMA würde es wahrscheinlich gehen, da auf dem Controller allerdings 
ein ziemlich großer Kalman-Filter laufen muss und noch einiges anderes 
muss ich DMA verwenden wo nur irgend möglich. Sieht jemand den Fehler?

Danke im Voraus,
Alex

von holger (Gast)


Lesenswert?

>Sieht jemand den Fehler?

#define HMI_ADC_DR_Address        ((uint32_t)HMI_ADC+0x10)

Noch mal im Datenblatt nachsehen!

von Alex K. (shadow851)


Lesenswert?

Super, danke für den Hinweis. Da war schonmal ein Fehler drin. 0x4C 
sollte stimmen, funktioniert aber immer noch nicht.
Sieht noch jemand etwas?

von holger (Gast)


Lesenswert?

>funktioniert aber immer noch nicht.

Was funktioniert nicht?
Ich wäre da ganz vorsichtig per DMA Daten in eine
so ungünstig aufgebaute Struktur zu übertragen.
Stichworte Alignment und Padding.
Und lass dir mal sizeof(SENSORS_t); ausgeben.
Das wird nicht 8 sein;)

von Alex K. (shadow851)


Lesenswert?

So, Start- und Stopmarkierung auf uint16_t aufgeblasen und jetzt 
funktioniert's (auch im scanmode).
Das Seltsame: sollte die DMA nicht trotz misalignment Daten kopieren, 
nur um 1 Byte verschoben?

von holger (Gast)


Lesenswert?

>So, Start- und Stopmarkierung auf uint16_t aufgeblasen und jetzt
>funktioniert's (auch im scanmode).
>Das Seltsame: sollte die DMA nicht trotz misalignment Daten kopieren,
>nur um 1 Byte verschoben?

Dann hast du wohl ein pack-struct in den Compileroptionen?
In dem Fall wolltest du Halfwords auf ungerade Adressen schreiben.
Und das geht laut Datenblatt nicht mit dem DMA.

von Alex K. (shadow851)


Lesenswert?

Nicht das ich wüsste. Für's makefile benutze ich das Eclipse GNU ARM 
plugin und darin sind alle pack-structures deaktiviert.
Hast du sonst noch eine Idee?

Danke im Übrigen für den Tipp, jetzt funktionierts wenigstens ;)

von holger (Gast)


Lesenswert?

>Nicht das ich wüsste. Für's makefile benutze ich das Eclipse GNU ARM
>plugin und darin sind alle pack-structures deaktiviert.

Hmm. Dann hätte das gehen müssen.
Oder du warst nicht darauf vorbereitet das:

typedef struct {
  uint8_t    start;

hier ein Padding Byte eingefügt wird.

  uint16_t  gier;
  uint16_t  throttle;


>Hast du sonst noch eine Idee?

Das alte Programm das nicht funktioniert noch mal hernehmen
und dann mal im Map File nachsehen was da los ist.
An welcher Adresse liegt die Struktur und wie groß ist sie.

von Alex K. (shadow851)


Lesenswert?

Es sind zwei paddingbytes vorhanden, die Addresse sieht gut aus.
Wie gesagt, das die Daten misaligned sind war zu erwarten, aber das die 
DMA erst gar keine Daten schreibt kann ich nicht nachvollziehen.
Bzw.: da ich nie mit SENSOR_States+x sondern mit SENSOR_states.stelle 
arbeite, sollte der Compiler nicht automatisch das paddingbyte bei der 
Addressberechnung berücksichtigen?

von Simon K. (simon) Benutzerseite


Lesenswert?

"Gier" heißt übrigens "Yaw" in Englisch.

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.