Forum: Mikrocontroller und Digitale Elektronik STM32F103 ADC per Timer triggern (SPL)


von Info (Gast)


Lesenswert?

Ich finde leider den Fehler nicht: Capture 2 funktioniert (Interrupt), 
löst aber nicht den ADC aus. Offenbar fehlt etwas - aber was?

1
#include "stm32f10x_conf.h"
2
3
int main(void)
4
{
5
6
    SystemInit();
7
8
9
    // Interrupts
10
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
11
12
    NVIC_InitTypeDef NVIC_InitStructure;
13
14
    NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
15
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
16
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
17
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
18
    NVIC_Init(&NVIC_InitStructure);
19
20
21
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
22
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
23
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
24
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
25
    NVIC_Init(&NVIC_InitStructure);
26
27
28
29
    // Clocks
30
31
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);
32
33
    RCC_APB2PeriphClockCmd(
34
        RCC_APB2Periph_GPIOA |
35
        RCC_APB2Periph_GPIOB |
36
        RCC_APB2Periph_AFIO  |
37
        RCC_APB2Periph_TIM1  |
38
        RCC_APB2Periph_ADC1  ,
39
        ENABLE
40
        );
41
42
43
44
    // IO
45
46
    GPIO_InitTypeDef GPIO_InitStructure;
47
48
    GPIO_StructInit(&GPIO_InitStructure);
49
50
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
51
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;       // AF: adc
52
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
53
54
    GPIO_Init(GPIOA, &GPIO_InitStructure);
55
56
57
    GPIO_StructInit( &GPIO_InitStructure );
58
59
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
60
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     // AF: timer 1 pwm
61
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
62
63
    GPIO_Init(GPIOA, &GPIO_InitStructure);
64
65
66
    GPIO_StructInit( &GPIO_InitStructure );
67
68
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
69
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
70
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
71
72
    GPIO_Init(GPIOB, &GPIO_InitStructure);
73
74
75
76
    // ADC
77
78
    ADC_InitTypeDef ADC_InitStructure;
79
80
    ADC_StructInit(&ADC_InitStructure);
81
82
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
83
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC2;
84
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
85
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
86
    ADC_InitStructure.ADC_NbrOfChannel = 1;
87
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
88
89
    ADC_Init(ADC1, &ADC_InitStructure);
90
91
    ADC_RegularChannelConfig(
92
         ADC1,
93
         ADC_Channel_1,
94
         1,                         // The rank in the regular group sequencer. This parameter must be between 1 to 16.
95
         ADC_SampleTime_1Cycles5
96
         );
97
98
    ADC_ExternalTrigConvCmd(ADC1, ENABLE);
99
100
    ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
101
    ADC_ITConfig(ADC1, ADC1_2_IRQn, ENABLE);
102
103
104
    ADC_Cmd(ADC1, ENABLE);
105
106
107
    // calibrate
108
    ADC_ResetCalibration(ADC1);
109
    while(ADC_GetResetCalibrationStatus(ADC1));
110
111
    ADC_StartCalibration(ADC1);
112
    while(ADC_GetCalibrationStatus(ADC1));
113
114
115
116
117
/*
118
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
119
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
120
    ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
121
    uint16_t value = ADC_GetConversionValue(ADC1);
122
*/
123
124
    // PWM Timer 1
125
126
    TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
127
128
    TIM_TimeBaseStructInit( &TIM_TimeBase_InitStructure );
129
130
    TIM_TimeBase_InitStructure.TIM_CounterMode =    TIM_CounterMode_Up;
131
    TIM_TimeBase_InitStructure.TIM_ClockDivision =  TIM_CKD_DIV1;
132
    TIM_TimeBase_InitStructure.TIM_Prescaler =      32;
133
    TIM_TimeBase_InitStructure.TIM_Period =         1023;
134
135
    TIM_TimeBaseInit(TIM1, &TIM_TimeBase_InitStructure);
136
137
138
139
    // CC1 PWM
140
    TIM_OCInitTypeDef   TIM_OC_InitStructure;
141
142
    TIM_OCStructInit( &TIM_OC_InitStructure );
143
144
    TIM_OC_InitStructure.TIM_OCMode =       TIM_OCMode_PWM1;
