You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在STM32及STM32F103RB中开启ADC_1中断(含无库NVIC操作)

Hey there, let's tackle your two questions about enabling ADC1 interrupts on STM32—one covering general methods, and the other diving into raw register-level code for Keil uVision4 and STM32F103RB. Let's break it down:

1. How to Enable ADC1 Interrupt on STM32 Microcontrollers

If you're using ST's standard peripheral libraries (the most common approach), follow these steps:

  • Enable the ADC1 interrupt source
    First, tell the ADC peripheral to trigger an interrupt when a conversion completes (this uses the End of Conversion, EOC, flag). Use this library call:

    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
    
  • Turn on the ADC1 peripheral clock
    The ADC won't function if its clock is disabled. Enable it via the RCC register:

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    
  • Configure the NVIC to handle ADC1 interrupts
    The Nested Vector Interrupt Controller (NVIC) needs to be set up to prioritize and route the ADC1 interrupt. Here's how to initialize it:

    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = ADC1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; // Adjust based on your system needs
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
    
  • Implement the Interrupt Service Routine (ISR)
    Finally, write the ISR to handle the interrupt. Make sure the function name matches the one defined in your startup file (this is critical—Keil relies on this name to map the interrupt):

    void ADC1_IRQHandler(void)
    {
        if(ADC_GetITStatus(ADC1, ADC_IT_EOC) != RESET)
        {
            // Example: Read the converted ADC value
            uint16_t adcResult = ADC_GetConversionValue(ADC1);
            
            // Your custom logic here (e.g., store the value, trigger an action)
            
            // Clear the interrupt flag to avoid repeated triggers
            ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
        }
    }
    
2. Enable ADC1 Interrupt via NVIC (No Library Functions, Keil uVision4, STM32F103RB)

If you want to avoid library functions and work directly with registers, here's the step-by-step raw code. Double-check register addresses against the STM32F103RB reference manual—this ensures you're targeting the correct hardware:

  • Enable ADC1 peripheral clock
    The RCC_APB2ENR register (address 0x40021018) controls APB2 peripheral clocks. Set bit 9 to enable ADC1:

    *(volatile uint32_t*)0x40021018 |= (1 << 9);
    
  • Enable ADC1 EOC interrupt
    The ADC_CR1 register (address 0x40012404) manages ADC interrupts. Set bit 5 to enable the EOC interrupt:

    *(volatile uint32_t*)0x40012404 |= (1 << 5);
    
  • Configure NVIC for ADC1 interrupt
    ADC1 uses IRQ number 18 (confirm this in the STM32F103RB datasheet). We need to enable the interrupt and set its priority:

    1. Enable the interrupt in NVIC_ISER0 (address 0xE000E100—this register controls the first 32 IRQs):
      *(volatile uint32_t*)0xE000E100 |= (1 << 18);
      
    2. Set interrupt priority (optional but recommended). Use NVIC_IPR4 (address 0xE000E410), which controls IRQs 16-19. For IRQ 18, we use bits 23:20 (each IRQ gets 4 priority bits). Here's how to set preemption/sub priority to 0:
      // Clear existing priority bits
      *(volatile uint32_t*)0xE000E410 &= ~(0xF << 20);
      // Set priority (adjust the 0x0 value if you need different priority levels)
      *(volatile uint32_t*)0xE000E410 |= (0x0 << 20);
      
  • Write the raw ISR
    Just like with libraries, the ISR name must match the startup file's vector table entry. Here's the bare-bones version:

    void ADC1_IRQHandler(void)
    {
        // Check if the EOC flag is set (ADC_SR register, address 0x40012400, bit 1)
        if(*(volatile uint32_t*)0x40012400 & (1 << 1))
        {
            // Read the conversion result from ADC_DR (address 0x4001240C)
            uint16_t adcResult = *(volatile uint16_t*)0x4001240C;
            
            // Your custom handling logic here
            
            // Clear the EOC flag (writing 0 to bit 1, or reading DR also clears it)
            *(volatile uint32_t*)0x40012400 &= ~(1 << 1);
        }
    }
    

A quick note: When working with raw registers, always cross-reference the STM32F103RB reference manual to confirm register addresses and bit positions—small hardware variations can trip you up!

内容的提问来源于stack exchange,提问作者Muzahir Hussain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:16:13