Forum: Mikrocontroller und Digitale Elektronik STM32 ADC und Interrupt


von Peter N. (piddie)


Lesenswert?

Hallo zusammen,

ich habe ein STM32F4 Discovery Board und will ein Programm schreiben, 
welches nach dem Drücken des user buttons auf dem Board einen Interrupt 
auslöst. Daraufhin soll dann ein Array mit ADC Samples gefüllt werden. 
Das ganze auch noch in Verbindung mit dem DMA Controller. Wenn das Array 
gefüllt ist, soll wieder ein Interrupt ausgelöst werden.
Ich habe es vorher schon geschafft mit DMA Controller und ADC ein Array 
mit ADC Samples zu füllen. Der Interrupt des user buttons wird richtig 
ausgelöst, aber dann schaff ich es nicht die Analog-Digital-Wandlungen 
ans laufen zu bringen.
Hier mal mein Code, kann gut sein, dass die eine oder andere Stelle 
aktuell keinen Sinn macht, weil ich recht viel rumprobiert habe.

#include <stdbool.h>
#include "misc.h"
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_dma.h"
#include "stm32f4xx_tim.h"
#include "stm32f4xx_exti.h"
#include "stm32f4xx_syscfg.h"

//################GLOBAL VARIABLES###############
#define BUFFER_SIZE 2048
volatile uint32_t dest_array[BUFFER_SIZE];
volatile uint16_t result = 0;

//################LOCAL FUNCTIONS###############
void Delay(__IO uint32_t nCount) {
  while(nCount--) {
  }
}

//function to initialize interrupt on user button pressed
static void EXTILine0_Config(void)
{
  EXTI_InitTypeDef   EXTI_InitStructure;
  GPIO_InitTypeDef   GPIO_InitStructure;
  NVIC_InitTypeDef   NVIC_InitStructure;

  // Enable GPIOA clock
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  // Enable SYSCFG clock
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

  // Configure PA0 pin as input floating
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  // Connect EXTI Line0 to PA0 pin
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);

  // Configure EXTI Line0
  EXTI_InitStructure.EXTI_Line = EXTI_Line0;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);

  // Enable and set EXTI Line0 Interrupt to the lowest priority
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

//function to initialize ADC2
static void ADC2_Init(void)
{
  //Init GPIOA
  GPIO_InitTypeDef  GPIO_InitStructure;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  //initialize ADC2

  //enable clock
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);

  //create ADC_Init structure
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
  ADC_InitTypeDef       ADC_InitStructure;

  //initialize initStructs
  ADC_CommonInitStructure.ADC_DMAAccessMode = 
ADC_DMAAccessMode_Disabled;
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = 
ADC_TwoSamplingDelay_20Cycles;

  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = 
ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; 
//WTF doesn't change anything
  ADC_InitStructure.ADC_NbrOfConversion = 1;
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;

  //adc init
  ADC_CommonInit(&ADC_CommonInitStructure);
  ADC_Init(ADC2, &ADC_InitStructure);

  //configurate channel
  ADC_RegularChannelConfig(ADC2, ADC_Channel_4, 1, 
ADC_SampleTime_480Cycles);

  //enable ADC EOC IT
  //ADC_ITConfig(ADC2, ADC_IT_EOC, ENABLE);
}

//function to initialize DMA2
static void DMA2_Init(void)
{
  // Clock Enable
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

  //initialize DMA controller
  DMA_InitTypeDef       DMA_InitStructure;

  // DMA-Disable
  DMA_Cmd(DMA2_Stream2, DISABLE);
  DMA_DeInit(DMA2_Stream2);

  //initialize DMA_Init structure
  DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;
  DMA_InitStructure.DMA_Channel = DMA_Channel_1;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&dest_array;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC2->DR;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_InitStructure.DMA_PeripheralDataSize = 
DMA_PeripheralDataSize_Word;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;

  DMA_Init(DMA2_Stream2, &DMA_InitStructure);
  DMA_Cmd(DMA2_Stream2, ENABLE);

  ADC_DMARequestAfterLastTransferCmd(ADC2, DISABLE);
  DMA_ITConfig(DMA2_Stream2, DMA_IT_TC, ENABLE);
}

