STM32L052寄存器上的模数转换器

时间:2019-01-30 13:39:19

标签: c stm32 processor bare-metal

我经历了模数转换器[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);
    }
}

1 个答案:

答案 0 :(得分:3)

两次使用

ADC1->ISR &= ~ADC_ISR_EOCAL | ~ADC_ISR_AWD; 

这对我来说真的很奇怪,好像定义是1位宽,它们很可能是,它们的按位OR为0xFFFFFFFF(全F,不为0),并且您没有更改ISR和CR(以后)在代码中)!您需要使用按位AND,不是吗?

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