Forum: Mikrocontroller und Digitale Elektronik STM32F1 Discoveryboard - Adc


von EmbeddedUser (Gast)


Lesenswert?

Hi,

ich möchte auf dem STM32F1 Discoveryboard den AD Wandler (Pin PC4) 
benutzen. Leider gelingt es mir bisher nicht den Ad Wandler zum laufen 
zu bringen.
1
#define ADC1_DR_Address    ((uint32_t)0x4001244C)
2
void ADC_Configuration(void);
3
__IO uint16_t ADCConvertedValue;
4
5
int main(void)
6
{
7
8
 while(1)
9
 {
10
 }
11
}
12
13
void ADC_Configuration(void)
14
{
15
  ADC_InitTypeDef ADC_InitStructure;
16
  DMA_InitTypeDef DMA_InitStructure;
17
  GPIO_InitTypeDef GPIO_InitStructure;
18
19
  /* Configure PC.4 (ADC Channel14) as analog input -------------------------*/
20
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
21
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
22
  GPIO_Init(GPIOC, &GPIO_InitStructure);
23
24
  /* DMA1 channel1 configuration ----------------------------------------------*/
25
  DMA_DeInit(DMA1_Channel1);
26
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
27
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;
28
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
29
  DMA_InitStructure.DMA_BufferSize = 1;
30
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
31
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
32
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
33
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
34
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
35
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
36
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
37
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
38
39
  /* Enable DMA1 channel1 */
40
  DMA_Cmd(DMA1_Channel1, ENABLE);
41
42
  /* ADC1 configuration ------------------------------------------------------*/
43
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
44
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
45
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
46
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
47
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
48
  ADC_InitStructure.ADC_NbrOfChannel = 1;
49
  ADC_Init(ADC1, &ADC_InitStructure);
50
51
  /* ADC1 regular channel14 configuration */
52
  ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_55Cycles5);
53
54
  /* Enable ADC1 DMA */
55
  ADC_DMACmd(ADC1, ENABLE);
56
57
  /* Enable ADC1 */
58
  ADC_Cmd(ADC1, ENABLE);
59
60
  /* Enable ADC1 reset calibaration register */
61
  ADC_ResetCalibration(ADC1);
62
  /* Check the end of ADC1 reset calibration register */
63
  while(ADC_GetResetCalibrationStatus(ADC1));
64
65
  /* Start ADC1 calibaration */
66
  ADC_StartCalibration(ADC1);
67
  /* Check the end of ADC1 calibration */
68
  while(ADC_GetCalibrationStatus(ADC1));
69
70
  /* Start ADC1 Software Conversion */
71
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
72
}

Was mache ich da möglicherweise falsch ?

von EmbeddedUser (Gast)


Lesenswert?

Vor der while(1) Schleife rufe ich natürlich die Funktion 
"ADC_Configuration" auf.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

EmbeddedUser schrieb:
> DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;

Diese Adresse sehe ich nirgends. Ist das eine gültige?
Ich zeig dir mal meine Init, die ist aber für mehr Kanäle:
1
// aus setup.h
2
/* ADC definitions */
3
#define SPAREINPUT_ADC              ADC1
4
#define SPAREINPUT_CHANNEL          ADC_Channel_0
5
#define SPAREINPUT_GPIO_PORT        GPIOA
6
#define SPAREINPUT_GPIO_PIN         GPIO_Pin_0
7
8
/* Speed Input */
9
#define SPEEDINPUT_ADC              ADC1
10
#define SPEEDINPUT_CHANNEL          ADC_Channel_1
11
#define SPEEDINPUT_GPIO_PORT        GPIOA
12
#define SPEEDINPUT_GPIO_PIN         GPIO_Pin_1
13
14
/* Only for 1 shunt resistor case */
15
#define PHASE_CURRENTS_ADC              ADC1
16
#define PHASE_CURRENTS_CHANNEL          ADC_Channel_2
17
#define PHASE_CURRENTS_GPIO_PORT        GPIOA
18
#define PHASE_CURRENTS_GPIO_PIN         GPIO_Pin_2
19
20
/** Bus and temperature readings **/
21
#define TEMP_ADC                        ADC1
22
#define TEMP_CHANNEL                    ADC_Channel_3
23
#define TEMP_GPIO_PORT                  GPIOA
24
#define TEMP_GPIO_PIN                   GPIO_Pin_3
25
26
typedef struct ADCValues
27
{
28
  uint16_t spare1;
29
  uint16_t speedInput;
30
  uint16_t current;
31
  uint16_t temp;
32
  uint16_t spare2;
33
} ADCValues_t;
34
// aus main.c
35
volatile ADCValues_t ADCRead;
36
/* Init the ADC converter to free-run with 4 channels
37
 *
38
 */
39
void ADCInit(void) {
40
ADC_InitTypeDef       ADC_InitStructure;
41
DMA_InitTypeDef    DMA_InitStructure;
42
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
43
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
44
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
45
/* DMA1 channel1 configuration ----------------------------------------------*/
46
  DMA_DeInit(DMA1_Channel1);    // Clear everything we had 
47
  DMA_InitStructure.DMA_PeripheralBaseAddr =  (uint32_t)&(ADC1->DR); // Source is the ADC data register
48
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADCRead;      // Its the destination here
49
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;   // from Peripheral to RAM
50
  DMA_InitStructure.DMA_BufferSize = 4;    /// Note that we have 4 Channels
51
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  // Source stays same address
52
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;     // Destination will be incremented
53
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  // 16 bit results
54
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;   // yeah same size -> 16 bit
55
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  // Wrap around the destination address
56
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;   // why not? its the only DMA thingy in this program
57
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;   // we don't want RAM to RAM
58
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);   // Init the stuff finally 
59
  /* Enable DMA1 channel1 */
