Forum: Mikrocontroller und Digitale Elektronik ADC EOC Interrupt


von blisson (Gast)


Lesenswert?

Hallo zusammen,

ich bin derzeit dabei, einen STM32F103ZGT6 auf einem STM3210E-Eval-Board 
mit der Toolchain von Raisonance Ride7 zu testen und will den im STM32 
integrierten ADC nutzen.
Ich habe ein wenig, aber nicht allzu viel Erfahrung in Sachen C und so 
gut wie keine Erfahrung mit dem STM32.

Mein Problem ist, dass mein Code vor dem gedachten EOC-Interrupt 
stehenbleibt. Genau genommen bleibt er vor dem EOC-Interrupt und vor dem 
ebenfalls getesteten Analog-Watchdog-Interrupt laut Online-Debugger in 
der Zusatz-Datei system_stm32f10x.c eine Zeile unter folgendem stehen:
1
#ifdef VECT_TAB_SRAM
2
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
3
#else
4
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
5
#endif

Deshalb gehe ich davon aus, dass er auf den Interrupt zwar reagiert, die 
zugehörige ISR jedoch nicht findet.
Kann mir irgendwer sagen, wo das Problem liegt? Danke im Voraus, hier 
mein Code:
1
#include "platform_config.h"
2
#include <stdio.h>
3
#include "stm32f10x.h"
4
#include "stm32f10x_adc.c"
5
#include "stm32_eval.h"
6
#include "string.h"
7
#include "stm3210e_eval_lcd.h" 
8
#include "stm32f10x_tim.c"
9
10
NVIC_InitTypeDef NVIC_InitStructure;
11
USART_InitTypeDef USART_InitStructure;
12
DMA_InitTypeDef DMA_InitStructure;
13
ADC_InitTypeDef ADC_InitStructure;
14
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
15
TIM_OCInitTypeDef  TIM_OCInitStructure;
16
17
void DMA_Configuration(void);
18
void USARTInit(void);
19
void send_string(char value[255]);
20
void RCC_Configuration(void);
21
void GPIO_Configuration(void);
22
void NVIC_Configuration(void);
23
void ADC1_Configuration(void);
24
void ADC2_Configuration(void);
25
void ADC1_Calibration(void);
26
void ADC2_Calibration(void);
27
void Timer_Configuration(void);
28
void LCDInit(void);
29
30
#ifdef __GNUC__
31
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
32
   set to 'Yes') calls __io_putchar() */
33
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
34
#else
35
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
36
#endif /* __GNUC__ */
37
38
int main(void)
39
{
40
  /* Variables ---------------------------------------------------------------*/
41
  char message[40];
42
43
  STM_EVAL_LEDInit(LED1);
44
45
  RCC_Configuration(); // System clocks configuration
46
  USARTInit(); // USART Initialization 
47
  Timer_Configuration(); // Timer configuration
48
  DMA_Configuration(); //DMA configuration
49
  NVIC_Configuration(); // NVIC configuration
50
  GPIO_Configuration(); // GPIO configuration
51
  ADC1_Configuration(); // ADC1 configuration
52
  ADC2_Configuration(); // ADC2 configuration
53
  ADC1_Calibration(); // ADC1 calibration
54
  ADC2_Calibration(); // ADC2_Calibration
55
56
  send_string("  \rMCU initialization complete.\n\rPlease press [s] to start conversion...\n\r");
57
  do
58
  {
59
  c=USART_ReceiveData(USART1);
60
  } while(c!='s');
61
62
  TIM_Cmd(TIM2, ENABLE); // TIM2 enable counter
63
64
  ADC_Cmd(ADC1, ENABLE); // Enable ADC1
65
  ADC_SoftwareStartConvCmd(ADC1, ENABLE); // Start ADC1 Conversion
66
  ADC_Cmd(ADC2, ENABLE); // Enable ADC2
67
  ADC_SoftwareStartConvCmd(ADC2, ENABLE); // Start ADC2 Conversion
68
}
69
70
PUTCHAR_PROTOTYPE
71
{
72
  USART_SendData(EVAL_COM1, (uint8_t) ch);
73
74
  while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TC) == RESET)