//interrupt handler for EXTI0 (user button pressed)
void EXTI0_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line0) != RESET)
  {
  //do 2048 ADC conversions and save data with DMA controller
  //start ADC2 once, interrupt does the rest
  ADC_SoftwareStartConv(ADC2);
  }
    // Clear the EXTI line 0 pending bit
    EXTI_ClearITPendingBit(EXTI_Line0);
}

//interrupt handler for ADC2 (end of conversion EOC IT)
//interrupt currently deactivated
void ADC1_2_IRQHandler(void)
{
  if(ADC_GetITStatus(ADC2, ADC_IT_EOC) != RESET)
  {
    Delay(1000);
  }
}

void DMA2_Stream2_IRQHandler(void)
{
  //should be reached if buffer is filled complete
  //disable adc2; enable on next user button pressed
  ADC_Cmd(ADC2, DISABLE);
  //TODO: generate software interrupt

}



//#########################MAIN#######################
int main(void)
{
  SystemInit(); // set clock settings
  EXTILine0_Config();
  ADC2_Init();
  DMA2_Init();

  int i;
  for(i=0;i<BUFFER_SIZE;i++)
  {
  dest_array[i] = i;
  }

  while(1)
  {
    //interrupt does the job
  }
}

von Gerald G. (gerald_g)


Lesenswert?

Ich kann dir zwar nicht genau helfen, aber an deiner Stelle würde ich 
versuchen den ADC/DMA Start erst einmal nicht mit einem interrupt, 
sondern "normal" über eine if-abfrage zu starten. Wenn das dann läuft, 
weißt du es liegt am interrupt für den Taster, ansonsten beim ADC/DMA

von Peter N. (piddie)


Lesenswert?

So, hab aufjedenfall einen Fehler gefuden. Habe dummerweise vergessen 
den ADC zu starten.

  //enable ADC
  ADC_DMACmd(ADC2, ENABLE);
  ADC_Cmd(ADC2, ENABLE);
  ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE);

In den Interrupt vom user button wird schön reingesprungen. Da starte 
ich jetzt die ADC conversion. Das klappt soweit.
Allerdings wird nicht in den Interrupt vom ADC (ADC_IT_EOC) und nicht in 
den vom DMA Controller (DMA_IT_TC) gesprungen. Kann mir jemand dabei 
helfen woran das liegt?

Ziel ist es, wie oben schon beschrieben, nach dem Drücken des Buttons 
beispielsweise 2048 Messwerte mit dem ADC aufzunehmen, diese mit dem DMA 
wegzuschreiben und danach einen Interrupt zu erzeugen. Ich könnte 
natürlich eine Schleife schreiben und 2048 ADC conversions starten, aber 
ich denke das muss auch irgendwie schöner gehen.

Vielen Dank schonmal.

von Irgendwer (Gast)


Lesenswert?

> DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

Warum lößt du den DMA Interrupt bei Halbvoll aus wenn du aber eigentlich 
2048 Sampels haben willst?


> //interrupt handler for EXTI0 (user button pressed)
> void EXTI0_IRQHandler(void)
> {
Hier fehlt eine Sperrflag das verhindert das dass Tastenprellen (oder 
auch ein erneutes drücken) den ADC immer wieder neu startet wenn es 
schon/noch läuft.

> //interrupt handler for ADC2 (end of conversion EOC IT)
> //interrupt currently deactivated
> void ADC1_2_IRQHandler(void)
> {
>   if(ADC_GetITStatus(ADC2, ADC_IT_EOC) != RESET)
>   {
>     Delay(1000);
>   }
> }
>
Delay innerhalb einer ISR. Der bloße Gedanke daran gehört eigentlich 
schon
mit heftigen ..... bestraft:-)