60
  DMA_Cmd(DMA1_Channel1, ENABLE);  // Run, but we wait for the ADC init
61
/* ADC1 configuration
62
 * 4 channel continuous
63
 */
64
ADC_DeInit(ADC1);   // again clear the whole ADC out
65
ADC_StructInit(&ADC_InitStructure);
66
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;    // no external triggers here
67
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
68
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
69
ADC_InitStructure.ADC_NbrOfChannel = 4;
70
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
71
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
72
/* Now do the setup */
73
ADC_DMACmd(ADC1, ENABLE);
74
ADC_Init(ADC1, &ADC_InitStructure);
75
/* Enable ADC1 */
76
ADC_RegularChannelConfig(ADC1,SPAREINPUT_CHANNEL,1,ADC_SampleTime_239Cycles5);
77
ADC_RegularChannelConfig(ADC1,SPEEDINPUT_CHANNEL,2,ADC_SampleTime_239Cycles5);
78
ADC_RegularChannelConfig(ADC1,PHASE_CURRENTS_CHANNEL,3,ADC_SampleTime_239Cycles5);
79
ADC_RegularChannelConfig(ADC1,TEMP_CHANNEL,4,ADC_SampleTime_239Cycles5);
80
ADC_Cmd(ADC1, ENABLE);
81
/* Enable ADC1 reset calibaration register */
82
ADC_ResetCalibration(ADC1);
83
/* Check the end of ADC1 reset calibration register */
84
while(ADC_GetResetCalibrationStatus(ADC1));
85
/* Start ADC1 calibaration */
86
ADC_StartCalibration(ADC1);
87
/* Check the end of ADC1 calibration */
88
while(ADC_GetCalibrationStatus(ADC1));
89
90
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
91
Delay(200);
92
}
Wie du siehst, lese ich 4 Kanäle ein, YMMV. Den ersten Kanal benutze ich 
allerdings nicht, weil mir da zu viele Störungen drauf sind.

von EmbeddedUser (Gast)


Lesenswert?

Danke für deine Unterstützung. Ich habe vergessen die Clock für den DMA 
zu aktivieren. Jetzt scheint der ADC zu funktionieren.

Allerdings eine Frage hätte ich noch. Ich möchte den Luftdrucksensor 
MPXA4100A an diesem ADC Eingang anschließen. Dieser Sensor benötigt +5 
Volt. Wenn ich nun den Sensor am ADC Eingang anschließe, dann geht doch 
der Spannungsrange nur von 0 Volt bis 3,3 Volt. Was müsste ich tun, 
damit ich diesen Sensor trotzdem mit diesem AD andler verwenden kann ?

von EmbeddedUser (Gast)


Angehängte Dateien:

Lesenswert?

Auszug aus dem Datenblatt.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

EmbeddedUser schrieb:
> Was müsste ich tun,
> damit ich diesen Sensor trotzdem mit diesem AD andler verwenden kann ?

Die klassische Lösung ist ein genauer Spannungsteiler. Dieser teilt z.B. 
genau durch 2, so das am Ausgang dann 0 - 2,5 Volt stehen, genau richtig 
für den ADC. Mit ein bisschen Rechnerei könntest du z.B. auch auf 3,3 
Volt skalieren.

von EmbeddedUser (Gast)


Lesenswert?

Ok danke. Ich habe nun mal die Spannung am Evaluationboard gemessen. Vs 
liegt nicht genau auf +5 V sondern auf 4,72 V. Dies bedeutet, der Sensor 
kann überhaupt keine +5 V maximal ausgeben. Für die Berechnung des 
Spannungsteilers muss somit mit 4,72 V gerechnet werden.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

EmbeddedUser schrieb:
> Für die Berechnung des
> Spannungsteilers muss somit mit 4,72 V gerechnet werden.

Am besten ist, wenn du ein 10-Gang Trimmpoti der etwas besseren Sorte 
nimmst. Damit kannst du den Spannungsteiler genau justieren. Wenn du die 
AREF dann aus der Betriebsspannung des Sensors herleitest, sollte das 
relativ genau werden.

EmbeddedUser schrieb:
> Für die Berechnung des
> Spannungsteilers muss somit mit 4,72 V gerechnet werden.

Lt. Freescale betreibst du damit den Sensor allerdings ausserhalb der 
ratiometrischen Specs.

von EmbeddedUser (Gast)


Lesenswert?

Was meinst du genau mit

>>Wenn du die AREF dann aus der Betriebsspannung des Sensors herleitest, >>sollte 
das relativ genau werden.

von EmbeddedUser (Gast)


Lesenswert?

Muss somit Vs schon genau auf +5 V liegen ?

von EmbeddedUser (Gast)


Lesenswert?

Den Ausgang vom Sensor habe ich nicht am ADC Eingang angeschlossen. Die 
gemessene Spannung beträgt Vout = 4,72 V. Eine Höhenkorrektur (ca. 115 
m) wurde noch nicht mit eingebracht.

Formel umgestallt nach P:

von EmbeddedUser (Gast)


Lesenswert?


Vout = 4.271 Volt
Vs   = 4.72 Volt

von Roland H. (batchman)


Lesenswert?

EmbeddedUser schrieb:
> Ich habe nun mal die Spannung am Evaluationboard gemessen. Vs
> liegt nicht genau auf +5 V sondern auf 4,72 V.

Das liegt vermutlich an der Schutzdiode D1 (Schottky) mit ca. 0,3V 
Spannungsabfall.

Ebenso liegt eine Schutzdiode D3 hinter dem Spannungsregler, welche 
ebenso Einfluss auf ADC hat.

Siehe auch Beitrag "STM32F4 Discovery + Spannungen"

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.