예제 #1
0
static void platform_init_adc() {
  /* Set up DMA for the ADC */
  nvic_enable_irq(NVIC_DMA2_STREAM0_IRQ);
  nvic_set_priority(NVIC_DMA2_STREAM0_IRQ, 64);

  /* Set up ADC */
  for (int i = 0; i < NUM_SENSORS; ++i) {
    if (config.sensors[i].method == SENSOR_ADC) {
      adc_pins[i] = config.sensors[i].pin;
      gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, (1<<adc_pins[i]));
    }
  }
  adc_off(ADC1);
  adc_enable_scan_mode(ADC1);
  adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_15CYC);
  adc_power_on(ADC1);

  adc_disable_dma(ADC1);
  adc_enable_dma(ADC1);
  adc_clear_overrun_flag(ADC1);
  adc_set_dma_continue(ADC1);

  dma_stream_reset(DMA2, DMA_STREAM0);
  dma_set_priority(DMA2, DMA_STREAM0, DMA_SxCR_PL_HIGH);
  dma_set_memory_size(DMA2, DMA_STREAM0, DMA_SxCR_MSIZE_16BIT);
  dma_set_peripheral_size(DMA2, DMA_STREAM0, DMA_SxCR_PSIZE_16BIT);
  dma_enable_memory_increment_mode(DMA2, DMA_STREAM0);
  dma_set_transfer_mode(DMA2, DMA_STREAM0, DMA_SxCR_DIR_PERIPHERAL_TO_MEM);
  dma_enable_circular_mode(DMA2, DMA_STREAM0);
  dma_set_peripheral_address(DMA2, DMA_STREAM0, (uint32_t) &ADC1_DR);
  dma_set_memory_address(DMA2, DMA_STREAM0, (uint32_t) adc_dma_buf);
  dma_set_number_of_data(DMA2, DMA_STREAM0, NUM_SENSORS);
  dma_enable_transfer_complete_interrupt(DMA2, DMA_STREAM0);
  dma_channel_select(DMA2, DMA_STREAM0, DMA_SxCR_CHSEL_0);
  dma_enable_stream(DMA2, DMA_STREAM0);
  adc_set_regular_sequence(ADC1, NUM_SENSORS, adc_pins);
}
예제 #2
0
/**
 * Enable selected channels on specified ADC.
 * Usage:
 *
 * adc_init_single(ADC1, 1, 1, 0, 0);
 *
 * ... would enable ADC1, enabling channels 1 and 2,
 * but not 3 and 4.
 */
static inline void adc_init_single(uint32_t adc,
                                   uint8_t chan1, uint8_t chan2,
                                   uint8_t chan3, uint8_t chan4)
{
  uint8_t num_channels, rank;
  uint8_t channels[4];

  // Paranoia, must be down for 2+ ADC clock cycles before calibration
  adc_off(adc);

  /* enable adc clock */
  if (adc == ADC1) {
#ifdef USE_AD1
    num_channels = NB_ADC1_CHANNELS;
    ADC1_GPIO_INIT();
#endif
  }
  else if (adc == ADC2) {
#ifdef USE_AD2
    num_channels = NB_ADC2_CHANNELS;
    ADC2_GPIO_INIT();
#endif
  }

  /* Configure ADC */

  /* Explicitly setting most registers, reset/default values are correct for most */

  /* Set CR1 register. */

  /* Clear AWDEN */
  adc_disable_analog_watchdog_regular(adc);
  /* Clear JAWDEN */
  adc_disable_analog_watchdog_injected(adc);
  /* Clear DISCEN */
  adc_disable_discontinuous_mode_regular(adc);
  /* Clear JDISCEN */
  adc_disable_discontinuous_mode_injected(adc);
  /* Clear JAUTO */
  adc_disable_automatic_injected_group_conversion(adc);
  /* Set SCAN */
  adc_enable_scan_mode(adc);
  /* Enable ADC<X> JEOC interrupt (Set JEOCIE) */
  adc_enable_eoc_interrupt_injected(adc);
  /* Clear AWDIE */
  adc_disable_awd_interrupt(adc);
  /* Clear EOCIE */
  adc_disable_eoc_interrupt(adc);

  /* Set CR2 register. */

  /* Clear TSVREFE */
  adc_disable_temperature_sensor(adc);
  /* Clear EXTTRIG */
  adc_disable_external_trigger_regular(adc);
  /* Clear ALIGN */
  adc_set_right_aligned(adc);
  /* Clear DMA */
  adc_disable_dma(adc);
  /* Clear CONT */
  adc_set_single_conversion_mode(adc);

  rank = 0;
  if (chan1) {
    adc_set_sample_time(adc, adc_channel_map[0], ADC_SMPR1_SMP_41DOT5CYC);
    channels[rank] = adc_channel_map[0];
    rank++;
  }
  if (chan2) {
    adc_set_sample_time(adc, adc_channel_map[1], ADC_SMPR1_SMP_41DOT5CYC);
    channels[rank] = adc_channel_map[1];
    rank++;
  }
  if (chan3) {
    adc_set_sample_time(adc, adc_channel_map[2], ADC_SMPR1_SMP_41DOT5CYC);
    channels[rank] = adc_channel_map[2];
    rank++;
  }
  if (chan4) {
    adc_set_sample_time(adc, adc_channel_map[3], ADC_SMPR1_SMP_41DOT5CYC);
    channels[rank] = adc_channel_map[3];
  }

  adc_set_injected_sequence(adc, num_channels, channels);

#if USE_AD_TIM4
#pragma message "Info: Using TIM4 for ADC"
  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM4_TRGO);
