Forum: Mikrocontroller und Digitale Elektronik STM32F4 DMA Request und IRQ Handler


von Aljo E. (alrue)


Lesenswert?

Hallo,
ich möchte den ADC3 mit dem DMA2_Stream1_Channel2 benutzen. Der ADC wird 
vom TIM3 getriggert. Sobald der Transfer in den DMA komplett ist, soll 
der DMA2_Stream1_IRQHandler aufgerufen werden. Dort möchte ich prüfen ob 
das Transer complete flag gesetzt wird.

Es tritt nun der Fall auf, dass ich sofort nach Programmbeginn in den 
DMA2_Stream1_IRQHandler gelange und dort im Prinzip nicht mehr 
rauskomme. Ich habe zum Testzweck eine LED getoggelt, jedes mal wenn die 
der IRQHandler aufgerufen wird und habe festgestellt, dass der mit 781 
kHz aufgerufen wird. Der Timer und die ADC Clock haben keinerlei 
Einfluss auf diesen absurd häufigen andlerzugriff. Eigentlich sollte 
doch alle paar Sekunden (je nach Einstellung des Timers) der ADC 
getriggert werden, die Wert vom ADC werden in den DMA geschrieben und 
dann komme ich in den Handler und sehe, dass das TF Flag gesetzt ist und 
mache dort meine Sachen. Allerdings ist auch nicht das TF Flag gesetzt 
und ich lande trotzdem im Handler.

Ich bin sehr verwirrt und würde mich über ein wenig Aufklärung freuen!

1
#define SCANBUFFERSIZE 1024
2
__IO uint16_t ADCScanConvVal[SCANBUFFERSIZE];
3
__IO uint8_t DMA2_Stream1_TC_Flg;
4
5
void RCC_Configuration(void)
6
{
7
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
8
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
9
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
10
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
11
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
12
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
13
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
14
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
15
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
16
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
17
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
18
}
19
20
void ADCscan_Configuration(void) // DMA2_Stream1_Channel2 für ADC3
21
{
22
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
23
  ADC_InitTypeDef ADC_InitStructure;
24
25
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
26
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
27
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
28
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
29
  ADC_CommonInit(&ADC_CommonInitStructure);
30
31
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
32
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
33
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
34
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
35
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;
36
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
37
  ADC_InitStructure.ADC_NbrOfConversion = 1;
38
  ADC_Init(ADC3, &ADC_InitStructure);
39
40
  ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_15Cycles); // PC0
41
  //ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 2, ADC_SampleTime_15Cycles); // PC1
42
  //ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 3, ADC_SampleTime_15Cycles); // PC2
43
  //ADC_RegularChannelConfig(ADC3, ADC_Channel_13, 4, ADC_SampleTime_15Cycles); // PC3
44
45
  ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);
46
  ADC_DMACmd(ADC3, ENABLE);
47
  ADC_Cmd(ADC3, ENABLE);
48
}
49
50
static void DMA2_Stream1_Configuration(void)
51
{
52
  DMA_InitTypeDef DMA_InitStructure;
53
54
  DMA_InitStructure.DMA_Channel = DMA_Channel_2;
55
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCScanConvVal;
56
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) 0x4001224C;//&ADC3->DR //ADC_CCR_ADDRESS
57
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
58
  DMA_InitStructure.DMA_BufferSize = SCANBUFFERSIZE;
59
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
60
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
61
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
62
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
63
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
64
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
65
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
66
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
67
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
68
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
69
  DMA_Init(DMA2_Stream1, &DMA_InitStructure);
70
71
  DMA_ITConfig(DMA2_Stream1, DMA_IT_TC, ENABLE);
72
73
  DMA_Cmd(DMA2_Stream1, ENABLE);
