Forum: Mikrocontroller und Digitale Elektronik EFM32 ADC und USB


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 Robert S. (gips1gott)


Bewertung
0 lesenswert
nicht lesenswert
Moin Leute,

ich möchte ADC Werte über USB ausgeben. Mein aktuelles Programm nimmt 
ADC-Werte auf und gibt diese auch über USB aus. Das Problem ist, dass 
die ADC-Werte nicht stimmen. Das Programm ohne Timer1 und USB gibt 
allerdings richtige ADC-Werte aus. Unten sind die wichtigsten Zeilen 
meines Programmes.

Init:
1
static void EFM32_Init(void)
2
{
3
4
  CDC_Init();
5
  SegmentLCD_Init(false);
6
7
  CMU_OscillatorEnable(cmuOsc_HFXO, true, false);
8
  CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO );
9
10
  CMU_ClockEnable(cmuClock_HFPER, true);
11
  CMU_ClockEnable(cmuClock_ADC0, true);
12
  CMU_ClockEnable(cmuClock_TIMER1, true);
13
14
  USBD_Init(&usbInitStruct);
15
16
  TIMER_Init(TIMER1, &timerInit);
17
18
  TIMER_IntEnable(TIMER1, TIMER_IF_OF);
19
20
  NVIC_EnableIRQ(TIMER1_IRQn);
21
22
  TIMER_TopSet(TIMER1, TOP);
23
24
  TIMER1->CNT=0;
25
26
}

sowie:
1
static void ADCConfig(void)
2
{
3
  ADC_Init_TypeDef       init       = ADC_INIT_DEFAULT;
4
  ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT;
5
6
  init.timebase = ADC_TimebaseCalc(0);
7
8
  init.prescale = ADC_PrescaleCalc(7000000, 0);
9
10
  ADC_Init(ADC0, &init);
11
12
  singleInit.reference  = adcRef5VDIFF;
13
  singleInit.input      = adcSingleInputCh0;/
14
  singleInit.resolution = adcRes12Bit;
15
16
  init.warmUpMode     = adcWarmupKeepScanRefWarm;
17
18
  singleInit.acqTime = adcAcqTime32;
19
20
  ADC_InitSingle(ADC0, &singleInit);
21
22
}

sowie:
1
void TIMER1_IRQHandler(void)
2
{
3
4
  TIMER_IntClear(TIMER1, TIMER_IF_OF);
5
  
6
  ADC_Start(ADC0, adcStartSingle);
7
              
8
  while (ADC0->STATUS & ADC_STATUS_SINGLEACT);
9
10
  ergebnis = ADC_DataSingleGet(ADC0);
11
}

von Nop (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jan S. schrieb:
> while (ADC0->STATUS & ADC_STATUS_SINGLEACT);

In Interrupts warten ist nie eine gute Idee. Wieso liest Du nicht 
einfach den ADC-Wert ohne Warteschleife aus und stößt direkt danach die 
nächste Messung an? Diese wird dann im nächsten Timer-Interrupt 
ausgelesen. Solange die Timerfrequenz geringer als die Wandlungszeit 
ist, geht das (wenn nicht, geht das alles eh nicht).

Die Werte sind dann zwar um eine Timerperiode veraltet, aber wenn Du das 
dann eh paketiert über USB schickst, wird das wohl keine so große Rolle 
spielen.

von Jim M. (turboj)


Bewertung
0 lesenswert
nicht lesenswert
Ich sehen in Deinem Code oben keinen Aufruf für ADCConfig(). Das muss an 
der korrekten Stelle stehen.

Ich sehe aber noch mehr:
1
  CDC_Init();
2
  SegmentLCD_Init(false);
3
4
  CMU_OscillatorEnable(cmuOsc_HFXO, true, false);
5
  CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO );

CDC_Init würde ich immer erst nach den Oszillatoren machen, sonst 
stimmt eventuell die Baudrate nicht. Dito SegmentLCD_init().

USB verwendet einen der Timer, aber IIRC nicht Timer1.

Da Du den HFXO direkt verwenden willst, besser:
1
CMU_OscillatorEnable(cmuOsc_HFXO, true, true);

Die Änderung von init.warmUpMode hat keinen Effekt, da sie nach 
ADC_Init() erfolgt.

Damit hast Du das Problem mit dem überlaufenden Referenzzähler im Warmup 
bei 48 Mhz (siehe Manual/Errata), was die schlechten ADC Werte erklären 
könnte.

von Robert S. (gips1gott)


Bewertung
0 lesenswert
nicht lesenswert
Moin Leute,

ich habe die ADC Abfrage nun außerhalb des Interrupts gelegt sowie die 
Initialisierungsschritte wie Jim Meba beschrieben hat durchgeführt. 
Vielen Dank erstmal dafür! Sicherlich habe ich auch hier Fehler gemacht. 
Die ADC-Config ist bei mir auch in der main(). Nach meinen 
Verbesserungen hat das Programm leider immer noch nicht wünschenswert 
gearbeitet. Nach einigen Messungen an den I/O-Pins fiel mir auf, dass 
ich auf CH0 3V im ADC Diff Modus mit CH0 und CH1 anliegen habe. Daher 
habe ich meinen ADC auf CH6 und CH7 gelegt und siehe da - es 
funktioniert. Vielen Dank an euch!

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.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

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