Forum: Mikrocontroller und Digitale Elektronik STM32 ADC sättigt zu früh


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,
ich versuche gerade den ADC eines STM32F103 in Betrieb zu nehmen. Dafür 
habe ich eine kleine Testroutine geschrieben (siehe unten) und ein Poti 
mit 0-2.4V an den ADC-Pin PC3 gehängt. Das Ganze wird auf einem Display 
ausgegeben.

Momentan habe ich das Problem, daß der Maximalwert 4095 schon bei einer 
Spannung von ca. 110mV angezeigt wird. Darunter scheint die Anzeige 
halbwegs proportional zu sein (das ist schwer, halbwegs feinfühlig so 
einen kleinen Bereich zu drehen).

Wie kann das passieren?

Viele Grüße
W.T.
1
/*
2
* adc_test.c
3
*
4
* Created: 18.02.2014
5
*  Author: Nicolas
6
*/
7
8
#include <stdio.h>
9
#include "../../ioMapping.h"
10
#include "../src_encoder/key.h"
11
#include "../src_avrcom/pgmspace.h"
12
#include "../src_avrcom/delay.h"
13
#include "../src_glcd/glcd_ks0108.h"
14
15
#ifdef STM32F10x
16
  #include "stm32f10x_adc.h"
17
  #include "stm32f10x_gpio.h"
18
  #include "stm32f10x_rcc.h"
19
#elif defined(STM32F4xx)
20
  #error "only for STM32F10x implemented yet"
21
#else
22
  #error "unknown MCU"
23
#endif
24
25
26
//#define POTI_UPDWN_GPIO  GPIOC
27
//#define POTI_UPDWN_Pin   GPIO_Pin_3
28
//#define POTI_UPDWM_ADCCH ADC_Channel_13
29
30
31
void adc_calib(ADC_TypeDef *ADCx) {
32
  ADC_Cmd(ADCx,ENABLE);
33
  ADC_ResetCalibration(ADCx);
34
  while(ADC_GetResetCalibrationStatus(ADCx));
35
  ADC_StartCalibration(ADCx);
36
  while(ADC_GetCalibrationStatus(ADCx));
37
  ADC_SoftwareStartConvCmd(ADCx,ENABLE);
38
}
39
40
41
42
/* Suchen von I2C-Devices und Darstellen auf LCD */
43
void adc_test(void) {
44
  ADC_InitTypeDef  ADC_InitStructure;
45
  GPIO_InitTypeDef GPIO_InitStructure;
46
  uint16_t value;
47
48
  // ADC-Takt max. 14MHz, hier 72MHz / 6 = 12MHz
49
  RCC_ADCCLKConfig(RCC_PCLK2_Div6);
50
51
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
52
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_ADC1,ENABLE);
53
54
  GPIO_InitStructure.GPIO_Pin = POTI_UPDWN_Pin;
55
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
56
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
57
  GPIO_Init(POTI_UPDWN_GPIO,&GPIO_InitStructure);
58
  
59
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
60
  ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;
61
  ADC_InitStructure.ADC_ExternalTrigConv   = ADC_ExternalTrigInjecConv_None;
62
  ADC_InitStructure.ADC_Mode               = ADC_Mode_Independent;
63
  ADC_InitStructure.ADC_NbrOfChannel       = 1;
64
  ADC_InitStructure.ADC_ScanConvMode       = DISABLE;
65
  ADC_Init(ADC1,&ADC_InitStructure);
66
67
  ADC_RegularChannelConfig(ADC1,POTI_UPDWM_ADCCH,1,ADC_SampleTime_1Cycles5);
68
69
  ADC_Cmd(ADC1,ENABLE);
70
71
  ADC_SoftwareStartConvCmd(ADC1,ENABLE);
72
73
  adc_calib(ADC1);
74
  
75
  printf_P(PSTR("\fADC Test Poti 1 \n\a"));
76
  
77
  // Kann als Dauerschleife angesehen werden
78
  while(!key_getstroke()) {
79
80
    value = ADC_GetConversionValue(ADC1);
81
    glcd_setpos(128);
82
    printf_P(PSTR("val=%6i\a"),value);
83
    delay_us(100);
84
  }
85
  printf_P(PSTR("\b\b\b\bdone.    \a"));
86
  
87
88
  return;
89
90
  error:
91
92
  printf_P(PSTR("\nError \a"));
93
  while(!key_getstroke());
94
} // end function
Erläuterung:
 - key_getstroke() liefert immer 0 zurück
 - printf_P(PSTR("...")); kann als printf("..."); angesehen werden
 - glcd_setpos( ) und delay_us(  ) machen das, was der Name suggeriert.

von Frank B. (f-baer)


Lesenswert?

Wie wäre es mit der Schaltung? Wenn der ADC in Sättigung geht, wirds 
wohl kein SW-Problem sein.
Dennoch könntest du die Sample-Zeit hochnehmen. Länger ist besser, weil 
genauer. Wenn du also kein ernstzunehmendes Zeitproblem hast, und 
deswegen im µs-Takt samplen möchtest, dann ist die Minimaleinstellung 
unsinnig.
Für deine Zwecke würde ich sogar eher die Maximaleinstellung wählen, 
reduzieren kann man später immernoch.

von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Die Schaltung ist kein Geheimnis. Ist ja nur ein STM32F103 und ein wenig 
Hühnerfutter (siehe Anhang, Versorgung auf Seite 2).

Der Tipp mit der Schaltung war goldrichtig. Der Pin VREF+ hatte etwas 
wenig Lötzinn auf dem Pad.

Jetzt geht der ADC proportiortional bis 2,4V, zeigt dort aber nur 2867 
an, als wäre die Referenz 3,3V und nicht 2,4V.

Muß ich noch irgendwo die Referenzspannung umstellen?

von Frank B. (f-baer)


Lesenswert?

Walter Tarpan schrieb:
> Jetzt geht der ADC proportiortional bis 2,4V, zeigt dort aber nur 2867
> an, als wäre die Referenz 3,3V und nicht 2,4V.

Weil dein VREF-Eingang an 3V3 liegt... Der Vorwiderstand ist keine 
Lösung, ein Spannungsteiler oder besser eine echte Referenz wäre da 
notwendig gewesen.

von Walter T. (nicolas)


Lesenswert?

Hm...es kann sein, daß ich die Application Notes AN2558 und AN2586 
falsch gelesen und vermischt habe. Muß ich mir die 
Referenzspannungssache nochmal genau ansehen.

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.