cancel
Showing results for 
Search instead for 
Did you mean: 

H7 read temperature from ADC

Pilous Droip
Senior

H friends,

I'm trying to read adc3, a temperature sensor from stm32h753. But something is wrong. Because I didn't get any interruptions. Can anyone help?

void MX_ADC3_Init(void) {
    LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_CLKP);
 
    /* Peripheral clock enable */
    LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_ADC3);
 
    if (LL_ADC_IsDeepPowerDownEnabled(ADC3) != 0UL)
        LL_ADC_DisableDeepPowerDown(ADC3);
 
    if (LL_ADC_IsInternalRegulatorEnabled(ADC3) == 0UL) {
        LL_ADC_EnableInternalRegulator(ADC3);
        __IO uint32_t wait_loop_index = 0UL;
        wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US / 10UL) * (SystemCoreClock / (100000UL * 2UL))) + 1000;
        while (wait_loop_index != 0UL) {
            wait_loop_index--;
        }
    }
 
    LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(ADC3), LL_ADC_CLOCK_ASYNC_DIV2);
    LL_ADC_SetResolution(ADC3, LL_ADC_RESOLUTION_16B);
    LL_ADC_REG_SetSequencerLength(ADC3, LL_ADC_REG_SEQ_SCAN_ENABLE_10RANKS);
    LL_ADC_SetLowPowerMode(ADC3, LL_ADC_LP_MODE_NONE);
    LL_ADC_REG_SetContinuousMode(ADC3, LL_ADC_REG_CONV_CONTINUOUS);
    LL_ADC_REG_SetSequencerDiscont(ADC3, LL_ADC_REG_SEQ_DISCONT_DISABLE);
    LL_ADC_REG_SetTriggerSource(ADC3, LL_ADC_REG_TRIG_SOFTWARE);
    LL_ADC_REG_SetDataTransferMode(ADC3, LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
    LL_ADC_REG_SetOverrun(ADC3, LL_ADC_REG_OVR_DATA_OVERWRITTEN);
    LL_ADC_SetOverSamplingScope(ADC3, LL_ADC_OVS_DISABLE);
 
    LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_TEMPSENSOR);
    LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SAMPLINGTIME_387CYCLES_5);
    LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SINGLE_ENDED);
 
    LL_ADC_SetOffset(ADC3, LL_ADC_OFFSET_1, LL_ADC_CHANNEL_TEMPSENSOR, 0);
 
    LL_ADC_EnableIT_EOS(ADC3); // End of regular sequence of conversions IR enable
    LL_ADC_EnableIT_EOC(ADC3); // End of conversion IR enable
}
 
void init_DMA_ADC(void) {
 
    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
 
    LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_STREAM_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
    LL_DMA_DisableFifoMode(DMA1, LL_DMA_STREAM_1);
    LL_DMA_SetMemoryBurstxfer(DMA1, LL_DMA_STREAM_1, LL_DMA_MBURST_SINGLE);
    LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_1, LL_DMA_MDATAALIGN_HALFWORD);
    LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MEMORY_INCREMENT);
    LL_DMA_SetMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MODE_CIRCULAR);
    LL_DMA_SetPeriphBurstxfer(DMA1, LL_DMA_STREAM_1, LL_DMA_PBURST_SINGLE);
    LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_1, LL_DMA_PDATAALIGN_HALFWORD);
    LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_PERIPH_NOINCREMENT);
    LL_DMA_SetPeriphRequest(DMA1, LL_DMA_STREAM_1, LL_DMAMUX1_REQ_ADC3);
    LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_1, LL_DMA_PRIORITY_HIGH);
 
    LL_DMA_SetPeriphAddress(DMA1, LL_DMA_STREAM_1, (uint32_t) (&ADC3->DR));
    LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_1, (uint32_t)tempSensor);
 
    LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_1);
}
 
void enable_adc_interrupt(void) {
 
    NVIC_SetPriority(ADC3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
    NVIC_EnableIRQ(ADC3_IRQn);
}
 
void enable_dma_interrupt(void) {
 
    NVIC_SetPriority(DMA1_Stream1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
    NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}
 
void enable_ADC(void)
{
    LL_ADC_Enable(ADC3);
    while (LL_ADC_IsEnabled(ADC3) == 0UL);
}
 
void start_ADC(uint32_t size)
{
    LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_1, size);
    LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_1);
    LL_ADC_REG_StartConversion(ADC3);
}
 
