STM32F1 Discoveryboard - Adc

Gast #3022311
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 ?
(Firma: matzetronics) #3022322
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.
Gast #3022329
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 ?
(Firma: matzetronics) #3022354
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.
Gast #3022360
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.
(Firma: matzetronics) #3022401
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.
Gast #3022443
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:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren