Exemplo n.º 1
0
Arquivo: main.c Projeto: N7QWT/klipper
void adc_config(void)
{
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC1);
    /* ADC might be in deep sleep, needs to be woken up twice in that case */
    LL_ADC_Enable(ADC1);
    LL_mDelay(1);
    LL_ADC_Enable(ADC1);
    LL_mDelay(1);
    LL_ADC_StartCalibration(ADC1);
    while (LL_ADC_IsCalibrationOnGoing(ADC1));
    LL_ADC_SetSequencersScanMode(ADC1, LL_ADC_SEQ_SCAN_DISABLE);
    LL_ADC_REG_SetTriggerSource(ADC1, LL_ADC_REG_TRIG_SOFTWARE);
    LL_ADC_REG_SetSequencerLength(ADC1, LL_ADC_REG_SEQ_SCAN_DISABLE);
}
Exemplo n.º 2
0
static int adc_stm32_init(struct device *dev)
{
	struct adc_stm32_data *data = dev->driver_data;
	const struct adc_stm32_cfg *config = dev->config->config_info;
	struct device *clk =
		device_get_binding(STM32_CLOCK_CONTROL_NAME);
	ADC_TypeDef *adc = (ADC_TypeDef *)config->base;

	LOG_DBG("Initializing....");

	data->dev = dev;
#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32L0X)
	/*
	 * All conversion time for all channels on one ADC instance for F0 and
	 * L0 series chips has to be the same. This additional variable is for
	 * checking if the conversion time selection of all channels on one ADC
	 * instance is the same.
	 */
	data->acq_time_index = -1;
#endif

	if (clock_control_on(clk,
		(clock_control_subsys_t *) &config->pclken) != 0) {
		return -EIO;
	}

#if defined(CONFIG_SOC_SERIES_STM32L4X)
	/*
	 * L4 series STM32 needs to be awaken from deep sleep mode, and restore
	 * its calibration parameters if there are some previously stored
	 * calibration parameters.
	 */
	LL_ADC_DisableDeepPowerDown(adc);
#endif
	/*
	 * F3 and L4 ADC modules need some time to be stabilized before
	 * performing any enable or calibration actions.
	 */
#if defined(CONFIG_SOC_SERIES_STM32F3X) || \
	defined(CONFIG_SOC_SERIES_STM32L4X)
	LL_ADC_EnableInternalRegulator(adc);
	k_busy_wait(LL_ADC_DELAY_INTERNAL_REGUL_STAB_US);
#endif

#if defined(CONFIG_SOC_SERIES_STM32F0X) || \
	defined(CONFIG_SOC_SERIES_STM32L0X)
	LL_ADC_SetClock(adc, LL_ADC_CLOCK_SYNC_PCLK_DIV4);
#elif defined(CONFIG_SOC_SERIES_STM32F3X) || \
	defined(CONFIG_SOC_SERIES_STM32L4X)
	LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(),
			LL_ADC_CLOCK_SYNC_PCLK_DIV4);
#endif

#if !defined(CONFIG_SOC_SERIES_STM32F2X) && \
	!defined(CONFIG_SOC_SERIES_STM32F4X) && \
	!defined(CONFIG_SOC_SERIES_STM32F7X) && \
	!defined(CONFIG_SOC_SERIES_STM32F1X)
	/*
	 * Calibration of F1 series has to be started after ADC Module is
	 * enabled.
	 */
	adc_stm32_calib(dev);
#endif

#if defined(CONFIG_SOC_SERIES_STM32F0X) || \
	defined(CONFIG_SOC_SERIES_STM32L0X)
	if (LL_ADC_IsActiveFlag_ADRDY(adc)) {
		LL_ADC_ClearFlag_ADRDY(adc);
	}

	/*
	 * These two series STM32 has one internal voltage reference source
	 * to be enabled.
	 */
	LL_ADC_SetCommonPathInternalCh(ADC, LL_ADC_PATH_INTERNAL_VREFINT);
#endif

#if defined(CONFIG_SOC_SERIES_STM32F0X) || \
	defined(CONFIG_SOC_SERIES_STM32F3X) || \
	defined(CONFIG_SOC_SERIES_STM32L0X) || \
	defined(CONFIG_SOC_SERIES_STM32L4X)
	/*
	 * ADC modules on these series have to wait for some cycles to be
	 * enabled.
	 */
	u32_t adc_rate, wait_cycles;

	if (clock_control_get_rate(clk,
		(clock_control_subsys_t *) &config->pclken, &adc_rate) < 0) {
		LOG_ERR("ADC clock rate get error.");
	}

	wait_cycles = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / adc_rate *
		      LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES;

	for (int i = wait_cycles; i >= 0; i--)
		;
#endif

	LL_ADC_Enable(adc);

#ifdef CONFIG_SOC_SERIES_STM32L4X
	/*
	 * Enabling ADC modules in L4 series may fail if they are still not
	 * stabilized, this will wait for a short time to ensure ADC modules
	 * are properly enabled.
	 */
	u32_t countTimeout = 0;

	while (LL_ADC_IsActiveFlag_ADRDY(adc) == 0) {
		if (LL_ADC_IsEnabled(adc) == 0UL) {
			LL_ADC_Enable(adc);
			countTimeout++;
			if (countTimeout == 10) {
				return -ETIMEDOUT;
			}
		}
	}
#endif

	config->irq_cfg_func();

#ifdef CONFIG_SOC_SERIES_STM32F1X
	/* Calibration of F1 must starts after two cycles after ADON is set. */
	LL_ADC_StartCalibration(adc);
	LL_ADC_REG_SetTriggerSource(adc, LL_ADC_REG_TRIG_SOFTWARE);
#endif
	adc_context_unlock_unconditionally(&data->ctx);

	return 0;
}