void DMA1_Stream1_IRQHandler(void) {
    if (LL_DMA_IsActiveFlag_TC1(DMA1)) {
        LL_DMA_ClearFlag_TC1(DMA1);
 
        dma_flag = 1;
    }
}
 
void ADC3_IRQHandler(void) {
 
    if(LL_ADC_IsActiveFlag_EOC(ADC3) || LL_ADC_IsActiveFlag_EOS(ADC3) ){
 
        LL_ADC_ClearFlag_EOC(ADC3);
        LL_ADC_ClearFlag_EOS(ADC3);
 
        adc_flag = 1;
    }
}

i call it in my main:

MX_ADC3_Init();
init_DMA_ADC();
enable_adc_interrupt();
enable_dma_interrupt();
enable_ADC();
start_ADC(2); // 2 for 2x half word

And in while ufnction I have condition:

if ((adc_flag == 1) || (dma_flag == 1)){
 
    adc_flag = 0;
    dma_flag = 0;
 
    // breakpoint here
}

my studing material is datasheet, reference manual and internet...

https://www.st.com/resource/en/datasheet/stm32h753ii.pdf

https://www.st.com/resource/en/reference_manual/dm00314099-stm32h742-stm32h743-753-and-stm32h750-value-line-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf

25 REPLIES 25

Yes, it was disabled. Now I enable it, by this line:

LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC3), LL_ADC_PATH_INTERNAL_TEMPSENSOR);

0693W00000GYSSUQA5.png 

But I am not sure, that measure adc3 is fine. I'll try to do some measurements.👍

I started measuring. I measured for about 15 minutes. It looks good. Tomorrow I will continue.

@Gwenole BROCHARD​  Thank you for your advice.

0693W00000GYStqQAH.png

I measured the temperature on the MCU for about 8 hours. It fluctuated within 2 ° C. I think that's good. With the help of @Gwenole BROCHARD​  there are source codes.

Now that I have a skeleton, I'm going to try to measure more than one channel. 😁

volatile int32_t dma_flag = 0;
volatile int32_t adc_flag = 0;
 
// set sram1 in linker :)
#define DMA_BUFFER __attribute__ ((section (".sram1"),aligned(32)))
 
// data save in sram1
volatile DMA_BUFFER uint16_t tempSensor[2] = { 0 };
 
void ADC_init(void) {
    // clock enable in other init function
    //LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLL3R);
 
    /* Peripheral clock enable */
    LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_ADC3);
 
    if (LL_ADC_IsDeepPowerDownEnabled(ADC3) != 0UL)
        LL_ADC_DisableDeepPowerDown(ADC3);
 
    if (LL_ADC_IsInternalRegulatorEnabled(ADC3) == 0UL) {
        LL_ADC_EnableInternalRegulator(ADC3);
        __IO uint32_t wait_loop_index = 0UL;
        wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US / 10UL) * (SystemCoreClock / (100000UL * 2UL))) + 1000;
        while (wait_loop_index != 0UL) {
            wait_loop_index--;
        }
    }
 
    LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC3), LL_ADC_PATH_INTERNAL_TEMPSENSOR);
    LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(ADC3), LL_ADC_CLOCK_ASYNC_DIV1);
    LL_ADC_SetResolution(ADC3, LL_ADC_RESOLUTION_12B);
    LL_ADC_REG_SetSequencerLength(ADC3, LL_ADC_REG_SEQ_SCAN_DISABLE);
    LL_ADC_SetLowPowerMode(ADC3, LL_ADC_LP_MODE_NONE);
    LL_ADC_REG_SetContinuousMode(ADC3, LL_ADC_REG_CONV_CONTINUOUS);
    LL_ADC_REG_SetSequencerDiscont(ADC3, LL_ADC_REG_SEQ_DISCONT_DISABLE);
    LL_ADC_REG_SetTriggerSource(ADC3, LL_ADC_REG_TRIG_SOFTWARE);
    LL_ADC_REG_SetDataTransferMode(ADC3, LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
    LL_ADC_REG_SetOverrun(ADC3, LL_ADC_REG_OVR_DATA_OVERWRITTEN);
    LL_ADC_SetOverSamplingScope(ADC3, LL_ADC_OVS_DISABLE);
 
    LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_TEMPSENSOR);
    LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SAMPLINGTIME_387CYCLES_5);
    LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SINGLE_ENDED);
 
    LL_ADC_SetOffset(ADC3, LL_ADC_OFFSET_1, LL_ADC_CHANNEL_TEMPSENSOR, 0);
 
    LL_ADC_EnableIT_EOS(ADC3); // End of regular sequence of conversions IR enable
    LL_ADC_EnableIT_EOC(ADC3); // End of conversion IR enable
}
 