75
  {}
76
77
  return ch;
78
}
79
80
void USARTInit(void)
81
{
82
  USART_InitStructure.USART_BaudRate = 115200;
83
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
84
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
85
  USART_InitStructure.USART_Parity = USART_Parity_No;
86
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
87
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
88
89
  STM_EVAL_COMInit(COM1, &USART_InitStructure);
90
91
  USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
92
93
  USART_Cmd(USART1, ENABLE);
94
}
95
96
/**
97
  * @brief  Configures the different system clocks.
98
  * @param  None
99
  * @retval None
100
  */
101
void RCC_Configuration(void)
102
{
103
  /* HCLK = SYSCLK = 56 MHz */
104
  RCC_HCLKConfig(RCC_SYSCLK_Div1);
105
106
  /* PCLK1 = HCLK/8 = 7 MHz*/
107
  RCC_PCLK1Config(RCC_HCLK_Div8);
108
  
109
  /* PCLK2 = HCLK/2 = 28 MHz*/
110
  RCC_PCLK2Config(RCC_HCLK_Div2);
111
112
  /* ADCCLK = PCLK2/2 = 14 MHz --> ADCCLK must not be higher than 14 MHz */
113
  switch(ADC_Clock)
114
  {
115
  case 1: RCC_ADCCLKConfig(RCC_PCLK2_Div2); break;
116
  case 2: RCC_ADCCLKConfig(RCC_PCLK2_Div4); break; 
117
  case 3: RCC_ADCCLKConfig(RCC_PCLK2_Div6); break;
118
  case 4: RCC_ADCCLKConfig(RCC_PCLK2_Div8); break; 
119
  }
120
    
121
  /* Enable peripheral clocks ------------------------------------------------*/
122
123
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 | RCC_AHBPeriph_DMA2, ENABLE); // Enable DMA1 and DMA2 clocks
124
125
  /* Enable ADC1, ADC2, GPIOA, GPIOC GPIOD, AFIO and USART1 clocks */
126
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA |RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO | 
127
                         RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_GPIOC, ENABLE);
128
129
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 | RCC_APB1Periph_TIM2, ENABLE); // Enable USART2 and TIM2 clocks
130
}
131
132
/**
133
  * @brief  Configures the different GPIO ports.
134
  * @param  None
135
  * @retval None
136
  */
137
void GPIO_Configuration(void)
138
{
139
  GPIO_InitTypeDef GPIO_InitStructure;
140
141
  /* Configure PC.01, PC.02, PC.03 and PC.04 (ADC Channel11, ADC Channel12, ADC Channel13 and 
142
     ADC Channel14) as analog inputs */
143
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
144
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
145
  GPIO_Init(GPIOC, &GPIO_InitStructure);
146
147
  /* Configure USART1 RTS and USART2 Tx as alternate function push-pull */
148
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
149
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
150
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
151
  GPIO_Init(GPIOA, &GPIO_InitStructure);
152
153
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
154
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
155
  GPIO_Init(GPIOA, &GPIO_InitStructure);
156
}
157
158
/**
159
  * @brief  Configures Vector Table base location.
160
  * @param  None
161
  * @retval None
162
  */
