/// \classmethod \constructor(pin) /// Create an ADC object associated with the given pin. /// This allows you to then read analog values on that pin. STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check number of arguments mp_arg_check_num(n_args, n_kw, 1, 1, false); // 1st argument is the pin name mp_obj_t pin_obj = args[0]; uint32_t channel; if (MP_OBJ_IS_INT(pin_obj)) { channel = adc_get_internal_channel(mp_obj_get_int(pin_obj)); } else { const pin_obj_t *pin = pin_find(pin_obj); if ((pin->adc_num & PIN_ADC1) == 0) { // No ADC1 function on that pin nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %q does not have ADC capabilities", pin->name)); } channel = pin->adc_channel; } if (!is_adcx_channel(channel)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "not a valid ADC Channel: %d", channel)); } if (ADC_FIRST_GPIO_CHANNEL <= channel && channel <= ADC_LAST_GPIO_CHANNEL) { // these channels correspond to physical GPIO ports so make sure they exist if (pin_adc1[channel] == NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "channel %d not available on this board", channel)); } } pyb_obj_adc_t *o = m_new_obj(pyb_obj_adc_t); memset(o, 0, sizeof(*o)); o->base.type = &pyb_adc_type; o->pin_name = pin_obj; o->channel = channel; adc_init_single(o); return o; }
STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) { if (!is_adcx_channel(adc_obj->channel)) { return; } if (ADC_FIRST_GPIO_CHANNEL <= adc_obj->channel && adc_obj->channel <= ADC_LAST_GPIO_CHANNEL) { // Channels 0-16 correspond to real pins. Configure the GPIO pin in ADC mode. const pin_obj_t *pin = pin_adc_table[adc_obj->channel]; mp_hal_pin_config(pin, MP_HAL_PIN_MODE_ADC, MP_HAL_PIN_PULL_NONE, 0); } adcx_init_periph(&adc_obj->handle, ADC_RESOLUTION_12B); #if defined(STM32L4) && defined(ADC_DUALMODE_REGSIMULT_INJECSIMULT) ADC_MultiModeTypeDef multimode; multimode.Mode = ADC_MODE_INDEPENDENT; if (HAL_ADCEx_MultiModeConfigChannel(&adc_obj->handle, &multimode) != HAL_OK) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Can not set multimode on ADC1 channel: %d", adc_obj->channel)); } #endif }
STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) { if (!is_adcx_channel(adc_obj->channel)) { return; } if (ADC_FIRST_GPIO_CHANNEL <= adc_obj->channel && adc_obj->channel <= ADC_LAST_GPIO_CHANNEL) { // Channels 0-16 correspond to real pins. Configure the GPIO pin in // ADC mode. const pin_obj_t *pin = pin_adc1[adc_obj->channel]; mp_hal_gpio_clock_enable(pin->gpio); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = pin->pin_mask; #if defined(STM32F4) || defined(STM32F7) GPIO_InitStructure.Mode = GPIO_MODE_ANALOG; #elif defined(STM32L4) GPIO_InitStructure.Mode = GPIO_MODE_ANALOG_ADC_CONTROL; #else #error Unsupported processor #endif GPIO_InitStructure.Pull = GPIO_NOPULL; HAL_GPIO_Init(pin->gpio, &GPIO_InitStructure); } adcx_clock_enable(); ADC_HandleTypeDef *adcHandle = &adc_obj->handle; adcHandle->Instance = ADCx; adcHandle->Init.ContinuousConvMode = DISABLE; adcHandle->Init.DiscontinuousConvMode = DISABLE; adcHandle->Init.NbrOfDiscConversion = 0; adcHandle->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; adcHandle->Init.DataAlign = ADC_DATAALIGN_RIGHT; adcHandle->Init.NbrOfConversion = 1; adcHandle->Init.DMAContinuousRequests = DISABLE; adcHandle->Init.Resolution = ADC_RESOLUTION_12B; #if defined(STM32F4) || defined(STM32F7) adcHandle->Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; adcHandle->Init.ScanConvMode = DISABLE; adcHandle->Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1; adcHandle->Init.EOCSelection = DISABLE; #elif defined(STM32L4) adcHandle->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; adcHandle->Init.ScanConvMode = ADC_SCAN_DISABLE; adcHandle->Init.EOCSelection = ADC_EOC_SINGLE_CONV; adcHandle->Init.ExternalTrigConv = ADC_SOFTWARE_START; adcHandle->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; adcHandle->Init.LowPowerAutoWait = DISABLE; adcHandle->Init.Overrun = ADC_OVR_DATA_PRESERVED; adcHandle->Init.OversamplingMode = DISABLE; #else #error Unsupported processor #endif HAL_ADC_Init(adcHandle); #if defined(STM32L4) ADC_MultiModeTypeDef multimode; multimode.Mode = ADC_MODE_INDEPENDENT; if (HAL_ADCEx_MultiModeConfigChannel(adcHandle, &multimode) != HAL_OK) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Can not set multimode on ADC1 channel: %d", adc_obj->channel)); } #endif }