void DMA_init(void) {
 
    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
 
    LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_STREAM_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
    LL_DMA_DisableFifoMode(DMA1, LL_DMA_STREAM_1);
    LL_DMA_SetMemoryBurstxfer(DMA1, LL_DMA_STREAM_1, LL_DMA_MBURST_SINGLE);
    LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_1, LL_DMA_MDATAALIGN_HALFWORD);
    LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MEMORY_INCREMENT);
    LL_DMA_SetMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MODE_CIRCULAR);
    LL_DMA_SetPeriphBurstxfer(DMA1, LL_DMA_STREAM_1, LL_DMA_PBURST_SINGLE);
    LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_1, LL_DMA_PDATAALIGN_HALFWORD);
    LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_PERIPH_NOINCREMENT);
    LL_DMA_SetPeriphRequest(DMA1, LL_DMA_STREAM_1, LL_DMAMUX1_REQ_ADC3);
    LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_1, LL_DMA_PRIORITY_HIGH);
 
    LL_DMA_SetPeriphAddress(DMA1, LL_DMA_STREAM_1, (uint32_t) (&ADC3->DR));
    LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_1, (uint32_t) tempSensor);
 
    LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_1);
}
 
void ADC_EnableInterrupt(void) {
 
    NVIC_SetPriority(ADC3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1, 0));
    NVIC_EnableIRQ(ADC3_IRQn);
}
 
void DMA_EnableInterrupt(void) {
 
    NVIC_SetPriority(DMA1_Stream1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1, 0));
    NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}
 
int32_t ADC_enable(void) {
    LL_ADC_Enable(ADC3);
    while (LL_ADC_IsEnabled(ADC3) == 0UL)
        ;
 
    LL_ADC_StartCalibration(ADC3, LL_ADC_CALIB_OFFSET, LL_ADC_SINGLE_ENDED);
 
    int32_t timeout = 0xFFFFFF;
 
    while ((LL_ADC_IsCalibrationOnGoing(ADC3) == 0UL) && (--timeout >= 0))
        ;
 
    return timeout;
}
 
void ADC_start(uint32_t size) {
    LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_1, size);
    LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_1);
    LL_ADC_REG_StartConversion(ADC3);
}
 
 
uint32_t GetMCUTemperature(uint32_t raw){
    return __LL_ADC_CALC_TEMPERATURE(3300, raw, LL_ADC_RESOLUTION_12B);
}
 
void DMA1_Stream1_IRQHandler(void) {
    if (LL_DMA_IsActiveFlag_TC1(DMA1)) {
        LL_DMA_ClearFlag_TC1(DMA1);
 
        dma_flag = 1;
    }
}
 
void ADC3_IRQHandler(void) {
 
    if (LL_ADC_IsActiveFlag_EOC(ADC3)) {
        LL_ADC_ClearFlag_EOC(ADC3);
 
        adc_flag = 1;
    }
 
    if (LL_ADC_IsActiveFlag_EOS(ADC3)) {
        LL_ADC_ClearFlag_EOS(ADC3);
 
        adc_flag = 2;
    }
}

0693W00000GYWbLQAX.png

Pilous Droip
Senior

So today I added another channel. And I think adc is working badly in my setup.

Here is complete code:

Clock source

PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    PeriphClkInitStruct.PLL3.PLL3M = 4;
    PeriphClkInitStruct.PLL3.PLL3N = 100;
    PeriphClkInitStruct.PLL3.PLL3P = 2;
    PeriphClkInitStruct.PLL3.PLL3Q = 2;
    PeriphClkInitStruct.PLL3.PLL3R = 4;
    PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_1;
    PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
    PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL3; // R output = ((8MHz / 4) * 100) / 4 = 50MHz

enable ADC

