1 /*!
2  * \file      adc-board.c
3  *
4  * \brief     Target board ADC driver implementation
5  *
6  * \copyright Revised BSD License, see section \ref LICENSE.
7  *
8  * \code
9  *                ______                              _
10  *               / _____)             _              | |
11  *              ( (____  _____ ____ _| |_ _____  ____| |__
12  *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
13  *               _____) ) ____| | | || |_| ____( (___| | | |
14  *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
15  *              (C)2013-2017 Semtech
16  *
17  * \endcode
18  *
19  * \author    Miguel Luis ( Semtech )
20  *
21  * \author    Gregory Cristian ( Semtech )
22  */
23 #include "stm32l0xx.h"
24 #include "board-config.h"
25 #include "adc-board.h"
26 
27 ADC_HandleTypeDef AdcHandle;
28 
AdcMcuInit(Adc_t * obj,PinNames adcInput)29 void AdcMcuInit( Adc_t *obj, PinNames adcInput )
30 {
31     AdcHandle.Instance = ADC1;
32 
33     __HAL_RCC_ADC1_CLK_ENABLE( );
34 
35     HAL_ADC_DeInit( &AdcHandle );
36 
37     if( adcInput != NC )
38     {
39         GpioInit( &obj->AdcInput, adcInput, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
40     }
41 }
42 
AdcMcuConfig(void)43 void AdcMcuConfig( void )
44 {
45     // Configure ADC
46     AdcHandle.Init.OversamplingMode      = DISABLE;
47     AdcHandle.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV2;
48     AdcHandle.Init.Resolution            = ADC_RESOLUTION_12B;
49     AdcHandle.Init.SamplingTime          = ADC_SAMPLETIME_160CYCLES_5;
50     AdcHandle.Init.ScanConvMode          = ADC_SCAN_DIRECTION_FORWARD;
51     AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;
52     AdcHandle.Init.ContinuousConvMode    = DISABLE;
53     AdcHandle.Init.DiscontinuousConvMode = DISABLE;
54     AdcHandle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE;
55     AdcHandle.Init.ExternalTrigConv      = ADC_SOFTWARE_START;
56     AdcHandle.Init.DMAContinuousRequests = DISABLE;
57     AdcHandle.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;
58     AdcHandle.Init.Overrun               = ADC_OVR_DATA_PRESERVED;
59     AdcHandle.Init.LowPowerAutoWait      = DISABLE;
60     AdcHandle.Init.LowPowerFrequencyMode = ENABLE; // To be enabled only if ADC clock < 2.8 MHz
61     AdcHandle.Init.LowPowerAutoPowerOff  = DISABLE;
62     HAL_ADC_Init( &AdcHandle );
63 }
64 
AdcMcuReadChannel(Adc_t * obj,uint32_t channel)65 uint16_t AdcMcuReadChannel( Adc_t *obj, uint32_t channel )
66 {
67     ADC_ChannelConfTypeDef adcConf = { 0 };
68     uint16_t adcData = 0;
69 
70     // Enable HSI
71     __HAL_RCC_HSI_ENABLE( );
72 
73     // Wait till HSI is ready
74     while( __HAL_RCC_GET_FLAG( RCC_FLAG_HSIRDY ) == RESET )
75     {
76     }
77 
78     // Wait the the Vrefint used by adc is set
79     while( __HAL_PWR_GET_FLAG( PWR_FLAG_VREFINTRDY ) == RESET )
80     {
81     }
82 
83     __HAL_RCC_ADC1_CLK_ENABLE( );
84 
85     // Calibrate ADC if any calibraiton hardware
86     HAL_ADCEx_Calibration_Start( &AdcHandle, ADC_SINGLE_ENDED );
87 
88     // Deselects all channels
89     adcConf.Channel = ADC_CHANNEL_MASK;
90     adcConf.Rank = ADC_RANK_NONE;
91     HAL_ADC_ConfigChannel( &AdcHandle, &adcConf );
92 
93     // Configure ADC channel
94     adcConf.Channel = channel;
95     adcConf.Rank = ADC_RANK_CHANNEL_NUMBER;
96     HAL_ADC_ConfigChannel( &AdcHandle, &adcConf );
97 
98     // Start ADC Software Conversion
99     HAL_ADC_Start( &AdcHandle );
100 
101     HAL_ADC_PollForConversion( &AdcHandle, HAL_MAX_DELAY );
102 
103     adcData = HAL_ADC_GetValue( &AdcHandle );
104 
105     __HAL_ADC_DISABLE( &AdcHandle );
106 
107     __HAL_RCC_ADC1_CLK_DISABLE( );
108 
109     // Disable HSI
110     __HAL_RCC_HSI_DISABLE( );
111 
112     return adcData;
113 }
114