STM32L052 寄存器上的模数转换器

STM32L052 Analog-to-digital converter on registers

我完成了模数转换器 [ADC] 的整个配置。当我在寄存器上工作时,我在某个地方犯了一个错误。以下是配置。在将 3.3 [V] 连接到项目中使用的引脚后,调试器通过 ST-Link 为它们分配一个值 0x00,表示失败。我做错了什么?

int main(void)
{
    RCC->APB2ENR |=  RCC_APB2ENR_ADC1EN; 
    //ADC attach

    RCC->IOPENR = RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN;      

    GPIOB->MODER = GPIO_MODER_MODE14_1 | GPIO_MODER_MODE15_1;
    //ADC_IN8 & ADC_IN9

    /* configure ADC */
    ADC1->ISR &= ~ADC_ISR_EOCAL & ~ADC_ISR_AWD;  
    //calibration flag, WATCHDOG flag

    ADC1->ISR |= ADC_ISR_ADRDY;
    ADC1->CR &= ~ADC_CR_ADSTART;  
    //The software is allowed to write smp bit only when ADSTART=0

    ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2;  
    //111: 160.5 ADC clock cycles

    ADC1->CFGR1 &= ~ADC_CFGR1_SCANDIR;  
    //Scan Direction 0: Upward scan (from CHSEL0 to CHSEL18)

    ADC1->CFGR1 |= ADC_CFGR1_AWDCH_3 | ADC_CFGR1_AWDEN | ADC_CFGR1_WAIT | ADC_CFGR1_CONT | ADC_CFGR1_AUTOFF; 
    //AWDCH[4:0]: Analog watchdog channel selection, Continuous Mode

    ADC->CCR |= ADC_CCR_LFMEN | ADC_CCR_VREFEN; 
    //Low Frequency Mode,  V REFINT enable

    ADC1->CHSELR |= ADC_CHSELR_CHSEL8 | ADC_CHSELR_CHSEL9 | ADC_CHSELR_CHSEL17; 
    //Channel Select 8 & 9  

    ADC1->IER |= ADC_IER_EOCIE | ADC_IER_EOSEQIE | ADC_IER_OVRIE | ADC_IER_EOSMPIE; 

    NVIC_EnableIRQ(ADC1_COMP_IRQn); 
    NVIC_SetPriority(ADC1_COMP_IRQn,3);

while(1)
    {
        ADC1->CR |= ADC_CR_ADEN;// | ADC_CR_ADSTART; 
        //Start the ADC conversion

        while ((ADC1->ISR & ADC_ISR_ADRDY)); 
        //Wait for stand up

        while ((ADC1->ISR & ADC_ISR_EOC)); 
        //wait for conversion flag

        ADC1->CR |= ADC_CR_ADCAL; 
        //End of the calibration

        delay(100); 

        uint16_t napiecie = ADC1->DR;
        uint8_t hi = ((napiecie >> 8) & 0xff);
        uint8_t lo = ((napiecie >> 0) & 0xff);

        //DISABLE ADC
        if ((ADC1->CR & ADC_CR_ADSTART) != 0){
            ADC1->CR |= ADC_CR_ADSTP;
            while ((ADC1->CR & ADC_CR_ADSTP) != 0);
        }
        ADC1->CR |= ADC_CR_ADDIS; //ADC disable command
        while ((ADC1->CR & ADC_CR_ADEN) != 0);
        ADC1->CR &= ~ADC_CR_ADSTART & ~ADC_CR_ADEN;
        //ADC1->CR &= ~ADC_ISR_ADRDY; //Clear the ADRDY bit in ADC_ISR register by programming this bit to 1 (optional).
    }

void ADC1_COMP_IRQHandler(void)
/* Interupt ADC */
{
    if(ADC1->ISR & ADC_ISR_EOC){
        uint16_t napiecie = ADC1->DR;
        uint8_t hi = ((napiecie >> 8) & 0xff);
        uint8_t lo = ((napiecie >> 0) & 0xff);
    }
}

你两次使用像

这样的行
ADC1->ISR &= ~ADC_ISR_EOCAL | ~ADC_ISR_AWD; 

这对我来说真的很奇怪,好像定义是 1 位宽,它们很可能是,它们的按位或是 0xFFFFFFFF(全是 F,没有 0)而且你没有改变 ISR 和 CR (稍后在代码中)完全没有!您需要使用按位与,不是吗?

ADC1->ISR &= ~ADC_ISR_EOCAL & ~ADC_ISR_AWD; 
...
ADC1->CR &= ~ADC_CR_ADSTART & ~ADC_CR_ADEN;

其他一些工作代码可在 https://electronics.stackexchange.com/questions/287073/get-internal-temperature-or-voltage-stm32l0/287162
https://github.com/ChristopherJD/STM32L053R8/blob/master/Intern_Project/ADC.c
https://www.digikey.com/eewiki/pages/viewpage.action?pageId=47644832