void ADC_init(void) {
    //LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLL3R);
 
    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
 
    /* PF10 ------> ADC3_INP6 */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    LL_GPIO_Init(GPIOF, &GPIO_InitStruct);
 
    LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_ADC12);
    LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_ADC3);
    __NOP();__NOP();__NOP();__NOP();
    LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_ADC12);
    LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_ADC3);
 
    /* Peripheral clock enable */
    LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_ADC3);
 
    if (LL_ADC_IsDeepPowerDownEnabled(ADC3) != 0UL)
        LL_ADC_DisableDeepPowerDown(ADC3);
 
    if (LL_ADC_IsInternalRegulatorEnabled(ADC3) == 0UL) {
        LL_ADC_EnableInternalRegulator(ADC3);
        __IO uint32_t wait_loop_index = 0UL;
        wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US / 10UL) * (SystemCoreClock / (100000UL * 2UL))) + 1000;
        while (wait_loop_index != 0UL) {
            wait_loop_index--;
        }
    }
 
    LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(ADC3), LL_ADC_CLOCK_ASYNC_DIV1);
    LL_ADC_SetBoostMode(ADC3, LL_ADC_BOOST_MODE_50MHZ);
 
    LL_ADC_SetResolution(ADC3, LL_ADC_RESOLUTION_12B);
    LL_ADC_SetLowPowerMode(ADC3, LL_ADC_LP_MODE_NONE);
 
    LL_ADC_REG_SetTriggerSource(ADC3, LL_ADC_REG_TRIG_SOFTWARE);
    LL_ADC_REG_SetSequencerLength(ADC3, LL_ADC_REG_SEQ_SCAN_ENABLE_2RANKS);
    LL_ADC_REG_SetSequencerDiscont(ADC3, LL_ADC_REG_SEQ_DISCONT_DISABLE);
    LL_ADC_REG_SetContinuousMode(ADC3, LL_ADC_REG_CONV_CONTINUOUS);             
    LL_ADC_REG_SetDataTransferMode(ADC3, LL_ADC_REG_DMA_TRANSFER_UNLIMITED);    
    LL_ADC_REG_SetOverrun(ADC3, LL_ADC_REG_OVR_DATA_OVERWRITTEN);               
    LL_ADC_SetOverSamplingScope(ADC3, LL_ADC_OVS_DISABLE);
 
    LL_ADC_SetMultimode(__LL_ADC_COMMON_INSTANCE(ADC3), LL_ADC_MULTI_INDEPENDENT);
 
    LL_ADC_INJ_SetQueueMode(ADC3, LL_ADC_INJ_QUEUE_DISABLE);
    // turn on all (PDF page 1042 RM0433 Rev7 and for use in future)
    // The software is allowed to write this bits only when the ADCs are disabled (ADCAL=0, JADSTART=0, ADSTART=0, ADSTP=0, ADDIS=0 and ADEN=0).
    LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC3), LL_ADC_PATH_INTERNAL_VREFINT | LL_ADC_PATH_INTERNAL_TEMPSENSOR | LL_ADC_PATH_INTERNAL_VBAT);
 
    LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_6);
    LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_6, LL_ADC_SAMPLINGTIME_8CYCLES_5);
    LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_6, LL_ADC_SINGLE_ENDED);
 
    LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_TEMPSENSOR);
    LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SAMPLINGTIME_810CYCLES_5);
    LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SINGLE_ENDED);
 
    LL_ADC_EnableIT_EOS(ADC3); // End of regular sequence of conversions IR enable
    LL_ADC_EnableIT_EOC(ADC3); // End of conversion IR enable
}

Enable DMA

void DMA_init(void) {
 
    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
 
    LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_STREAM_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
    LL_DMA_DisableFifoMode(DMA1, LL_DMA_STREAM_1);
    LL_DMA_SetMemoryBurstxfer(DMA1, LL_DMA_STREAM_1, LL_DMA_MBURST_SINGLE);
    LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_1, LL_DMA_MDATAALIGN_HALFWORD);
    LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MEMORY_INCREMENT);
    LL_DMA_SetMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MODE_CIRCULAR);
    LL_DMA_SetPeriphBurstxfer(DMA1, LL_DMA_STREAM_1, LL_DMA_PBURST_SINGLE);
    LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_1, LL_DMA_PDATAALIGN_HALFWORD);
    LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_PERIPH_NOINCREMENT);
    LL_DMA_SetPeriphRequest(DMA1, LL_DMA_STREAM_1, LL_DMAMUX1_REQ_ADC3);
    LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_1, LL_DMA_PRIORITY_HIGH);
 
    LL_DMA_SetPeriphAddress(DMA1, LL_DMA_STREAM_1, LL_ADC_DMA_GetRegAddr(ADC3, LL_ADC_DMA_REG_REGULAR_DATA));
    LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_1, (uint32_t) tempSensor);
 
    LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_1);
}

