2021-11-19 12:45 AM
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...
2021-11-22 07:03 AM
Yes, it was disabled. Now I enable it, by this line:
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC3), LL_ADC_PATH_INTERNAL_TEMPSENSOR);
But I am not sure, that measure adc3 is fine. I'll try to do some measurements.:thumbs_up:
2021-11-22 07:48 AM
I started measuring. I measured for about 15 minutes. It looks good. Tomorrow I will continue.
@Gwenole BROCHARD Thank you for your advice.
2021-11-22 10:27 PM
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. :beaming_face_with_smiling_eyes:
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;
}
}
2021-11-23 03:28 AM
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).
2021-11-24 04:49 AM
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.
2021-11-29 05:10 AM
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
}