> void DMA2_Stream2_IRQHandler(void)
> {
Hier eine Flag setzen das die Daten "fertig" sind und weiterverarbeitet 
werden können. Wenn die main die Daten verarbeitet hat kann sie dann 
beide Flags zurücksetzen uns das System ist bereit für einen neuen 
Start...

von Thomas W. (ratos)


Lesenswert?

Peter N. schrieb:
> Allerdings wird nicht in den Interrupt vom ADC (ADC_IT_EOC) und nicht in
> den vom DMA Controller (DMA_IT_TC) gesprungen. Kann mir jemand dabei
> helfen woran das liegt?

Vielleicht noch die Interrupts mit NVIC aktivieren?

von Peter N. (piddie)


Lesenswert?

Danke für deine Antwort Irgendwer.
Ich habe jetzt mal die DMA_InitStructure.DMA_FIFOThreshold = 
DMA_FIFOThreshold_Full; gesetzt. Aber das macht eigentlich keinen 
Unterschied. Ich habe bisher gedacht, dass diese Option einstellt, wie 
lange der DMA Daten in seinem FIFO zwischenspeichert, bis er einmal 
alles an die destination schreibt. Ich glaub eigentlich nicht, dass das 
irgendwas mit dem DMA Interrupt zu tun hat oder?

Habe jetzt ein Sperrflag im EXTI0_IRQHandler eingebaut. Gute Idee.

von Irgendwer (Gast)


Lesenswert?

Peter N. schrieb:
> Ich habe jetzt mal die DMA_InitStructure.DMA_FIFOThreshold =
> DMA_FIFOThreshold_Full; gesetzt. Aber das macht eigentlich keinen
> Unterschied. Ich habe bisher gedacht, dass diese Option einstellt, wie
> lange der DMA Daten in seinem FIFO zwischenspeichert, bis er einmal
> alles an die destination schreibt.

Ja, sorry. Hier hatte ich auf die schnelle was verwechselt (es gibt auch 
einen Mode wo bei "Half-transfer" bereits ein irq ausgelößt wird).
Du hast ja ohnehin DMA_InitStructure.DMA_FIFOMode = 
DMA_FIFOMode_Disable; so das die Einstellungen für den FiFo egal sind.


Was mir aber noch merkwürdig erscheint ist:
> volatile uint32_t dest_array[BUFFER_SIZE];
> DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
Das Arrey ist DWord, du stellst aber unter Size Word ein(was ja durchaus 
zum ADC passt). Beim auslesen das Arrys hast du dann aber zwei Werte in 
einer 32Bit Variable.


Und warum:
> DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
wenn du am ende eh anhalten willst und manuell neustarten?


Was ich irgendwie garnicht bei dir finde ist das Gegenstück zu z.B.
> // Transfer complete interrupt enable
> DMA1_S5_CR.TCIE=1; (keine Ahnung wo das genau in den ST-Beispielfunktionen 
versteckt ist)
wo du den "Transfer complete" Interrupt überhaupt aktivierst?


Table 43. DMA interrupt requests
Half-transfer HTIF HTIE
Transfer complete TCIF TCIE
Transfer error TEIF TEIE
FIFO overrun/underrun FEIF FEIE
Direct mode error DMEIF DMEIE

von Peter N. (piddie)


Lesenswert?

Thomas W. schrieb:
> Vielleicht noch die Interrupts mit NVIC aktivieren?

Okay danke, das hab ich gemacht und jetzt funktionieren die Interrupts.


Irgendwer schrieb:
> Ja, sorry. Hier hatte ich auf die schnelle was verwechselt (es gibt auch
> einen Mode wo bei "Half-transfer" bereits ein irq ausgelößt wird).
> Du hast ja ohnehin DMA_InitStructure.DMA_FIFOMode =
> DMA_FIFOMode_Disable; so das die Einstellungen für den FiFo egal sind.

Jo, hab den FIFO jetzt mal aktiviert und auf full transfer gestellt. 
Jetzt wartet der immer, bis 4 Messwerte vorliegen und schreibt die dann 
ins dest_array.

> Was mir aber noch merkwürdig erscheint ist:
>> volatile uint32_t dest_array[BUFFER_SIZE];
>> DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
> Das Arrey ist DWord, du stellst aber unter Size Word ein(was ja durchaus
> zum ADC passt). Beim auslesen das Arrys hast du dann aber zwei Werte in
> einer 32Bit Variable.

Also ich weiß nicht warum, aber die Werte im Array passen. Ich hab den 
Pin den ich auslese auf 3V gezogen und ich hab Werte im Array, die meist 
recht nahe bei 4095 liegen.
Das Array muss aber scheinbar uint32_t sein, weil die Adresse dieses 
Format hat?

> Was ich irgendwie garnicht bei dir finde ist das Gegenstück zu z.B.
>> // Transfer complete interrupt enable
>> DMA1_S5_CR.TCIE=1; (keine Ahnung wo das genau in den ST-Beispielfunktionen
> versteckt ist)
> wo du den "Transfer complete" Interrupt überhaupt aktivierst?

Den aktiviere ich in der letzten Zeile der Funktion DMA2_Init() und halt 
jetzt noch mir NVIC...
1
DMA_ITConfig(DMA2_Stream2, DMA_IT_TC, ENABLE);

Soweit läuft das jetzt. Ich versuche jetzt den ADC mit einem Timer zu 
triggern. Vielen Dank für eure Hilfe, schönes Wochenende.

von Peter N. (piddie)


Lesenswert?

Hey, leider habe ich auch Probleme damit den ADC mit einem Timer zu 
triggern.
Ich habe mich unter anderem an diesem Beispiel orientiert:

Beitrag "stm32F4 + ADC + Timer + DMA"

Aber der ADC wird irgendwie nicht durch den Timer getriggert. Wenn ich 
den user button des Discoveryboards drücke, wird eine ADC Wandlung 
durchgeführt. Ziel ist es nach dem Drücken des Buttons das Array mit 
Messwerten voll zu schreiben, die mit der Frequenz mit der der Timer 
triggert gesamplet wurden.

Hier mein aktueller Code:
1
//#include "main.h"
2
#include <stdbool.h>
3
#include "misc.h"
4
#include "stm32f4xx.h"
5
#include "stm32f4xx_gpio.h"
6
#include "stm32f4xx_rcc.h"
7
#include "stm32f4xx_adc.h"
8
#include "stm32f4xx_dma.h"
9
#include "stm32f4xx_tim.h"
10
#include "stm32f4xx_exti.h"
11
#include "stm32f4xx_syscfg.h"
12
13
//################GLOBAL VARIABLES###############
14
#define BUFFER_SIZE 2048
15
volatile uint32_t dest_array[BUFFER_SIZE];
16
volatile uint16_t result = 0;
17
volatile bool button_pressed = false;
18
volatile bool conversion_finished = false;
19
20
//#################LOCAL FUNCTIONS###############
21
void Delay(__IO uint32_t nCount) {
22
  while(nCount--) {
23
  }
24
}
25
26
//function to initialize interrupt on user button pressed
27
static void EXTILine0_Config(void)
28
{
29
  [...]
30
}
31
32
//function to initialize ADC2
33
static void ADC2_Init(void)
34
{
35
  //Init GPIOA
36
  GPIO_InitTypeDef  GPIO_InitStructure;
37
38
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
39
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
40
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
41
  GPIO_Init(GPIOA, &GPIO_InitStructure);
42
43
  //initialize ADC2
44
45
  //enable clock
46
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
47
48
  //create ADC_Init structure
49
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
50
  ADC_InitTypeDef       ADC_InitStructure;
51
52
  //initialize initStructs
53
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
54
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
55
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
56
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
57
58
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
59
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
60
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
61
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
62
  ADC_InitStructure.ADC_NbrOfConversion = 1;
63
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
64
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
65
66
  //adc init
67
  ADC_CommonInit(&ADC_CommonInitStructure);
68
  ADC_Init(ADC2, &ADC_InitStructure);
69
70
  //configurate channel
71
  ADC_RegularChannelConfig(ADC2, ADC_Channel_4, 1, ADC_SampleTime_15Cycles);
72
73
  //enable ADC EOC IT
74
  //ADC_ITConfig(ADC2, ADC_IT_EOC, ENABLE);
75
76
  //enable ADC
77
  ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE);
78
  ADC_DMACmd(ADC2, ENABLE);
79
  ADC_Cmd(ADC2, ENABLE);
80
81
  //init ADC interrupt
82
  NVIC_InitTypeDef   NVIC_InitStructure;
83
84
  NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
85
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
86
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
87
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
88
  NVIC_Init(&NVIC_InitStructure);
89
}
90
91
//function to initialize DMA2
92
static void DMA2_Init(void)
93
{
94
  // Clock Enable
95
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
96
97
  //initialize DMA controller
98
  DMA_InitTypeDef       DMA_InitStructure;
99
100
  // DMA-Disable
101
  DMA_Cmd(DMA2_Stream2, DISABLE);
102
  DMA_DeInit(DMA2_Stream2);
103
104
  //initialize DMA_Init structure
105
  DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;
106
  DMA_InitStructure.DMA_Channel = DMA_Channel_1;
107
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
108
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
109
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
110
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&dest_array;
111
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
112
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
113
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
114
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
115
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC2->DR;
116
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
117
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
118
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
119
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
120
121
  DMA_Init(DMA2_Stream2, &DMA_InitStructure);
122
  DMA_Cmd(DMA2_Stream2, ENABLE);
123
124
  ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE);