Enable interrupts:

void ADC_EnableInterrupt(void) {
    NVIC_SetPriority(ADC3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1, 0));
    NVIC_EnableIRQ(ADC3_IRQn);
}
 
void DMA_EnableInterrupt(void) {
    NVIC_SetPriority(DMA1_Stream1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1, 0));
    NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}

Enable ADC and start ADC

int32_t ADC_enable(void) {
    LL_ADC_Enable(ADC3);
    while (LL_ADC_IsEnabled(ADC3) == 0UL)
        ;
 
    LL_ADC_StartCalibration(ADC3, LL_ADC_CALIB_OFFSET, LL_ADC_SINGLE_ENDED);
 
    int32_t timeout = 0xFFFFFF;
 
    while ((LL_ADC_IsCalibrationOnGoing(ADC3) == 0UL) && (--timeout >= 0))
        ;
 
    return timeout;
}
 
void ADC_start(void) {
    LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_1, (uint32_t) (sizeof(tempSensor) / sizeof(uint16_t)));
    LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_1);
    LL_ADC_REG_StartConversion(ADC3);
}

And convert values from adc

uint32_t BSP_GetMCUTemperature(void){
    return __LL_ADC_CALC_TEMPERATURE(3300, tempSensor[1], LL_ADC_RESOLUTION_12B);
}
 
uint32_t GetPF10Voltage(void){
    return __LL_ADC_CALC_DATA_TO_VOLTAGE(3300, tempSensor[0], LL_ADC_RESOLUTION_12B);
}

ISR

void DMA1_Stream1_IRQHandler(void) {
    if (LL_DMA_IsActiveFlag_TC1(DMA1)) {
        LL_DMA_ClearFlag_TC1(DMA1);
    }
}
 
void ADC3_IRQHandler(void) {
 
    if (LL_ADC_IsActiveFlag_EOC(ADC3)) {
        LL_ADC_ClearFlag_EOC(ADC3);
    }
 
    if (LL_ADC_IsActiveFlag_EOS(ADC3)) {
        LL_ADC_ClearFlag_EOS(ADC3);
    }
}

I have a potentiometer on the PF10 pin. But the value does not change when it changes position.

Now I test it on: NUCLEO-H743ZI2 (NUH743ZI$AT1).

Pilous Droip
Senior

I'm rewriting my code ... But it's worse than before. :face_with_steam_from_nose:

I create one init function:

