AnsweredAssumed Answered

Triggering ADC 1 with Timer 1 (STM32F103)

Question asked by none on Oct 5, 2016
Latest reply on Oct 5, 2016 by FTITI.Walid
STM32F103RC
I am trying to trigger ADC1 from Timer 1 CC 2, but nothing happens.
Timer 1 is configured with PWM and CC interrupt.
Triggering from Timer 1 CC 1 causes EOC Interrupt to execute on timer update (PWM rising edge) for some reason.
ADC interrupt works properly when triggering conversion in software (also from CC interrupt).

See attached scope capture (blue debug pin, pink PWM):
https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Attachments/70530/t1cc1_adc1.png
t1cc1_adc1.png

Is there more documentation on this than what I found in the Reference Manual (DocID13902 Rev 16) ?
11.7  Conversion on external trigger
Conversion can be triggered by an external event (e.g. timer capture, EXTI line). If the EXT-
TRIG  control  bit  is  set  then  external  events  are  able  to  trigger  a  conversion.  The  EXT-
SEL[2:0] and JEXTSEL[2:0] control bits allow the application to select decide which out of 8
possible events can trigger conversion for the regular and injected groups.
Note: When an external trigger is selected for ADC regular or injected conversion, only the rising
edge of the signal can start the conversion.
          Table 67. External trigger for regular channels for ADC1 and ADC2

The SPL code examples and everything else I found so far use DMA.
The Errata does not seem to mention anything that applies to my issue.

So aside from the different behaviour of the two compare units, I must be forgetting to configure something.