163
void NVIC_Configuration(void)
164
{
165
  NVIC_InitTypeDef NVIC_InitStructure;
166
167
  /* Configure and enable ADC interrupt */
168
  #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
169
  NVIC_InitStructure.NVIC_IRQChannel = ADC1_IRQn;
170
#else
171
  NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
172
#endif
173
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
174
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
175
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
176
  NVIC_Init(&NVIC_InitStructure);
177
178
  /* Enable the TIM2 gloabal Interrupt */
179
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
180
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
181
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
182
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
183
  NVIC_Init(&NVIC_InitStructure);
184
}
185
186
void send_string(char value[255]) 
187
{
188
  int n;
189
190
  for(n=0; n<strlen(value);n++)
191
  {
192
    USART_SendData(USART1, value[n]); //USART transmission
193
    while(!USART_GetFlagStatus(USART1, USART_FLAG_TC)); // Wait until transmission complete
194
  }
195
}
196
197
void ADC1_Configuration(void)
198
{
199
  /* ADC1 configuration ------------------------------------------------------*/
200
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
201
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
202
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
203
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
204
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
205
  ADC_InitStructure.ADC_NbrOfChannel = 1;
206
  ADC_Init(ADC1, &ADC_InitStructure);
207
 
208
/* ADC1 regular channels configuration */  
209
  switch(ADC_Cycles)
210
  {
211
  case 1: ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_1Cycles5); break;
212
  case 2: ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_7Cycles5); break;
213
  case 3: ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_13Cycles5); break;
214
  case 4: ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_28Cycles5); break;
215
  case 5: ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_41Cycles5); break;
216
  case 6: ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5); break;
217
  case 7: ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_71Cycles5); break;
218
  case 8: ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_239Cycles5); break;
219
  }
220
221
  ADC_ITConfig(ADC1, ADC_IT_EOC, DISABLE); // Enable ADC1 EOC interrupt
222
  ADC_ITConfig(ADC1, ADC_IT_AWD, ENABLE); // Enable ADC1 AWD interrupt
223
224
  ADC_AnalogWatchdogCmd(ADC1, ADC_AnalogWatchdog_SingleRegEnable);
225
  ADC_AnalogWatchdogThresholdsConfig(ADC1, 0x6A0, 0x000);
226
  ADC_AnalogWatchdogSingleChannelConfig(ADC1, ADC_Channel_11);
227
228
  ADC_DMACmd(ADC1, ENABLE); // Enable ADC1 DMA
229
}  
230
  
231
void ADC2_Configuration(void)
232
{
233
  /* ADC2 configuration ------------------------------------------------------*/
234
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
235
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
236
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
237
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
238
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
239
  ADC_InitStructure.ADC_NbrOfChannel = 1;
240
  ADC_Init(ADC2, &ADC_InitStructure);
241
  
242
  ADC_RegularChannelConfig(ADC2, ADC_Channel_14, 1, ADC_SampleTime_28Cycles5); // ADC2 regular channels configuration
243
  ADC_ITConfig(ADC2, ADC_IT_EOC, DISABLE); // Enable ADC2 EOC interupt 
244
  ADC_DMACmd(ADC2, ENABLE); // Enable ADC2 DMA 
245
}
246
247
void ADC1_Calibration(void)
248
{
249
  ADC_ResetCalibration(ADC1); // Enabe ADC1 reset calibration register
250
  while(!ADC_GetResetCalibrationStatus(ADC1)); // Check the end of ADC1 reset calibration register
251
  ADC_StartCalibration(ADC1); // Start ADC1 calibration
252
  while(ADC_GetCalibrationStatus(ADC1)); // Check the end of ADC1 calibration
253
}        
254
  
255
void ADC2_Calibration(void)
256
{
257
  ADC_ResetCalibration(ADC2); // Enable ADC2 reset calibaration register
258
  while(!ADC_GetResetCalibrationStatus(ADC2)); // Check the end of ADC2 reset calibration register
259
  ADC_StartCalibration(ADC2); // Start ADC2 calibaration
260
  while(ADC_GetCalibrationStatus(ADC2)); // Check the end of ADC2 calibration
261
}
262
263
264
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
265
void ADC1_IRQHandler(void)
266
#else
267
void ADC1_2_IRQHandler(void)
268
#endif
269
{ 
270
  STM_EVAL_LEDOn(LED1);
271
  if(ADC_GetITStatus(ADC1, ADC_IT_EOC) != RESET)
272
  {
273
    sprintf(buf, "%d\t%d ms\n\r", ADC1ConvertedValue, time);
274
    send_string(buf);
275
  
276
    ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
277
    ADC_ClearITPendingBit(ADC1, ADC_IT_AWD);
278
  }
279
}