void ADC_init(void) {LL_DMA_InitTypeDef ADC_Config_DMA;
    LL_GPIO_InitTypeDef ADC_Config_GPIO;
    LL_ADC_InitTypeDef ADC_Config_Init;
    LL_ADC_CommonInitTypeDef ADC_Config_CommonInit;
    LL_ADC_REG_InitTypeDef ADC_Config_REG;
 
    LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOF);
    LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_ADC3);
    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
 
    LL_ADC_StructInit(&ADC_Config_Init);
    LL_ADC_CommonStructInit(&ADC_Config_CommonInit);
    LL_ADC_REG_StructInit(&ADC_Config_REG);
    LL_GPIO_StructInit(&ADC_Config_GPIO);
    LL_DMA_StructInit(&ADC_Config_DMA);
 
    //Configure GPIOF
    ADC_Config_GPIO.Mode = LL_GPIO_MODE_ANALOG;
    ADC_Config_GPIO.Pin = LL_GPIO_PIN_10;
    ADC_Config_GPIO.Pull = LL_GPIO_PULL_NO;
    ADC_Config_GPIO.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
    LL_GPIO_Init(GPIOF, &ADC_Config_GPIO);
 
    ADC_Config_DMA.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
    ADC_Config_DMA.FIFOMode = LL_DMA_FIFOMODE_DISABLE;
    ADC_Config_DMA.MemBurst = LL_DMA_MBURST_SINGLE;
    ADC_Config_DMA.MemoryOrM2MDstAddress = (uint32_t) tempSensor;
    ADC_Config_DMA.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD;
    ADC_Config_DMA.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
    ADC_Config_DMA.Mode = LL_DMA_MODE_CIRCULAR;
    ADC_Config_DMA.NbData = ADC3_NUM_CHANNEL;   // now set 2 for PF10 and internal temp
    ADC_Config_DMA.PeriphBurst = LL_DMA_PBURST_SINGLE;
    ADC_Config_DMA.PeriphOrM2MSrcAddress = (uint32_t) &ADC3->DR;
    ADC_Config_DMA.PeriphOrM2MSrcDataSize = LL_DMA_MDATAALIGN_HALFWORD;
    ADC_Config_DMA.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
    ADC_Config_DMA.PeriphRequest = LL_DMAMUX1_REQ_ADC3;
    ADC_Config_DMA.Priority = LL_DMA_PRIORITY_LOW;
    //Interrupt: DMA
    LL_DMA_Init(DMA1, LL_DMA_STREAM_1, &ADC_Config_DMA);
 
    ADC_Config_Init.LeftBitShift = LL_ADC_LEFT_BIT_SHIFT_NONE;
    ADC_Config_Init.LowPowerMode = LL_ADC_LP_MODE_NONE;
    ADC_Config_Init.Resolution = LL_ADC_RESOLUTION_16B;
    LL_ADC_Init(ADC3, &ADC_Config_Init);
 
    ADC_Config_CommonInit.CommonClock = LL_ADC_CLOCK_ASYNC_DIV1;
    ADC_Config_CommonInit.MultiDMATransfer = LL_ADC_MULTI_REG_DMA_EACH_ADC;
    ADC_Config_CommonInit.Multimode = LL_ADC_MULTI_INDEPENDENT;
    LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC3), &ADC_Config_CommonInit);
 
    ADC_Config_REG.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS;
    ADC_Config_REG.DataTransferMode = LL_ADC_REG_DMA_TRANSFER_UNLIMITED;
    ADC_Config_REG.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN;
    ADC_Config_REG.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
    ADC_Config_REG.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_2RANKS;
    ADC_Config_REG.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
    LL_ADC_REG_Init(ADC3, &ADC_Config_REG);
 
    LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_6);
    LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_TEMPSENSOR);
 
    LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_6, LL_ADC_SAMPLINGTIME_810CYCLES_5);
    LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SAMPLINGTIME_810CYCLES_5);
 
    LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_6, LL_ADC_SINGLE_ENDED);
 
    LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC3), LL_ADC_PATH_INTERNAL_TEMPSENSOR | LL_ADC_PATH_INTERNAL_VREFINT | LL_ADC_PATH_INTERNAL_VBAT);
    LL_ADC_SetBoostMode(ADC3, LL_ADC_BOOST_MODE_25MHZ); // Boost mode is configured for 20Mhz < frequency <= 25Mhz
    LL_ADC_SetLowPowerMode(ADC3, LL_ADC_LP_MODE_NONE);
 
    LL_RCC_PLL3_SetM(4);
    LL_RCC_PLL3_SetN(100);
    LL_RCC_PLL3_SetP(2);
    LL_RCC_PLL3_SetQ(2);
    LL_RCC_PLL3_SetR(9);
    LL_RCC_PLL3_SetFRACN(0);    // ((8.000.000 / 4) x 100) / 9 = 22,222222 MHz
    LL_RCC_PLL3_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_8_16);
    LL_RCC_PLL3_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
    LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLL3R);
    LL_RCC_PLL3FRACN_Enable();
    LL_RCC_PLL3R_Enable();
    LL_RCC_PLL3_Enable();
 
    LL_ADC_EnableIT_EOS(ADC3); // End of regular sequence of conversions IR enable
    LL_ADC_EnableIT_EOC(ADC3); // End of conversion IR enable
    LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_1);
 
    LL_ADC_StartCalibration(ADC3, LL_ADC_CALIB_OFFSET, LL_ADC_SINGLE_ENDED);
    while (LL_ADC_IsCalibrationOnGoing(ADC3))
        ;
 
    LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_1);
    LL_ADC_DisableDeepPowerDown(ADC3);
    LL_ADC_EnableInternalRegulator(ADC3);
    LL_ADC_ClearFlag_ADRDY(ADC3);
    LL_ADC_Enable(ADC3);
    while (LL_ADC_IsActiveFlag_ADRDY(ADC3) == 0)
        ;
    LL_ADC_ClearFlag_ADRDY(ADC3);
    LL_ADC_REG_StartConversion(ADC3);
}

