STM32F4 ADC DMA Multichannel

OP #4807742
Lesenswert?

Hi,

Ich versuche den ADC1 auf einem STM32F4 mit 2 Channels zu verwenden. Das 
Problem ist, dass aus irgend einem Grund der DMA Interrupt nur einmal 
aufgerufen wird und dann nie mehr. Der ADC sollte eigentlich durch den 
Timer immer wieder neu getriggert werden. Wenn ich zwei verschiedene 
ADC's verwende dann geht es, nur bei einem ADC mit mehreren Channels 
nicht. Hier mein Code:
1
/**
2
  ******************************************************************************
3
  * @file    main.c
4
  * @author  Ac6
5
  * @version V1.0
6
  * @date    01-December-2013
7
  * @brief   Default main function.
8
  ******************************************************************************
9
*/
10

11

12
#include "stm32f4xx.h"
13
#include "stm32f4_discovery.h"
14

15
#define VOLTAGE_REF 3.3 //Datasheet
16

17
void RCC_Configuration(void)
18
{
19
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
20
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
21
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
22
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
23
}
24

25
/***************************************************************************/
26
void GPIO_Configuration(void)
27
{
28
  GPIO_InitTypeDef GPIO_InitStructure;
29
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
30
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
31
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
32
  GPIO_Init(GPIOC, &GPIO_InitStructure);
33
}
34
/***************************************************************************/
35
void ADC_Configuration(void)
36
{
37
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
38
  ADC_InitTypeDef ADC_InitStructure;
39
  /* ADC Common Init */
40
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
41
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
42
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;
43
  // 2 half-words one by one, 1 then 2
44
  ADC_CommonInitStructure.ADC_TwoSamplingDelay =  ADC_TwoSamplingDelay_5Cycles;
45
  ADC_CommonInit(&ADC_CommonInitStructure);
46
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
47
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
48
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // Conversions Triggered
49
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
50
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
51
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
52
  ADC_InitStructure.ADC_NbrOfConversion = 2;
53
  ADC_Init(ADC1, &ADC_InitStructure);
54
  //ADC_Init(ADC2, &ADC_InitStructure); // Mirror on ADC2
55
  /* ADC1 regular channel 10 configuration */
56

57
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1,ADC_SampleTime_15Cycles);
58
  ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 2,ADC_SampleTime_15Cycles);
59

60
  //ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
61
  ADC_DMACmd(ADC1, ENABLE);
62

63

64
  /* Enable ADC1 */
65
  ADC_Cmd(ADC1, ENABLE);
66

67
}
68

69
/**************************************************************************/
70
# define BUFFERSIZE 900 // I+Q 200KHz x2 HT/TC at 1KHz
71

72
__IO uint16_t ADCDualConvertedValues[BUFFERSIZE]; // Filled as pairs ADC1, ADC2
73

74
static void DMA_Configuration(void)
75
{
76
  DMA_InitTypeDef DMA_InitStructure;
77

78
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;
79
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCDualConvertedValues;
80
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x40012308;
81
  // CDR_ADDRESS; Packed ADC1, ADC2
82
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
83
  DMA_InitStructure.DMA_BufferSize = BUFFERSIZE; // Count of 16-bit words
84
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
85
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
86
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
87
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
88
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
89
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
90
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
91
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
92
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
93
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
94
  DMA_Init(DMA2_Stream0, &DMA_InitStructure);
95
  /* Enable DMA Stream Half / Transfer Complete interrupt */
96
  DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_HT, ENABLE);
97
  /* DMA2_Stream0 enable */
98
  DMA_Cmd(DMA2_Stream0, ENABLE);
99
}
100
void TIM2_Configuration(void)
101
{
102
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
103
  /* Time base configuration */
104
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
105
  TIM_TimeBaseStructure.TIM_Period =(84000000 / 200000) - 1;
106
   // 200 KHz, from 84 MHz TIM2CLK (ie APB1 = HCLK/4, TIM2CLK = HCLK/2)
107
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
108
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
109
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
110
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
111
  /* TIM2 TRGO selection */
112
  TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
113
  // ADC_ExternalTrigConv_T2_TRGO
114
 /* TIM2 enable counter */
115
  TIM_Cmd(TIM2, ENABLE);
116
}
117

118
/****************************************************************************/
119
void NVIC_Configuration(void)
120
{
121
 NVIC_InitTypeDef NVIC_InitStructure;
122
           /* Enable the DMA Stream IRQ Channel */
123
  NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
124
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
125
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
126
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
127
  NVIC_Init(&NVIC_InitStructure);
128
}
129

130
/***********************************************************************/
131
void DMA2_Stream0_IRQHandler(void)//Called at 1 KHz for 200 KHz sample rate
132
{
133
 /* Test on DMA Stream Half Transfer interrupt */
134
 if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_HTIF0))
135
 {
136
  /* Clear DMA Stream Half Transfer interrupt pending bit */
137
  DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_HTIF0);
138

139
 }
140

141
 /* Test on DMA Stream Transfer Complete interrupt */
142
 if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))
143
 {
144
  /* Clear DMA Stream Transfer Complete interrupt pending bit */
145
  DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
146

147
  // Add code here to process second half of buffer (pong)
148
  }
149
 }
150

151
 /*****************************************************************************/
152

153
 int main(void)
154
 {
155
  RCC_Configuration();
156
  GPIO_Configuration();
157
  NVIC_Configuration();
158
  TIM2_Configuration();
159
  DMA_Configuration();
160
  ADC_Configuration();
161

162
  /* Start ADC1 Software Conversion */
163
  ADC_SoftwareStartConv(ADC1);
164

165
  while(1) {// Don't want to exit
166
    float x=ADCDualConvertedValues[0];
167
    float y=ADCDualConvertedValues[1];
168

169
  }
170
 /***************************************************************************/
171
}
(Firma: matzetronics) #4807820
Lesenswert?

Sebastian T. schrieb:
> DMA_InitStructure.DMA_Memory0BaseAddr =
> (uint32_t)&ADCDualConvertedValues;
>   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x40012308;

Gib hier mal lieber die richtigen Adressen vor:
1
  DMA_InitStructure.DMA_PeripheralBaseAddr =  (uint32_t)&(ADC1->DR); // source address
2
  DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&ADCDualConvertedValues[0];      //  result memory location
Dann ist es sinnvoll, zu warten, bis die DMA soweit ist, bevor man den 
ADC startet:
1
  DMA_Cmd(DMA2_Stream0,ENABLE);
2
 // wait for the DMA Stream to be ready
3
  while(DMA_GetCmdStatus(DMA2_Stream0)==DISABLE){};
4
 // now run the ADC
5
  ADC_DMACmd(ADC1, ENABLE);
6
  ADC_Cmd(ADC1, ENABLE);
7
  ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
8
  ADC_ContinuousModeCmd(ADC1,ENABLE);
9
  ADC_SoftwareStartConv(ADC1);
Ich schreibe die ADC Ergebnisse statt in ein Array in ein Struct, aber 
das sollte nicht wirklich einen Unterschied machen.

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