Ich habe einige eher unwichtige Parts 'rausgelassen, wundert euch also 
nicht über etwaige unnütze Timer-Clocks etc.

MfG,

blisson

von blisson (Gast)


Lesenswert?

Ein kleiner Nachtrag noch:

Ich hatte bei meinen Tests natürlich folgendes stehen:

ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);

bzw.

ADC_ITConfig(ADC2, ADC_IT_EOC, ENABLE);

MfG,

blisson

von holger (Gast)


Lesenswert?

>der Zusatz-Datei system_stm32f10x.c eine Zeile unter folgendem stehen:
>
>#ifdef VECT_TAB_SRAM
>  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in 
>Internal SRAM. */
>#else
>  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in 
>Internal FLASH. */
>#endif

>Deshalb gehe ich davon aus, dass er auf den Interrupt zwar reagiert, die
>zugehörige ISR jedoch nicht findet.

Ich gehe davon aus das der einen Reset bekommen hat.
Die Zeile in der du landest wird beim Systemstart ausgeführt.

von blisson (Gast)


Lesenswert?

Hallo Holger,

erstmal danke für die Antwort.

Was ich vielleicht noch hätte dazusagen sollen:

Ich habe wie erwähnt den AnalogWatchdog ebenfalls getestet und 
festgestellt, dass er dieses Verhalten auch genau dann zeigt, wenn sich 
der (in meinem Fall steuerbare) Spannungswert, der am ADC anliegt, aus 
dem erlaubten Spannungsbereich herausbewegt. D.h. genau dann, wenn er 
eigtl. einen Interrupt erzeugen sollte.
Und selbst wenn er, wie du sagst, einen Reset bekommt und diese Zeile 
Teil des dann eintretenden Systemstarts ist, warum bleibt er dann an 
diesem Punkt stehen?
Des weiteren: Sollte das Reset-Signal nicht i.A. vom Hardware-Debugger 
bemerkt werden? Zumindest bei einem per Taster auf dem Board ausgelösten 
Reset ist es so.

Jemand dazu eine Idee?

Mfg,

blisson

von blisson (Gast)


Lesenswert?

Niemand eine Idee? :(

blisson

von blisson (Gast)


Lesenswert?

Also, falls es jemanden interessiert :), ich konnte das Problem 
mittlerweile lösen. Offenbar ist der für den ADC1_2_IRQn zuständige 
Handler nicht der in der von mir genutzten Toolchain (und auch im 
Manual) angegebene ADC1_2_IRQHandler sondern ADC1_IRQHandler.

Diese Möglichkeit hielt ich bisher nur für unwahrscheinlich, weil in der 
restlichen Toolchain wie gesagt der ADC1_2_IRQHandler verwendet wird und 
auf den eigentlich richtigen ADC1_IRQHandler kein Hinweis, geschweige 
denn eine Deklaration desselben zu finden ist.

Offenbar einer von vielen unschönen Fehlerchen, die sich in den letzten 
Library-Versionen eingeschlichen haben...

blisson

von stealthy2k (Gast)


Lesenswert?

Hallo,

sollte
while(!ADC_GetResetCalibrationStatus(ADC2));
nicht
while(ADC_GetResetCalibrationStatus(ADC2));
sein? (oder wurde die Funktion umgeschrieben? :)

Achja habe da ev. noch ne Frage, wenn ich die ADC Cycle unter 28.5 
stelle (14Mhz ADC-Clk)...
z.B. 1.5 oder 7.5 ... bekomme ich immer einen Offset auf die ADC-Werte

je kleiner der Cycle desto größer der Offset...

Jemand ne Idee?

Ich überleg ob es etwas mit der Kalibrierung zu tun hat, mir gehen die 
Ideen aus...


lg

von stealthy2k (Gast)


Lesenswert?

So,

habe den Fehler...
Schuld war eine ungewohnt kleine Eingangsimpedanz des ADC's, welche 
durch die "Sample-Hold-Technologie" des ADC's abhängig von der 
Abtastrate ist...

lg Stealthy2k

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.