#elif USE_AD_TIM1
#pragma message "Info: Using TIM1 for ADC"
  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM1_TRGO);
#else
#pragma message "Info: Using default TIM2 for ADC"
  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM2_TRGO);
#endif

  /* Enable ADC<X> */
  adc_power_on(adc);

  /* Enable ADC<X> reset calibaration register */
  adc_reset_calibration(adc);
  /* Check the end of ADC<X> reset calibration */
  while ((ADC_CR2(adc) & ADC_CR2_RSTCAL) != 0);
  /* Start ADC<X> calibaration */
  adc_calibration(adc);
  /* Check the end of ADC<X> calibration */
  while ((ADC_CR2(adc) & ADC_CR2_CAL) != 0);

} // adc_init_single
예제 #3
0
static inline void adc_init_single(uint32_t adc, uint8_t nb_channels, uint8_t* channel_map)
{
  // Paranoia, must be down for 2+ ADC clock cycles before calibration
  adc_off(adc);

  /* Configure ADC */
  /* Explicitly setting most registers, reset/default values are correct for most */
  /* Set CR1 register. */
  /* Clear AWDEN */
  adc_disable_analog_watchdog_regular(adc);
  /* Clear JAWDEN */
  adc_disable_analog_watchdog_injected(adc);
  /* Clear DISCEN */
  adc_disable_discontinuous_mode_regular(adc);
  /* Clear JDISCEN */
  adc_disable_discontinuous_mode_injected(adc);
  /* Clear JAUTO */
  adc_disable_automatic_injected_group_conversion(adc);
  /* Set SCAN */
  adc_enable_scan_mode(adc);
  /* Enable ADC<X> JEOC interrupt (Set JEOCIE) */
  adc_enable_eoc_interrupt_injected(adc);
  /* Clear AWDIE */
  adc_disable_awd_interrupt(adc);
  /* Clear EOCIE */
  adc_disable_eoc_interrupt(adc);

  /* Set CR2 register. */
  /* Clear TSVREFE */
#if defined(STM32F1)
  adc_disable_temperature_sensor(adc);
#elif defined(STM32F4)
  adc_disable_temperature_sensor();
#endif
  /* Clear EXTTRIG */
  adc_disable_external_trigger_regular(adc);
  /* Clear ALIGN */
  adc_set_right_aligned(adc);
  /* Clear DMA */
  adc_disable_dma(adc);
  /* Clear CONT */
  adc_set_single_conversion_mode(adc);

  //uint8_t x = 0;
  //for (x = 0; x < nb_channels; x++) {
  //  adc_set_sample_time(adc, channel_map[x], ADC_SAMPLE_TIME);
  //}
  adc_set_sample_time_on_all_channels(adc, ADC_SAMPLE_TIME);

  adc_set_injected_sequence(adc, nb_channels, channel_map);

#if USE_AD_TIM4
  PRINT_CONFIG_MSG("Info: Using TIM4 for ADC")
#if defined(STM32F1)
  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM4_TRGO);
#elif defined(STM32F4)
  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM4_TRGO, ADC_CR2_JEXTEN_BOTH_EDGES);
#endif
#elif USE_AD_TIM1
  PRINT_CONFIG_MSG("Info: Using TIM1 for ADC")
#if defined(STM32F1)
  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM1_TRGO);
#elif defined(STM32F4)
  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM1_TRGO, ADC_CR2_JEXTEN_BOTH_EDGES);
#endif
#else
  PRINT_CONFIG_MSG("Info: Using default TIM2 for ADC")
#if defined(STM32F1)
  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM2_TRGO);
#elif defined(STM32F4)
  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM2_TRGO, ADC_CR2_JEXTEN_BOTH_EDGES);
#endif
#endif

  /* Enable ADC<X> */
  adc_power_on(adc);
#if defined(STM32F1)
  /* Enable ADC<X> reset calibaration register */
  adc_reset_calibration(adc);
  /* Check the end of ADC<X> reset calibration */
  while ((ADC_CR2(adc) & ADC_CR2_RSTCAL) != 0);
  /* Start ADC<X> calibaration */
  adc_calibration(adc);
  /* Check the end of ADC<X> calibration */
  while ((ADC_CR2(adc) & ADC_CR2_CAL) != 0);
#endif

  return;
} // adc_init_single