125
  DMA_ITConfig(DMA2_Stream2, DMA_IT_TC, ENABLE);
126
127
  NVIC_InitTypeDef   NVIC_InitStructure;
128
129
  NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn;
130
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
131
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
132
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
133
134
  NVIC_Init(&NVIC_InitStructure);
135
}
136
137
//function to initialize Timer 2
138
static void Timer_Init(void)
139
{
140
  RCC_AHB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
141
142
  //TIM intit structure
143
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
144
145
  //config init structure
146
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
147
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
148
  TIM_TimeBaseStructure.TIM_Period = 84-1;
149
  TIM_TimeBaseStructure.TIM_Prescaler = 1000-1;
150
  //TIM_TimeBaseStructure.TIM_RepetitionCounter = ?;
151
152
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
153
  TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
154
  //TIM_Cmd(TIM2, ENABLE);
155
156
}
157
158
//interrupt handler for EXTI0 (user button pressed)
159
void EXTI0_IRQHandler(void)
160
{
161
  if(EXTI_GetITStatus(EXTI_Line0) != RESET)
162
  {
163
    if(button_pressed == false)
164
    {
165
      button_pressed = true;
166
      //start ADC2 once, interrupt does the rest
167
      ADC_SoftwareStartConv(ADC2);
168
    }
169
  }
170
  // Clear the EXTI line 0 pending bit
171
  EXTI_ClearITPendingBit(EXTI_Line0);
172
}
173
174
//interrupt handler for ADC2 (end of conversion EOC IT)
175
void ADC_IRQHandler()
176
{
177
  //ADC_SoftwareStartConv(ADC2);
178
}
179
180
void DMA2_Stream2_IRQHandler(void)
181
{
182
  //should be reached if buffer is filled complete
183
  //TODO: generate software interrupt
184
  if(conversion_finished == false)
185
  {
186
    conversion_finished = true;
187
  }
188
}
189
190
191
192
//#########################MAIN#######################
193
int main(void)
194
{
195
  SystemInit(); // set clock settings
196
  EXTILine0_Config();
197
  Timer_Init();
198
  ADC2_Init();
199
  DMA2_Init();
200
201
  int i;
202
  for(i=0;i<BUFFER_SIZE;i++)
203
  {
204
  dest_array[i] = i;
205
  }
206
  //enable timer
207
  TIM_Cmd(TIM2, ENABLE);
208
209
  while(1)
210
  {
211
    //interrupt does the job
212
  }
213
}

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.