Forum: Mikrocontroller und Digitale Elektronik Abtastrate ADC STM32 - DMA nur jeden 2ten Wert


von Waddi (Gast)


Lesenswert?

Moin,

ich arbeite mit dem STM32F103 und wandle analoge Werte im Simultanen 
Modus mit den ADC Wandlern des Controllers, die gewandelten Werte werden 
mittels DMA in ein großes Array geschoben und von dort aus über den USB 
an einen PC gesendet.

Wenn ich die Abtastrate des ADC einstellen möchte, mache ich das über 
die Prescaler und die SampleTime. Für die ADC Clock komme ich auf 12MHz 
und wenn ich den DMA benutze berechne ich meine Abtastrate mit folgender 
Formel:

Ta = (12,5 + SampleTime) / 12MHz.

Da kommen dann nur krumme Werte für die Abtastfrequenz bei raus, außer 
bei der Einstellung 7,5Cycles. Da erhalte ich 600kHz, diese 
Abtastfrequenz ist allerdings zu hoch für eine Mehrkanalabtastung mit 
nachfolgender Übertragung per USB und darum möchte ich diese Abtastrate 
weiter teilen, zum Bsp. auf 300kHz,200kHz oder 150kHz. Dafür wollte ich 
einen eigenen Teiler verwenden.

Für den DMA habe ich automatische Inkrementierung des Memory Zeigers 
aktiviert und der wird bei jeder DMA - Übertragung inkrementiert, d.h. 
600k mal in der Sekunde.

Hat jemand eine Idee wie ich die Inkrementierung beeinflussen kann, 
sodass nur noch jeder zweite, dritte oder vierte Wert übertragen wird?

Danke im Voraus.
Gruß Waddi

von Brutus (Gast)


Lesenswert?

Lass doch per DMA das Ergebis in den Speicher übertragen und mach die 
Übertragung per USB von da aus mit der gewünschten Abtastrate.

von Gebhard R. (Firma: Raich Gerätebau & Entwicklung) (geb)


Lesenswert?

Wieso nimmst du keinen Timer für die Abtastrate? TIM4 wäre z.B. möglich.

Grüsse

von Waddi (Gast)


Lesenswert?

Mit der Timer - Triggerung habe ich mich noch nicht auseinandergesetzt. 
Hast du da Erfahrung mit? Sind damit so hohe Abtastraten denn möglich?

Wäre nett wenn du mir ein Beispiel nennen könntest, bzw. Beispielcode. 
Danke

Gruß Johannes

von holger (Gast)


Lesenswert?

>Hat jemand eine Idee wie ich die Inkrementierung beeinflussen kann,
>sodass nur noch jeder zweite, dritte oder vierte Wert übertragen wird?

Du hast DMA nicht verstanden. Das übertragt dir nur Blöcke.
Aber nicht jedes zweite, dritte, vierte Byte.

von Heinzi (Gast)


Lesenswert?

holger schrieb:
> Du hast DMA nicht verstanden. Das übertragt dir nur Blöcke.
> Aber nicht jedes zweite, dritte, vierte Byte.

Du auch nicht. So etwas gibt es, aber nicht bei dieser CPU.


c.u.

von Waddi (Gast)


Lesenswert?

Danke Holger & Heinzi aber auf solche Antworten kann ich echt 
verzichten!!!

Also ich ich weiß wie der DMA funktioniert! Meine Frage war ob ich die 
Inkrementierung beeinflussen kann.

von holger (Gast)


Lesenswert?

>Also ich ich weiß wie der DMA funktioniert! Meine Frage war ob ich die
>Inkrementierung beeinflussen kann.

Ja, klar du kannst auf 8Bit, 16Bit und 32Bit umschalten.
Aber ich glaube das bringt dich nicht weiter.

von Waddi (Gast)


Lesenswert?

Danke Holger! Das habe ich auch schon durchgespielt, aber ohne Lösung.

Also ich dachte irgendiwe daran, dass ich den MemoryZeiger beeinflussen 
kann. Über das CMDTR Register, aber das ist nicht der Zeiger sondern nur 
die Anzahl an verbleibenden Bytes.

von Gebhard R. (Firma: Raich Gerätebau & Entwicklung) (geb)


Lesenswert?

Ich versteh dein Problem nicht! Wenn du nur jeden 2.Wert brauchst,dann 
brauchts du ja auch nur mit dieser Frequenz zu sampeln. Außer du willst 
zur Auflösungsverbesserung mehrere Werte mitteln.

Die Ansteuerung des ADC über TIM4 geht sinngemäß so:

/* TIM4 configuration 
------------------------------------------------------*/
  /* Time Base configuration */
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_Period = 3051;
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
  /* TIM4 channel4 configuration in PWM mode */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 0x3F;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OC4Init(TIM4, &TIM_OCInitStructure);


ADC:

ADC_DeInit( ADC1);
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  //ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 12;
  ADC_Init(ADC1, &ADC_InitStructure);



void start_ADC1(void)
{
ADC_ExternalTrigConvCmd(ADC1, ENABLE);

TIM_CtrlPWMOutputs(TIM4, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);
 /* Enable DMA1 Channel1 Transfer Complete & Half interrupt */
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
DMA_ITConfig(DMA1_Channel1,DMA_IT_HT, ENABLE);
TIM_Cmd(TIM4, ENABLE);
DevStatus.adc1_run=1;
}

Grüsse

von Waddi (Gast)


Lesenswert?

Dankeschön, das werde ich gleich mal ausprobieren.

Also das oben Beschriebene wollte ich machen, weil wir uns über die 
gesamte Zeit der Entwicklung auf die SampleTime Einstellungen 
konzentriert haben und uns die krummen Abtastraten erstmal egal waren, 
nun da alles soweit funktioniert wollten wir auch gerade Abtastraten 
erreichen und da kam uns die Idee den ADC mit 600kHz abtasten zu lassen 
und nur jeden zweiten Wert zu nehmen, sodass wir effektiv mit 300kHz 
abtasten.

Aber diese Sache mit dem nur jeden zweiten Wert nehmen, dass klappt 
nicht wie ich mir das ausgedacht hatte. Schade.

Da ich im letzten Monat meiner BA bin, wollte ich mich nun eigentlich 
nicht mehr mit den Timern beschäftigen, aber das wird mein 
Entwicklerherz wohl nicht zulassen und darum werde ich heute Nacht mal 
eine Timer - Time einlegen.

Gruß

von branadic (Gast)


Lesenswert?

Der Thread ist zwar schon eine Weile in der Versenkung, allerdings 
beschäftige ich mich auch gerade mit der Thematik. Bist du zum 
gewünschten Ziel gelangt und falls ja, wie hast du es nun final 
umgesetzt?

Ich habe eine ähnliche Aufgabe vor mir:
- die Umsetzung soll über einen Taster ausgelöst werden

- die Abtastrate soll 200kHz betragen

- ein Signal soll über einen einzelnen ADC 100ms lang aufgezeichnet 
werden
--> 20.000 Messwerte à 12bit resp. 16bit

- die gesampelten Daten sollen im SRAM (ggf. Erweiterung des SRAM über 
FSMC) hinterlegt und weiterverarbeitet und das Ergebnis der Analyse auf 
einem GLCD (per FSMC angebunden) dargestellt werden (Histogramm, 
MinWert, MaxWert, Vpp etc.)

- bzw. die gesampelten Daten aus dem SRAM sollen zum PC hin übertragen 
und abgespeichert werden, um dort ausgewertet werden zu können

Als Plattform habe ich den STM32F103 (HY-Mini) vor mir zu liegen.


branadic

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.