Other functions are: enable interrupts and get value

void ADC_EnableInterrupt(void) {
 
    NVIC_SetPriority(ADC3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 2, 0));
    NVIC_EnableIRQ(ADC3_IRQn);
}
 
void DMA_EnableInterrupt(void) {
 
    NVIC_SetPriority(DMA1_Stream1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 2, 0));
    NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}
 
uint32_t GetMCUTemperature(void){
    return __LL_ADC_CALC_TEMPERATURE(3300, tempSensor[1], LL_ADC_RESOLUTION_16B);
}
 
uint32_t GetPF10Voltage(void){
    return __LL_ADC_CALC_DATA_TO_VOLTAGE(3300, tempSensor[0], LL_ADC_RESOLUTION_16B);
}

Interrupt handler:

void DMA1_Stream1_IRQHandler(void) {
    if (LL_DMA_IsActiveFlag_TC1(DMA1)) {
        LL_DMA_ClearFlag_TC1(DMA1);
 
        dma_flag = 1;
    }
}
 
void ADC3_IRQHandler(void) {
 
    if (LL_ADC_IsActiveFlag_EOC(ADC3)) {
        LL_ADC_ClearFlag_EOC(ADC3);
 
        adc_flag = 1;
    }
 
    if (LL_ADC_IsActiveFlag_EOS(ADC3)) {
        LL_ADC_ClearFlag_EOS(ADC3);
        adc_flag = 2;
    }
}

Variable for reading

#define DMA_BUFFER __attribute__ ((section (".sram1"),aligned(32)))
#define     ADC3_NUM_CHANNEL    2
 
volatile DMA_BUFFER uint16_t tempSensor[ADC3_NUM_CHANNEL] = { 0 };

In main, I call every one second:

if (adc_flag > 0) {
      InfoPrint("adc_flag: %d", adc_flag);
       adc_flag = 0;
}
 
if (dma_flag > 0) {
        InfoPrint("dma_flag: %d", dma_flag);
        dma_flag = 0;
}
 
UARTprint("pf10 = %d, temp = %d", BSP_GetPF10Voltage(), BSP_GetMCUTemperature());

And my outpu is here:

adc_flag: 2
dma_flag: 1
pf10 = 2538, temp = -216
adc_flag: 2
dma_flag: 1
pf10 = 2538, temp = -216
adc_flag: 2
dma_flag: 1
pf10 = 2538, temp = -216
adc_flag: 2
dma_flag: 1
pf10 = 2538, temp = -216
adc_flag: 2
dma_flag: 1
pf10 = 2538, temp = -216
adc_flag: 2
dma_flag: 1
pf10 = 2538, temp = -216

And I see that interrupts work, but continuous measurement doesn't work.

0693W00000GYiiiQAD.png

Pilous Droip
Senior

I'm approaching a solution. In some pdf I read about DCache. So I tried to update my code:

