#include "stm32f030x6.h" #include #include const uint8_t adc_channels[POTI_COUNT] = {POTI_ADC_CHANNELS}; static volatile uint16_t adc_raw_values[POTI_COUNT]; static volatile uint16_t adc_moving_avg[POTI_COUNT]; static volatile uint8_t adc_moving_avg_out[POTI_COUNT]; /** * @brief Perform calibration. ADC must be disabled */ static void perform_cal(void) { ADC1->CR = ADC_CR_ADCAL; while (ADC1->CR & ADC_CR_ADCAL); (void)ADC1->DR; } void poti_init_adc(void) { int i; uint32_t reg; RCC->APB2ENR |= RCC_APB2ENR_ADCEN; RCC->AHBENR |= RCC_AHBENR_DMAEN; for (i = 0; i < POTI_COUNT; i++) { adc_moving_avg[i] = 0u; } DMA1_Channel1->CCR = 0ul; /* Clear ADC ready bit */ ADC1->ISR = ADC_ISR_ADRDY; ADC1->CFGR1 = 0; /* Start calibration */ perform_cal(); /* Activate channels to convert */ reg = 0ul; for (i = 0; i < POTI_COUNT; i++) { if (adc_channels[i] <= 17) reg |= (1<CHSELR = reg; /* Setup sample time (71.5 cycles) */ ADC1->SMPR = ADC_SMPR_SMP_2 | ADC_SMPR_SMP_1; /* Setup ADC clock (PCLK / 4) */ ADC1->CFGR2 = ADC_CFGR2_CKMODE_1; /* Setup continuous sample mode with DMA in circular mode */ ADC1->CFGR1 = ADC_CFGR1_CONT | ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG; /* Enable ADC and wait for ready */ ADC1->CR = ADC_CR_ADEN; while (!(ADC1->ISR & ADC_ISR_ADRDY)); /* Setup DMA channel 1 */ DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; DMA1_Channel1->CMAR = (uint32_t)adc_raw_values; DMA1_Channel1->CNDTR = POTI_COUNT; DMA1_Channel1->CCR = DMA_CCR_PL_0 | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_TCIE | DMA_CCR_EN; NVIC_EnableIRQ(DMA1_Channel1_IRQn); /* Start the conversion */ ADC1->CR |= ADC_CR_ADSTART; } void poti_get_values(struct poti_values *out_val) { int i; if (!out_val) return; for (i = 0; i < POTI_COUNT; i++) { out_val->current_pot_vals[i] = adc_raw_values[i]; out_val->pot_vals_filtered[i] = adc_moving_avg_out[i]; } } static uint16_t calc_moving_avg(uint16_t adc_val, uint16_t prev_avg) { uint32_t val; val = (uint32_t)prev_avg; val /= 16u; val *= 15u; val += adc_val; return val; } void DMA_CH1_IRQHandler(void) { uint32_t isr; int i; isr = DMA1->ISR; DMA1->IFCR = isr & DMA_ISR_TCIF1; if (isr & DMA_ISR_TCIF1) { /* All ADC samples converted */ for (i = 0; i < POTI_COUNT; i++) { adc_moving_avg[i] = calc_moving_avg(adc_raw_values[i], adc_moving_avg[i]); adc_moving_avg_out[i] = (uint8_t)(adc_moving_avg[i] / 16u / 16u); } } }