我有一个 NUCLEO-F429ZI 板,我试图让 ADC1 在 tiM2 触发时(每秒)转换一个通道(通道 3)。
由于我没有示波器,我想测量转换时间——以确保一切配置正确——使用 Segger SystemView。
使用下面的代码,我将 ADCCLK 设置为 22.5 MHz 并将采样时间设置为 480 个时钟周期,因此我预计 ADC 中断将在定时器中断后大约 22 µs 发生。
不过,我看到的是 ADC 中断 (ISR34) 在定时器 ISR (ISR 44) 之后 2.6 µs 发生(见屏幕截图)。
问:为什么ADC中断这么快?
附件中的 ZIP 文件是完整的 Segger Studio 项目,可以编译了。
这是完整的代码:
- /*********************************************************************
- * SEGGER Microcontroller GmbH *
- * The Embedded Experts *
- **********************************************************************
- * *
- * (c) 2014 - 2020 SEGGER Microcontroller GmbH *
- * *
- * www.segger.com Support: support@segger.com *
- * *
- **********************************************************************
- * *
- * All rights reserved. *
- * *
- * Redistribution and use in source and binary forms, with or *
- * without modification, are permitted provided that the following *
- * conditions are met: *
- * *
- * - Redistributions of source code must retain the above copyright *
- * notice, this list of conditions and the following disclaimer. *
- * *
- * - Neither the name of SEGGER Microcontroller GmbH *
- * nor the names of its contributors may be used to endorse or *
- * promote products derived from this software without specific *
- * prior written permission. *
- * *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
- * DISCLAIMED. *
- * IN NO EVENT SHALL SEGGER Microcontroller GmbH BE LIABLE FOR *
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
- * DAMAGE. *
- * *
- **********************************************************************
- -------------------------- END-OF-HEADER -----------------------------
- File : main.c
- Purpose : Generic application start
- */
- #include <STM32f4xx.h>
- #include "SEGGER_SYSVIEW.h"
- void ClockInit(void)
- {
- uint32_t timeout = 1000000;
- // enable flash prefetch
- FLASH->ACR |= FLASH_ACR_PRFTEN;
- // set 5 wait states (needed for high PLL frequency)
- FLASH->ACR &= ~FLASH_ACR_LATENCY_Msk;
- FLASH->ACR |= FLASH_ACR_LATENCY_5WS;
- do
- {
- timeout--;
- } while (((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != FLASH_ACR_LATENCY_5WS) && (timeout > 0));
- // switch on external clock, bypass HSE with it and wait for clock to be ready
- RCC->CR |= (RCC_CR_HSEON | RCC_CR_HSEBYP);
- timeout = 1000000;
- do
- {
- timeout--;
- } while (((RCC->CR & RCC_CR_HSERDY_Msk) != RCC_CR_HSERDY) && (timeout > 0));
- // configure (HSE as clock source, M = 4, N = 180, P = 2), enable and wait for PLL
- RCC->PLLCFGR = (RCC_PLLCFGR_PLLSRC_HSE | (4 << RCC_PLLCFGR_PLLM_Pos) | (180 << RCC_PLLCFGR_PLLN_Pos));
- RCC->CR |= RCC_CR_PLLON;
- timeout = 1000000;
- do
- {
- timeout--;
- } while (((RCC->CR & RCC_CR_PLLRDY_Msk) != RCC_CR_PLLRDY) && (timeout > 0));
- // configure rest of clock tree
- RCC->CFGR &= ~(RCC_CFGR_PPRE2_Msk | RCC_CFGR_PPRE1_Msk | RCC_CFGR_HPRE_Msk);
- RCC->CFGR |= (RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_HPRE_DIV1);
- // set PLL as clock source and wait until clock is ready
- RCC->CFGR &= ~(RCC_CFGR_SW_Msk);
- RCC->CFGR |= RCC_CFGR_SW_PLL;
- timeout = 1000000;
- do
- {
- timeout--;
- } while (((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL) && (timeout > 0));
- SystemCoreClockUpdate();
- // enable GPIOA, ADC1 and TIM2 clocks
- RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
- RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
- RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
- }
- void TimerInit(void)
- {
- // counter direction down, generate update event only on underflow
- TIM2->CR1 |= (TIM_CR1_DIR | TIM_CR1_URS);
- // set update event as trigger source
- TIM2->CR2 &= ~TIM_CR2_MMS_Msk;
- TIM2->CR2 |= TIM_CR2_MMS_1;
- // enable update interrupt
- TIM2->DIER |= TIM_DIER_UIE;
- // set timer and reload value for update generation every 1000 ms
- TIM2->ARR = TIM2->CNT = 90000000;
- }
- void TimerStart(void)
- {
- TIM2->CR1 |= TIM_CR1_CEN;
- }
- void AdcInit(void)
- {
- // PA3 as analog input
- GPIOA->MODER |= GPIO_MODER_MODE3;
- // set clock prescaler to 4 -> 22,5 MHz
- ADC123_COMMON->CCR |= ADC_CCR_ADCPRE_0;
- // enable timer 2 trigger event as start trigger on rising edge and generate EOC interrupt after each conversion
- ADC1->CR2 |= (ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTEN_0 | ADC_CR2_EOCS);
- // set 480 cycles sample time for channel 3
- ADC1->SMPR2 |= ADC_SMPR2_SMP3;
- // set channel 3 as first (any only) regular channel
- ADC1->SQR3 |= (ADC_SQR3_SQ1_2 | ADC_SQR3_SQ1_1);
- // enable EOC interrupt
- ADC1->CR1 |= ADC_CR1_EOCIE;
- // enable ADC
- ADC1->CR2 |= ADC_CR2_ADON;
- }
- void InterruptInit(void)
- {
- // Timer 2
- NVIC_SetPriority(TIM2_IRQn, 3);
- NVIC_ClearPendingIRQ(TIM2_IRQn);
- NVIC_EnableIRQ(TIM2_IRQn);
- // ADC
- NVIC_SetPriority(ADC_IRQn, 2);
- NVIC_ClearPendingIRQ(ADC_IRQn);
- NVIC_EnableIRQ(ADC_IRQn);
- }
- void TIM2_IRQHandler(void)
- {
- SEGGER_SYSVIEW_RecordEnterISR();
- NVIC_ClearPendingIRQ(TIM2_IRQn);
- TIM2->SR &= ~TIM_SR_UIF;
- }
- void ADC_IRQHandler(void)
- {
- uint16_t Value;
- SEGGER_SYSVIEW_RecordEnterISR();
- Value = ADC1->DR;
- NVIC_ClearPendingIRQ(ADC_IRQn);
- }
- int main(void)
- {
- ClockInit();
- SEGGER_SYSVIEW_Conf();
- TimerInit();
- AdcInit();
- InterruptInit();
- TimerStart();
- while(1);
- }
- /*************************** End of file ****************************/
0
|
1个回答
|
|
|