SCB_InvalidateDCache_by_Addr((uint32_t*) tempSensor, (uint32_t) (sizeof(tempSensor) / sizeof(uint16_t)));
UartPrint("TEMP=%d; PF10=%d;  VREF=%d", GetMCUTemperature(), GetPF10Voltage(), GetVrefVoltage
 
 
// Using function for read temps and voltages
uint32_t GetMCUTemperature(void) {
    return __LL_ADC_CALC_TEMPERATURE(3300, tempSensor[0], LL_ADC_RESOLUTION_16B);
}
 
uint32_t GetPF10Voltage(void) {
    return __LL_ADC_CALC_DATA_TO_VOLTAGE(3300, tempSensor[1], LL_ADC_RESOLUTION_16B);
}
 
uint32_t GetVrefVoltage(void) {
    return __LL_ADC_CALC_DATA_TO_VOLTAGE(3300, tempSensor[2], LL_ADC_RESOLUTION_16B);
}

I used a freezer before starting the MCU. Now I have a problem with the PF10 value. This value is not measured.

The time in ms is given in parentheses.

[02011] TEMP=24; PF10=580;  VREF=1269
[03016] TEMP=27; PF10=598;  VREF=1268
[04021] TEMP=28; PF10=591;  VREF=1268
[05026] TEMP=27; PF10=578;  VREF=1269
[06031] TEMP=29; PF10=593;  VREF=1269
[07036] TEMP=31; PF10=571;  VREF=1269
[08041] TEMP=34; PF10=587;  VREF=1269
[09046] TEMP=37; PF10=571;  VREF=1270
[10051] TEMP=40; PF10=570;  VREF=1269
[11056] TEMP=42; PF10=606;  VREF=1271
[12061] TEMP=44; PF10=609;  VREF=1270
[13066] TEMP=45; PF10=605;  VREF=1271
[14071] TEMP=46; PF10=605;  VREF=1270
[15076] TEMP=48; PF10=623;  VREF=1270
[16081] TEMP=48; PF10=617;  VREF=1270
[17086] TEMP=49; PF10=626;  VREF=1269
[18091] TEMP=49; PF10=635;  VREF=1271
[19096] TEMP=49; PF10=634;  VREF=1271
[20101] TEMP=51; PF10=612;  VREF=1270
[21106] TEMP=51; PF10=611;  VREF=1270
[22111] TEMP=51; PF10=604;  VREF=1270
[23116] TEMP=52; PF10=612;  VREF=1270
[24121] TEMP=52; PF10=614;  VREF=1270
[25126] TEMP=52; PF10=620;  VREF=1271

Here is my init ADC

void ADC_Init(void) {
 // clock is set to 50MHz
    LL_GPIO_InitTypeDef GPIO_InitStruct = { 0 };
 
    LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOF);
    /* PF10 ------> ADC3_INP6 */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    LL_GPIO_Init(GPIOF, &GPIO_InitStruct);
 
    LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLL3R);
 
    /* Peripheral clock enable */
    LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_ADC3);
 
    if (LL_ADC_IsDeepPowerDownEnabled(ADC3) != 0UL)
        LL_ADC_DisableDeepPowerDown(ADC3);
 
    if (LL_ADC_IsInternalRegulatorEnabled(ADC3) == 0UL) {
        LL_ADC_EnableInternalRegulator(ADC3);
        __IO uint32_t wait_loop_index = 0UL;
        wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US / 10UL) * (SystemCoreClock / (100000UL * 2UL))) + 1000;
        while (wait_loop_index != 0UL) {
            wait_loop_index--;
        }
    }
 
    LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC3), LL_ADC_PATH_INTERNAL_TEMPSENSOR | LL_ADC_PATH_INTERNAL_VREFINT | LL_ADC_PATH_INTERNAL_VBAT);
    LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(ADC3), LL_ADC_CLOCK_ASYNC_DIV1);
    LL_ADC_SetResolution(ADC3, LL_ADC_RESOLUTION_16B);
    LL_ADC_REG_SetSequencerLength(ADC3, LL_ADC_REG_SEQ_SCAN_ENABLE_3RANKS);
    LL_ADC_SetLowPowerMode(ADC3, LL_ADC_LP_MODE_NONE);
    LL_ADC_REG_SetContinuousMode(ADC3, LL_ADC_REG_CONV_CONTINUOUS);
    LL_ADC_REG_SetSequencerDiscont(ADC3, LL_ADC_REG_SEQ_DISCONT_DISABLE);
    LL_ADC_REG_SetTriggerSource(ADC3, LL_ADC_REG_TRIG_SOFTWARE);
    LL_ADC_REG_SetDataTransferMode(ADC3, LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
    LL_ADC_REG_SetOverrun(ADC3, LL_ADC_REG_OVR_DATA_OVERWRITTEN);
    LL_ADC_SetOverSamplingScope(ADC3, LL_ADC_OVS_DISABLE);
 
    LL_ADC_SetBoostMode(ADC3, LL_ADC_BOOST_MODE_50MHZ);
 
    LL_ADC_SetMultimode(__LL_ADC_COMMON_INSTANCE(ADC3), LL_ADC_MULTI_INDEPENDENT);
 
    LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_TEMPSENSOR);
    LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SAMPLINGTIME_387CYCLES_5);
    LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SINGLE_ENDED);
 
    LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_6);
    LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_6, LL_ADC_SAMPLINGTIME_8CYCLES_5);
    LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_6, LL_ADC_SINGLE_ENDED);
 
    LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_3, LL_ADC_CHANNEL_VREFINT);
    LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_VREFINT, LL_ADC_SAMPLINGTIME_64CYCLES_5);
    LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_VREFINT, LL_ADC_SINGLE_ENDED);
 
    LL_ADC_EnableIT_EOS(ADC3); // End of regular sequence of conversions IR enable
 
}