| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 | #include "stm32f0xx_hal.h"#include "adc.h"#include "led.h"#include <stdio.h>#define VOLTAGE_FACTOR      0.000806 // 0.24194#define FREQ_FACTOR         0.000806ADC_HandleTypeDef       AdcHandle;ADC_ChannelConfTypeDef  sConfig;ADC_FILTER_t            adc_bat;ADC_FILTER_t            adc_freq;float                   bat_voltage = 0.0; float                   freq_voltage = 0.0;        __IO uint16_t   adc_values[2];//void adc_init(void){    GPIO_InitTypeDef GPIO_InitStruct = {0};    __HAL_RCC_GPIOA_CLK_ENABLE();    __HAL_RCC_ADC1_CLK_ENABLE();    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;    GPIO_InitStruct.Pull = GPIO_NOPULL;    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);            AdcHandle.Instance          = ADC1;        HAL_ADC_DeInit(&AdcHandle);      AdcHandle.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV2;      /* Synchronous clock mode, input ADC clock with prscaler 2 */    AdcHandle.Init.Resolution            = ADC_RESOLUTION_12B;            /* 12-bit resolution for converted data */    AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;           /* Right-alignment for converted data */    AdcHandle.Init.ScanConvMode          = ADC_SCAN_DIRECTION_FORWARD;    /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */    AdcHandle.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;           /* EOC flag picked-up to indicate conversion end */    AdcHandle.Init.LowPowerAutoPowerOff  = DISABLE;    AdcHandle.Init.LowPowerAutoWait      = DISABLE;                       /* Auto-delayed conversion feature disabled */    AdcHandle.Init.ContinuousConvMode    = DISABLE;                        /* Continuous mode enabled (automatic conversion restart after each conversion) */    AdcHandle.Init.DiscontinuousConvMode = ENABLE;                       /* Parameter discarded because sequencer is disabled */    AdcHandle.Init.ExternalTrigConv      = ADC_SOFTWARE_START;            /* Software start to trig the 1st conversion manually, without external event */    AdcHandle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because software trigger chosen */    AdcHandle.Init.DMAContinuousRequests = ENABLE;                       /* ADC DMA continuous request to match with DMA circular mode */    AdcHandle.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;      /* DR register is overwritten with the last conversion result in case of overrun */    AdcHandle.Init.SamplingTimeCommon    = ADC_SAMPLETIME_28CYCLES_5;            HAL_ADC_Init(&AdcHandle);      sConfig.Channel                      = ADC_CHANNEL_0;               /* Channel to be converted */    sConfig.Rank                         = ADC_RANK_CHANNEL_NUMBER;    HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);      sConfig.Channel                      = ADC_CHANNEL_1;               /* Channel to be converted */    HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);        HAL_ADCEx_Calibration_Start(&AdcHandle);        adc_dma_init(&AdcHandle);        //HAL_ADC_Start(&AdcHandle);}void adc_dma_init(ADC_HandleTypeDef *hadc){    static DMA_HandleTypeDef  DmaHandle;    __HAL_RCC_DMA1_CLK_ENABLE();      DmaHandle.Instance = DMA1_Channel1;    DmaHandle.Init.Direction           = DMA_PERIPH_TO_MEMORY;    DmaHandle.Init.PeriphInc           = DMA_PINC_DISABLE;    DmaHandle.Init.MemInc              = DMA_MINC_ENABLE;    DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;   /* Transfer from ADC by half-word to match with ADC configuration: ADC resolution 10 or 12 bits */    DmaHandle.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;   /* Transfer to memory by half-word to match with buffer variable type: half-word */    DmaHandle.Init.Mode                = DMA_CIRCULAR;              /* DMA in circular mode to match with ADC configuration: DMA continuous requests */    DmaHandle.Init.Priority            = DMA_PRIORITY_HIGH;      HAL_DMA_DeInit(&DmaHandle);    HAL_DMA_Init(&DmaHandle);    __HAL_LINKDMA(hadc, DMA_Handle, DmaHandle);      HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 1, 0);    HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);}//float adc_average(ADC_FILTER_t *flt, float new_value){    if (!(flt->head < ADC_FILTER_LEN))        flt->head = 0;    if (flt->count < ADC_FILTER_LEN)        flt->count++;    flt->sum -= flt->buf[flt->head];    flt->sum += new_value;    flt->buf[flt->head++] = new_value;      return flt->sum/(flt->count);}//void adc_task(void){    HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)adc_values, 2);    HAL_ADC_Start(&AdcHandle);    #if 0      bat_voltage = 2*adc_average(&adc_bat, HAL_ADC_GetValue(&AdcHandle) * ADC_FACTOR);        if (bat_voltage > 3.4)        led_but_on();    else        led_but_toggle();#endif    }//void adc_print_data(void){    printf("%f %f\r\n", bat_voltage, freq_voltage);}void DMA1_Channel1_IRQHandler(void){    HAL_DMA_IRQHandler(AdcHandle.DMA_Handle);}void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *AdcHandle){    bat_voltage = adc_average(&adc_bat, adc_values[0] * VOLTAGE_FACTOR);    freq_voltage = adc_average(&adc_freq, adc_values[1] * FREQ_FACTOR);}
 |