001.// attempting to trigger ADC conversion with Timer 1 Compare 2
002.//
003.// Softtrigger works as expected
004.// Trigger with CC1:
005.//   ADC interrupt occurs just after timer update/reset (when PWM output pin goes high)
006.// Trigger with CC2 does not work at all
007. 
008.// device: STM32F103RCT6 / 0x414
009.//   LQFP64
010.//   rev Y / 0x1003 (ST-Link Utility 3.9: rev X)
011.//   datecode 321
012.//
013. 
014.// 8 MHz crystal -> 72 MHz
015.// compiler
016./*
017.   C:\Program Files (x86)\EmBitz\1.00\share\em_armgcc\bin>arm-none-eabi-gcc-5.4.1.exe --version
018.   arm-none-eabi-gcc-5.4.1.exe (GNU Tools for ARM Embedded Processors) 5.4.1 20160609 (release) [ARM/embedded-5-branch revision 237715]
019.   Copyright (C) 2015 Free Software Foundation, Inc.
020.   This is free software; see the source for copying conditions.  There is NO
021.   warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
022.*/
023.// SPL 3.5
024. 
025.#include "stm32f10x_conf.h"
026. 
027. 
028.//#define SOFTTRIGGER
029.#define CC1
030.//#define CC2
031. 
032. 
033. 
034.int main(void)
035.{
036. 
037.    SystemInit();
038. 
039. 
040.    // Interrupts
041.    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
042. 
043.    NVIC_InitTypeDef NVIC_InitStructure;
044. 
045.    NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
046.    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
047.    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
048.    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
049.    NVIC_Init(&NVIC_InitStructure);
050. 
051. 
052.    NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
053.    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
054.    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
055.    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
056.    NVIC_Init(&NVIC_InitStructure);
057. 
058. 
059. 
060.    // Clocks
061. 
062.    RCC_ADCCLKConfig(RCC_PCLK2_Div6);
063. 
064.    RCC_APB2PeriphClockCmd(
065.        RCC_APB2Periph_GPIOA |
066.        RCC_APB2Periph_GPIOB |
067.        //RCC_APB2Periph_AFIO  |
068.        RCC_APB2Periph_TIM1  |
069.        RCC_APB2Periph_ADC1  ,
070.        ENABLE
071.        );
072. 
073. 
074. 
075.    // IO
076. 
077.    GPIO_InitTypeDef GPIO_InitStructure;
078. 
079.    GPIO_StructInit(&GPIO_InitStructure);
080. 
081.    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
082.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;       // adc
083.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
084. 
085.    GPIO_Init(GPIOA, &GPIO_InitStructure);
086. 
087. 
088.    GPIO_StructInit( &GPIO_InitStructure );
089. 
090.    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
091.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     // timer 1 pwm
092.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
093. 
094.    GPIO_Init(GPIOA, &GPIO_InitStructure);
095. 
096. 
097.    GPIO_StructInit( &GPIO_InitStructure );
098. 
099.    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
100.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
101.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
102. 
103.    GPIO_Init(GPIOB, &GPIO_InitStructure);
104. 
105. 
106. 
107.    // PWM Timer 1
108. 
109.    TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
110. 
111.    TIM_TimeBaseStructInit( &TIM_TimeBase_InitStructure );
112. 
113.    TIM_TimeBase_InitStructure.TIM_CounterMode =    TIM_CounterMode_Up;
114.    TIM_TimeBase_InitStructure.TIM_ClockDivision =  TIM_CKD_DIV1;
115.    TIM_TimeBase_InitStructure.TIM_Prescaler =      32;
116.    TIM_TimeBase_InitStructure.TIM_Period =         1023;
117. 
118.    TIM_TimeBaseInit(TIM1, &TIM_TimeBase_InitStructure);
119. 
120. 
121. 
122.    // CC1 PWM
123.    TIM_OCInitTypeDef   TIM_OC_InitStructure;
124. 
125.    TIM_OCStructInit( &TIM_OC_InitStructure );
126. 
127.    TIM_OC_InitStructure.TIM_OCMode =       TIM_OCMode_PWM1;
128.    TIM_OC_InitStructure.TIM_OCIdleState =  TIM_OCIdleState_Reset;
129.    TIM_OC_InitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
130.    TIM_OC_InitStructure.TIM_OCPolarity =   TIM_OCPolarity_High;
131.    TIM_OC_InitStructure.TIM_OCNPolarity =  TIM_OCNPolarity_Low;
132.    TIM_OC_InitStructure.TIM_Pulse =        127;
133.    TIM_OC_InitStructure.TIM_OutputState =  TIM_OutputState_Enable;
134.    TIM_OC_InitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
135.    TIM_OC1Init(TIM1, &TIM_OC_InitStructure);
136. 
137.    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
138. 
139.#ifdef CC1
140.    TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
141.    TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);
142.#endif
143. 
144. 
145.    // CC2 ADC
146.    TIM_OCStructInit( &TIM_OC_InitStructure );
147.    TIM_OC_InitStructure.TIM_Pulse =        511;
148.    TIM_OC2Init(TIM1, &TIM_OC_InitStructure);
149. 
150.    TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
151. 
152.#ifdef CC2
153.    TIM_ClearITPendingBit(TIM1, TIM_IT_CC2);
154.    TIM_ITConfig(TIM1, TIM_IT_CC2, ENABLE);
155.#endif
156. 
157. 
158. 
159.    TIM_Cmd(TIM1, ENABLE);
160. 
161.    TIM_CtrlPWMOutputs(TIM1, ENABLE);
162. 
163. 
164. 
165.    // ADC
166. 
167.    ADC_InitTypeDef ADC_InitStructure;
168. 
169.    ADC_StructInit(&ADC_InitStructure);
170. 
171.    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
172. 
173. 
174. 
175.#ifdef SOFTTRIGGER
176.    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
177.#else
178.    #ifdef CC1
179.    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
180.    #endif
181.    #ifdef CC2
182.    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC2;
183.    #endif
184.#endif
185.    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
186.    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
187.    ADC_InitStructure.ADC_NbrOfChannel = 1;
188.    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
189. 
190.    ADC_Init(ADC1, &ADC_InitStructure);
191. 
192.    ADC_RegularChannelConfig(
193.         ADC1,
194.         ADC_Channel_1,
195.         1,                         // The rank in the regular group sequencer. This parameter must be between 1 to 16.
196.         ADC_SampleTime_1Cycles5
197.         );
198. 
199.#ifndef SOFTTRIGGER
200.    ADC_ExternalTrigConvCmd(ADC1, ENABLE);
201.#endif
202. 
203.    ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
204.    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
205. 
206.    ADC_Cmd(ADC1, ENABLE);
207. 
208. 
209.    // calibrate
210.    ADC_ResetCalibration(ADC1);
211.    while(ADC_GetResetCalibrationStatus(ADC1));
212. 
213.    ADC_StartCalibration(ADC1);
214.    while(ADC_GetCalibrationStatus(ADC1));
215. 
216. 
217. 
218./*
219.#ifdef SOFTTRIGGER
220.    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
221.    //while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
222.    //ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
223.    //uint16_t value = ADC_GetConversionValue(ADC1);
224.#endif
225.*/
226. 
227. 
228.  while(1)
229.  {
230. 
231.  }
232.}
233. 
234. 
235. 
236.void ADC1_2_IRQHandler(void){
237. 
238. 
239.        if( ADC_GetITStatus(ADC1, ADC_IT_EOC) == SET){
240.            ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
241. 
242.           // GPIO_SetBits(GPIOB, GPIO_Pin_14);
243.            GPIO_ResetBits(GPIOB, GPIO_Pin_14);
244. 
245.        }else
246.        {
247.            asm("NOP");
248.        }
249.}
250. 
251. 
252. 
253.void TIM1_CC_IRQHandler(void)
254.{
255.    if( TIM_GetITStatus(TIM1, TIM_IT_CC1) == SET ){
256.        TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
257.        GPIO_SetBits(GPIOB, GPIO_Pin_14);
258. 
259.        #ifdef SOFTTRIGGER
260.        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
261.        #endif
262.    }
263. 
264. 
265.    if( TIM_GetITStatus(TIM1, TIM_IT_CC2) == SET ){
266.        TIM_ClearITPendingBit(TIM1, TIM_IT_CC2);
267.        GPIO_SetBits(GPIOB, GPIO_Pin_14);
268.       // GPIO_ResetBits(GPIOB, GPIO_Pin_14);
269. 
270.        #ifdef SOFTTRIGGER
271.        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
272.        #endif
273.    }
274.}
275. 
276. 
277.void NMI_Handler(void){asm("NOP");}                 //
278.void HardFault_Handler(void){while(1);}             //
279.void MemManage_Handler(void){asm("NOP");}           //
280.void BusFault_Handler(void){while(1);}              //
281.void UsageFault_Handler(void){while(1);}            //
282.void SVC_Handler(void){asm("NOP");}                 //
283.void DebugMon_Handler(void){asm("NOP");}            //
284.void PendSV_Handler(void){asm("NOP");}              //
285.void SysTick_Handler(void){asm("NOP");}             //
286.void Default_Handler(void){asm("NOP");}             //
287. 
288.// External Interrupts
289.void WWDG_IRQHandler(void){asm("NOP");}            // Window Watchdog
290.void PVD_IRQHandler(void){asm("NOP");}             // PVD through EXTI Line detect
291.void TAMPER_IRQHandler(void){asm("NOP");}          // Tamper
292.void RTC_IRQHandler(void){asm("NOP");}             // RTC
293.void FLASH_IRQHandler(void){asm("NOP");}           // Flash
294.void RCC_IRQHandler(void){asm("NOP");}             // RCC
295.void EXTI0_IRQHandler(void){asm("NOP");}           // EXTI Line 0
296.void EXTI1_IRQHandler(void){asm("NOP");}           // EXTI Line 1
297.void EXTI2_IRQHandler(void){asm("NOP");}           // EXTI Line 2
298.void EXTI3_IRQHandler(void){asm("NOP");}           // EXTI Line 3
299.void EXTI4_IRQHandler(void){asm("NOP");}           // EXTI Line 4
300.void DMA1_Channel1_IRQHandler(void){asm("NOP");}   // DMA1 Channel 1
301.void DMA1_Channel2_IRQHandler(void){asm("NOP");}   // DMA1 Channel 2
302.void DMA1_Channel3_IRQHandler(void){asm("NOP");}   // DMA1 Channel 3
303.void DMA1_Channel4_IRQHandler(void){asm("NOP");}   // DMA1 Channel 4
304.void DMA1_Channel5_IRQHandler(void){asm("NOP");}   // DMA1 Channel 5
305.void DMA1_Channel6_IRQHandler(void){asm("NOP");}   // DMA1 Channel 6
306.void DMA1_Channel7_IRQHandler(void){asm("NOP");}   // DMA1 Channel 7
307.//void ADC1_2_IRQHandler(void){asm("NOP");}          // ADC1 & ADC2
308.void USB_HP_CAN1_TX_IRQHandler(void){asm("NOP");}  // USB High Priority or CAN1 TX
309.void USB_LP_CAN1_RX0_IRQHandler(void){asm("NOP");} // USB Low  Priority or CAN1 RX0
310.void CAN1_RX1_IRQHandler(void){asm("NOP");}        // CAN1 RX1
311.void CAN1_SCE_IRQHandler(void){asm("NOP");}        // CAN1 SCE
312.void EXTI9_5_IRQHandler(void){asm("NOP");}         // EXTI Line 9..5
313.void TIM1_BRK_IRQHandler(void){asm("NOP");}        // TIM1 Break
314.void TIM1_UP_IRQHandler(void){asm("NOP");}         // TIM1 Update
315.void TIM1_TRG_COM_IRQHandler(void){asm("NOP");}    // TIM1 Trigger and Commutation
316.//void TIM1_CC_IRQHandler(void){asm("NOP");}         // TIM1 Capture Compare
317.void TIM2_IRQHandler(void){asm("NOP");}            // TIM2
318.void TIM3_IRQHandler(void){asm("NOP");}            // TIM3
319.void TIM4_IRQHandler(void){asm("NOP");}            // TIM4
320.void I2C1_EV_IRQHandler(void){asm("NOP");}         // I2C1 Event
321.void I2C1_ER_IRQHandler(void){asm("NOP");}         // I2C1 Error
322.void I2C2_EV_IRQHandler(void){asm("NOP");}         // I2C2 Event
323.void I2C2_ER_IRQHandler(void){asm("NOP");}         // I2C2 Error
324.void SPI1_IRQHandler(void){asm("NOP");}            // SPI1
325.void SPI2_IRQHandler(void){asm("NOP");}            // SPI2
326.void USART1_IRQHandler(void){asm("NOP");}          // USART1
327.void USART2_IRQHandler(void){asm("NOP");}          // USART2
328.void USART3_IRQHandler(void){asm("NOP");}          // USART3
329.void EXTI15_10_IRQHandler(void){asm("NOP");}       // EXTI Line 15..10
330.void RTCAlarm_IRQHandler(void){asm("NOP");}        // RTC Alarm through EXTI Line
331.void USBWakeUp_IRQHandler(void){asm("NOP");}       // USB Wakeup from suspend
332.void TIM8_BRK_IRQHandler(void){asm("NOP");}        // TIM8 Break
333.void TIM8_UP_IRQHandler(void){asm("NOP");}         // TIM8 Update
334.void TIM8_TRG_COM_IRQHandler(void){asm("NOP");}    // TIM8 Trigger and Commutation
335.void TIM8_CC_IRQHandler(void){asm("NOP");}         // TIM8 Capture Compare
336.void ADC3_IRQHandler(void){asm("NOP");}            // ADC3
337.void FSMC_IRQHandler(void){asm("NOP");}            // FSMC
338.void SDIO_IRQHandler(void){asm("NOP");}            // SDIO
339.void TIM5_IRQHandler(void){asm("NOP");}            // TIM5
340.void SPI3_IRQHandler(void){asm("NOP");}            // SPI3
341.void UART4_IRQHandler(void){asm("NOP");}           // UART4
342.void UART5_IRQHandler(void){asm("NOP");}           // UART5
343.void TIM6_IRQHandler(void){asm("NOP");}            // TIM6
344.void TIM7_IRQHandler(void){asm("NOP");}            // TIM7
345.void DMA2_Channel1_IRQHandler(void){asm("NOP");}   // DMA2 Channel1
346.void DMA2_Channel2_IRQHandler(void){asm("NOP");}   // DMA2 Channel2
347.void DMA2_Channel3_IRQHandler(void){asm("NOP");}   // DMA2 Channel3
348.void DMA2_Channel4_5_IRQHandler(void){asm("NOP");} // DMA2 Channel4 & Channel5

Attachments

Outcomes