145
    TIM_OC_InitStructure.TIM_OCIdleState =  TIM_OCIdleState_Reset;
146
    TIM_OC_InitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
147
    TIM_OC_InitStructure.TIM_OCPolarity =   TIM_OCPolarity_High;
148
    TIM_OC_InitStructure.TIM_OCNPolarity =  TIM_OCNPolarity_Low;
149
    TIM_OC_InitStructure.TIM_Pulse =        127;
150
    TIM_OC_InitStructure.TIM_OutputState =  TIM_OutputState_Enable;
151
    TIM_OC_InitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
152
    TIM_OC1Init(TIM1, &TIM_OC_InitStructure);
153
154
    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
155
156
157
    // CC2 ADC
158
    TIM_OCStructInit( &TIM_OC_InitStructure );
159
    TIM_OC_InitStructure.TIM_Pulse =        511;
160
    TIM_OC2Init(TIM1, &TIM_OC_InitStructure);
161
162
    TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
163
164
165
    TIM_ClearITPendingBit(TIM1, TIM_IT_CC2);
166
    TIM_ITConfig(TIM1, TIM_IT_CC2, ENABLE);
167
168
169
170
    TIM_Cmd(TIM1, ENABLE);
171
172
    TIM_CtrlPWMOutputs(TIM1, ENABLE);
173
174
175
176
  while(1)
177
  {
178
179
  }
180
}
181
182
183
184
void ADC1_2_IRQHandler(void){
185
186
187
        if( ADC_GetITStatus(ADC1, ADC_IT_EOC) == SET){
188
            ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
189
190
            GPIO_ResetBits(GPIOB, GPIO_Pin_14);
191
        }
192
}
193
194
195
196
void TIM1_CC_IRQHandler(void)
197
{
198
    if( TIM_GetITStatus(TIM1, TIM_IT_CC1) == SET ){
199
        TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
200
    }
201
202
203
    if( TIM_GetITStatus(TIM1, TIM_IT_CC2) == SET ){
204
        TIM_ClearITPendingBit(TIM1, TIM_IT_CC2);
205
206
        if(GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_14) == SET)
207
            GPIO_ResetBits(GPIOB, GPIO_Pin_14);
208
        else
209
            GPIO_SetBits(GPIOB, GPIO_Pin_14);
210
211
    }
212
}

von Info (Gast)


Lesenswert?

Besser:
1
    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);

Macht aber keinen Unterschied :-(

von Info (Gast)


Lesenswert?

ADC und PWM haben mit alternate functions nichts zu tun, also:
1
//RCC_APB2Periph_AFIO  |

von Info (Gast)


Lesenswert?

Nach Softwaretrigger des ADCs kommt erwartungsgemäß der ADC-Interrupt, 
und mit der anderen Compare-Einheit
1
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;

klappt es ebenfalls prinzipiell. Nur mit CC2 nicht.

Es ist offenbar dasselbe Problem wie hier:

Beitrag "STM32: zweites compare-register vom timer verwenden"

von Info (Gast)


Lesenswert?

So richtig scheint es doch nicht zu gehen mit CC1: der angebliche 
ADC_IT_EOC fällt immer auf den Timerüberlauf, sprich auf die steigende 
Flanke des PWM-Pulses bei 0.

von Info (Gast)


Lesenswert?

Die Doku ist irreführend. Der externe Trigger des ADCs ist kein direktes 
"internes Signal" von der CC, sondern nutzt dessen Ausgangssignal, 
sprich, das (PWM-) Signal, und dort auch nur eine steigende Flanke. Um 
zum Comparezeitpunkt den ADC zu starten, muss also eine invertierte PWM 
erzeugt werden. Sie muss jedoch nicht zwangsläufig über den GPIO 
ausgegeben werden. Allerdings lässt sich dann wahrscheinlich eine 
weitere alternate function für den Pin nicht mehr nutzen, wenn dort 
schon der Timer aktiv ist.

Das ist etwas enttäuschend; ich hätte gedacht, 
timersynchrone/-gesteuerte Messungen wären an der Tagesordnung und daher 
einfach möglich, sprich per echtem, direktem "Event" von der 
Compare-Einheit.

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.