Forum: Mikrocontroller und Digitale Elektronik STM32F103 Timer Synchronisierung für ADC


von Stm M. (stmfresser)


Angehängte Dateien:

Lesenswert?

Hallo,

ich möchte 3 Phasenströme von einem BLDC Motor für eine feldorientierte 
Regelung messen. Wie es im FOC üblich ist, muss die AD Wandlung bei 
jedem PWM Cycle in der Mitte der PWM DutyCycle von Timer1 bei Center 
Aligned Mode geschehen. Dabei kann ich die Ch1 Ch2 Ch3 von Timer1 nicht 
als Trigger Input für den ADC nehmen. Leider gibts bei dem STM32F103 
nicht die Trigger Möglichkeit über den Ch4.

Daher will ich den Timer4 mit Timer1 synchronisieren und über Timer4 Ch4 
den ADC triggern. Bei meiner derzeitigen Initialisierung läuft der 
Timer4 nicht wie es mir gewünscht hatte. Für Debug habe ich einen Pin 
nach jeder AD Wandlung toggeln lassen. Wie man auf dem Bild sieht, wird 
die AD Wandlung immer bei jeden 3ten PWM Phase ausgelöst.

Weiss jemand woran es liegt?

Vielen Dank im Voraus.

Hier mein Code:
1
void Timer_Configuration(void) {
2
  /* TIM1 clock enable APB2 = 48MHz */
3
  /* 15kHz PWM_fr = TIM_CLK_fr / (Prescaler + 1) / (Period + 1)  TIM_CLK_fr = 48MHz */
4
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
5
  TIM_OCInitTypeDef TIM_OCInitStructure;
6
7
  /* Initialize basic structures to default */
8
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
9
  TIM_OCStructInit(&TIM_OCInitStructure);
10
11
  /* TIM4 Peripheral Configuration ----------------------------------------*/
12
  /* TIM4 Slave Configuration: PWM1 Mode
13
   * The TIM4 is running at:
14
   (TIM1 frequency)/ ((TIM4 period +1)* (Repetition_Counter+1)) = 15KHz */
15
16
  TIM_TimeBaseStructure.TIM_Period = 1;
17
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
18
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
19
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;
20
21
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
22
23
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
24
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
25
  TIM_OCInitStructure.TIM_Pulse = TIM4->ARR-1;
26
27
  TIM_OC4Init(TIM4, &TIM_OCInitStructure);
28
29
  /* Slave Mode selection: TIM4 */
30
  TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Gated);
31
  TIM_SelectInputTrigger(TIM4, TIM_TS_ITR0);
32
33
  /* TIM1 Peripheral Configuration ----------------------------------------*/
34
  /* Time Base configuration */
35
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
36
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;
37
  TIM_TimeBaseStructure.TIM_Period = 1600 - 1;
38
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
39
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
40
41
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
42
43
  /* Channel 1, 2 and 3 Configuration in PWM mode */
44
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
45
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
46
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
47
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
48
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
49
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
50
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
51
52
  TIM_OCInitStructure.TIM_Pulse = 0;
53
  TIM_OC1Init(TIM1, &TIM_OCInitStructure);
54
55
  TIM_OCInitStructure.TIM_Pulse = 0;
56
  TIM_OC2Init(TIM1, &TIM_OCInitStructure);
57
58
  TIM_OCInitStructure.TIM_Pulse = 0;
59
  TIM_OC3Init(TIM1, &TIM_OCInitStructure);
60
61
  /* Master Mode selection */
62
  TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
63
64
  /* Select the Master Slave Mode */
65
  TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
66
67
  /* TIM enable counter */
68
  TIM_Cmd(TIM1, ENABLE);
69
  TIM_Cmd(TIM4, ENABLE);
70
71
}
72
73
void NVIC_Configuration(void) {
74
  /* Configure and enable ADC interrupt */
75
  NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
76
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
77
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
78
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
79
  NVIC_Init(&NVIC_InitStructure);
80
}
81
82
void DMA_Configuration(void) {
83
  DMA_InitTypeDef DMA_InitStructure;
84
  DMA_DeInit(DMA1_Channel1);
85
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(ADC1->DR);
86
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) ADCBuffer;
87
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
88
  DMA_InitStructure.DMA_BufferSize = 3;
89
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
90
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // Disable only ADCBuffer[0]
91
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
92
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
93
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
94
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
95
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
96
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
97
98
  /* Enable DMA1 channel1 */
99
  DMA_Cmd(DMA1_Channel1, ENABLE);
100
}
101
102
void ADC_Configuration(void) {
103
  ADC_InitTypeDef ADC_InitStructure;
104
  /* ADC1 configuration ------------------------------------------------------*/
105
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
106
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
107
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
108
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4;
109
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
110
  ADC_InitStructure.ADC_NbrOfChannel = 3;
111
  ADC_Init(ADC1, &ADC_InitStructure);
112
113
  /* ADC1 rchannel10-15 configuration 14Cycles = 1us, Tconv = 7.5 + 12.5 = 20 ca 5us*/
114
  ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_7Cycles5);
115
  ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 2, ADC_SampleTime_7Cycles5);
116
  ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 3, ADC_SampleTime_7Cycles5);
117
118
  /* Regular discontinuous mode channel number configuration */
119
  ADC_DiscModeChannelCountConfig(ADC1, 1);
120
  /* Enable regular discontinuous mode */
121
  ADC_DiscModeCmd(ADC1, ENABLE);
122
123
  /* Enable ADC1 external trigger */
124
  ADC_ExternalTrigConvCmd(ADC1, ENABLE);
125
126
  /* Enable EOC interrupt */
127
  ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
128
129
  /* Enable ADC1 DMA */
130
  ADC_DMACmd(ADC1, ENABLE);
131
132
  /* Enable ADC1 */
133
  ADC_Cmd(ADC1, ENABLE);
134
135
  /* Enable ADC1 reset calibration register */
136
  ADC_ResetCalibration(ADC1);
137
  /* Check the end of ADC1 reset calibration register */
138
  while (ADC_GetResetCalibrationStatus(ADC1)) {
139
  }
140
141
  /* Start ADC1 calibration */
142
  ADC_StartCalibration(ADC1);
143
  /* Check the end of ADC1 calibration */
144
  while (ADC_GetCalibrationStatus(ADC1)) {
145
  }
146
147
  /* Start ADC1 Software Conversion */
148
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
149
}
150
151
void ADC1_2_IRQHandler(void) {
152
  ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
153
  GPIOA->ODR ^= GPIO_Pin_2;
154
155
}

von S. K. (hauspapa)


Lesenswert?

Ist nicht genau für Deinen Fall im Timer TIMx_CR2 Register das Bit 3 
geschaffen worden:

"Bit 3 CCDS: Capture/compare DMA selection
0: CCx DMA request sent when CCx event occurs
1: CCx DMA requests sent when update event occurs"

Das Ding auf 1 setzten und alles wird gut.

Deinen Code habe ich mir bisher nicht im Detail angeschaut.

viel Erfolg
hauspapa

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.