74
}
75
76
void TIM3_Configuration(void)
77
{
78
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
79
80
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
81
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV4;
82
  TIM_TimeBaseStructure.TIM_Period = 840;
83
  TIM_TimeBaseStructure.TIM_Prescaler = 50000;
84
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
85
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
86
87
  TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
88
89
  TIM_Cmd(TIM3, ENABLE);
90
}
91
92
void NVIC_Configuration(void)
93
{
94
  NVIC_InitTypeDef NVIC_InitStructure2;
95
96
  NVIC_InitStructure2.NVIC_IRQChannel = DMA2_Stream1_IRQn;
97
  NVIC_InitStructure2.NVIC_IRQChannelPreemptionPriority = 0;
98
  NVIC_InitStructure2.NVIC_IRQChannelSubPriority = 0;
99
  NVIC_InitStructure2.NVIC_IRQChannelCmd = ENABLE;
100
  NVIC_Init(&NVIC_InitStructure2);
101
}
102
103
void DMA2_Stream1_IRQHandler(void)
104
{
105
  GPIO_ToggleBits(GPIOA, GPIO_Pin_5);
106
  if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF0) || DMA_GetITStatus(DMA2_Stream1, DMA_IT_HTIF0))
107
  {
108
    DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF0);
109
    DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_HTIF0);
110
111
    //GPIO_ToggleBits(GPIOA, GPIO_Pin_5);
112
113
    DMA2_Stream1_TC_Flg = 1;
114
115
    ADC_Cmd(ADC3, DISABLE);
116
  }
117
}
118
119
int main(void)
120
{
121
    clock_Configuration();
122
    SystemCoreClockUpdate();
123
124
  RCC_Configuration();
125
  GPIO_Configuration();
126
  NVIC_Configuration();
127
  TIM3_Configuration();
128
  DMA2_Stream1_Configuration();
129
  ADCscan_Configuration();
130
  USART_Configuration();
131
  SPI_Configuration();
132
133
  ADC_SoftwareStartConv(ADC3);
134
135
  while(1)
136
  {
137
138
    if(DMA2_Stream1_TC_Flg == 1)
139
    {
140
      copyData();
141
      conversionRestart();
142
      sendData();
143
    }
144
145
  }
146
}

von Nico W. (nico_w)


Lesenswert?

Ich arbeite zwar direkt mit den Registern, aber ich hatte am Anfang auch 
ganz schön zu kämpfen.

Im DMA-Handler checke ich den TCIF, clear das Flag und deaktiviere den 
Continious Mode vom ADC.

Im Timer (bei mir zumindest sowas ähnliches), starte ich dann den ADC 
neu und aktiviere wieder den Cont-Mode vom ADC. Den kompletten ADC 
braucht man ja nicht deaktiveren.

Musst sonst mal gucken was der ADC_cmd(xx, DISABLE) alles noch macht.

Also ganz grob als ADC-Init:
CR1_SCAN
CR2_DMA
CR2_DDS
CR2_CONT
CR2_ADON
CR2_SWSTART

Im DMA-Init:
CR_TCIE
CR_EN

Im DMA-Handler
if TCIF
DMA->HIFCR clear
ADC->CR2 &= ~CR2_CONT

Im Timer:
ADC->CR2 |= CR2_SWSTART | CR2_CONT

von Aljo E. (alrue)


Lesenswert?

Also das Problem scheint bei mir der DMA2_Stream 1 zu sein. Ich habe 
eine Version wie ich sie brauche zum laufen gebracht, allerdings mit dem 
DMA2_Stream0_Channel2 (ist dem ADC3 zugeordnet). Hat super funktioniert. 
Anschließend habe ich einfach auf den DMA2_Stream1_Channel2, welcher 
laut AN4031 ebenfalls ADC3 zugeordnet ist. Dann funktioniert der Code 
aber nicht mehr und der Prozessor kommt nicht in meinen 
DMA2_Stream1_IRQHandler.

Was könnte das Problem sein? Muss ich einen anderen ADC channel 
verwenden? Ich hab keine Ahnung.

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.