STM32L4 ADC не работает (несколько каналов без DMA)

Я пытаюсь запустить код, который я нашел здесь некоторое время назад, который позволяет выбрать канал АЦП из нескольких каналов и при необходимости прочитать его индивидуально. Нет прямого доступа к памяти. Использую STM32L4R5. Моя идея состоит в том, чтобы просто подтвердить правильность чтения АЦП, включив и выключив светодиоды состояния, если какой-то уровень доступен, и он пока не работает (светодиод состояния всегда включен). В качестве источника входного сигнала я использую вывод GPIO, установленный на высокий уровень, который проходит через резистор 1 кОм и светодиод, поэтому напряжение составляет около 0,7 В. Я вызываю __HAL_RCC_ADC_CLK_ENABLE (); и __HAL_RCC_GPIOC_CLK_ENABLE (); в HAL_ADC_MspInit (). Функция status_led () не отображается, но я ее часто использую, никаких проблем с ней.

Остальной код выглядит следующим образом:

uint32_t pdlvl=0;

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_ADC1_Init();
    MX_TIM1_Init();

    // Test ADC reading voltage input
    //

    while(1){
        pdlvl=read_ADC_channel(ADC_CHANNEL_13);
        if(pdlvl<10){
            status_led(4,1);
            status_led(3,0);
        }
        if(pdlvl>10){
            status_led(3,1);
            status_led(4,0);
        }
    }

} // end of main
static void MX_ADC1_Init(void)
{

  ADC_ChannelConfTypeDef sConfig = {0};

  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  sConfig.Channel = ADC_CHANNEL_13;
  sConfig.Rank = ADC_RANK_NONE;
  sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  sConfig.Channel = ADC_CHANNEL_14;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

Инициализация пина

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  __HAL_RCC_GPIOC_CLK_ENABLE();

  GPIO_InitStruct.Pin = ROUT1_Pin|ROUT2_Pin; // ADC_CHANNEL_13 and ADC_CHANNEL_14
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

}

Теперь сложная часть с предварительной настройкой каналов:


void config_ADC_channel(uint32_t channel, uint8_t val)
{
    ADC_ChannelConfTypeDef sConfig;

    sConfig.Channel = channel;
    sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
    sConfig.SingleDiff = ADC_SINGLE_ENDED;
    sConfig.OffsetNumber = ADC_OFFSET_NONE;

    if(val==1){
        sConfig.Rank = 1;
    }
    else{
        sConfig.Rank = ADC_RANK_NONE;
    }
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}

и функция чтения

uint32_t read_ADC_channel(uint32_t channel)
{
  uint32_t digital_result;

  config_ADC_channel(channel, 1);

//  HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);

  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1, 1000);
  digital_result = HAL_ADC_GetValue(&hadc1);
  HAL_ADC_Stop(&hadc1);

  config_ADC_channel(channel, 0);

  return digital_result;
}

Есть идеи, где я ошибаюсь?

Спасибо!


person D. K.    schedule 18.07.2020    source источник


Ответы (1)


Я нашел проблему. Я неправильно установил источник синхронизации Периферии (изначально сгенерированный CubeMX, а затем измененный мной источник):

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
  PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
  PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1;
  PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
  PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE;
  PeriphClkInit.PLLSAI1.PLLSAI1M = 6;
  PeriphClkInit.PLLSAI1.PLLSAI1N = 20;
  PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV2;
  PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
  PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
  PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_ADC1CLK;

person D. K.    schedule 27.08.2020