mbed

Fork of mbed-dev by mbed official

Committer:
AnnaBridge
Date:
Fri Feb 16 16:09:33 2018 +0000
Revision:
182:57724642e740
Parent:
181:96ed750bd169
mbed-dev library. Release version 159.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Anna Bridge 181:96ed750bd169 1 /* mbed Microcontroller Library
Anna Bridge 181:96ed750bd169 2 * Copyright (c) 2016, STMicroelectronics
Anna Bridge 181:96ed750bd169 3 * All rights reserved.
Anna Bridge 181:96ed750bd169 4 *
Anna Bridge 181:96ed750bd169 5 * Redistribution and use in source and binary forms, with or without
Anna Bridge 181:96ed750bd169 6 * modification, are permitted provided that the following conditions are met:
Anna Bridge 181:96ed750bd169 7 *
Anna Bridge 181:96ed750bd169 8 * 1. Redistributions of source code must retain the above copyright notice,
Anna Bridge 181:96ed750bd169 9 * this list of conditions and the following disclaimer.
Anna Bridge 181:96ed750bd169 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
Anna Bridge 181:96ed750bd169 11 * this list of conditions and the following disclaimer in the documentation
Anna Bridge 181:96ed750bd169 12 * and/or other materials provided with the distribution.
Anna Bridge 181:96ed750bd169 13 * 3. Neither the name of STMicroelectronics nor the names of its contributors
Anna Bridge 181:96ed750bd169 14 * may be used to endorse or promote products derived from this software
Anna Bridge 181:96ed750bd169 15 * without specific prior written permission.
Anna Bridge 181:96ed750bd169 16 *
Anna Bridge 181:96ed750bd169 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Anna Bridge 181:96ed750bd169 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Anna Bridge 181:96ed750bd169 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Anna Bridge 181:96ed750bd169 20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
Anna Bridge 181:96ed750bd169 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Anna Bridge 181:96ed750bd169 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Anna Bridge 181:96ed750bd169 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
Anna Bridge 181:96ed750bd169 24 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
Anna Bridge 181:96ed750bd169 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Anna Bridge 181:96ed750bd169 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Anna Bridge 181:96ed750bd169 27 */
Anna Bridge 181:96ed750bd169 28 #include "mbed_assert.h"
Anna Bridge 181:96ed750bd169 29 #include "analogin_api.h"
Anna Bridge 181:96ed750bd169 30
Anna Bridge 181:96ed750bd169 31 #if DEVICE_ANALOGIN
Anna Bridge 181:96ed750bd169 32
Anna Bridge 181:96ed750bd169 33 #include "mbed_wait_api.h"
Anna Bridge 181:96ed750bd169 34 #include "cmsis.h"
Anna Bridge 181:96ed750bd169 35 #include "pinmap.h"
Anna Bridge 181:96ed750bd169 36 #include "mbed_error.h"
Anna Bridge 181:96ed750bd169 37 #include "PeripheralPins.h"
Anna Bridge 181:96ed750bd169 38 #include <stdbool.h>
Anna Bridge 181:96ed750bd169 39
Anna Bridge 181:96ed750bd169 40 void analogin_init(analogin_t *obj, PinName pin)
Anna Bridge 181:96ed750bd169 41 {
Anna Bridge 181:96ed750bd169 42 static bool adc_calibrated = false;
Anna Bridge 181:96ed750bd169 43 uint32_t function = (uint32_t)NC;
Anna Bridge 181:96ed750bd169 44
Anna Bridge 181:96ed750bd169 45 // ADC Internal Channels "pins" (Temperature, Vref, Vbat, ...)
Anna Bridge 181:96ed750bd169 46 // are described in PinNames.h and PeripheralPins.c
Anna Bridge 181:96ed750bd169 47 // Pin value must be between 0xF0 and 0xFF
Anna Bridge 181:96ed750bd169 48 if ((pin < 0xF0) || (pin >= 0x100)) {
Anna Bridge 181:96ed750bd169 49 // Normal channels
Anna Bridge 181:96ed750bd169 50 // Get the peripheral name from the pin and assign it to the object
Anna Bridge 181:96ed750bd169 51 obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC);
Anna Bridge 181:96ed750bd169 52 // Get the functions (adc channel) from the pin and assign it to the object
Anna Bridge 181:96ed750bd169 53 function = pinmap_function(pin, PinMap_ADC);
Anna Bridge 181:96ed750bd169 54 // Configure GPIO
Anna Bridge 181:96ed750bd169 55 pinmap_pinout(pin, PinMap_ADC);
Anna Bridge 181:96ed750bd169 56 } else {
Anna Bridge 181:96ed750bd169 57 // Internal channels
Anna Bridge 181:96ed750bd169 58 obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC_Internal);
Anna Bridge 181:96ed750bd169 59 function = pinmap_function(pin, PinMap_ADC_Internal);
Anna Bridge 181:96ed750bd169 60 // No GPIO configuration for internal channels
Anna Bridge 181:96ed750bd169 61 }
Anna Bridge 181:96ed750bd169 62 MBED_ASSERT(obj->handle.Instance != (ADC_TypeDef *)NC);
Anna Bridge 181:96ed750bd169 63 MBED_ASSERT(function != (uint32_t)NC);
Anna Bridge 181:96ed750bd169 64
Anna Bridge 181:96ed750bd169 65 obj->channel = STM_PIN_CHANNEL(function);
Anna Bridge 181:96ed750bd169 66
Anna Bridge 181:96ed750bd169 67 // Save pin number for the read function
Anna Bridge 181:96ed750bd169 68 obj->pin = pin;
Anna Bridge 181:96ed750bd169 69
Anna Bridge 181:96ed750bd169 70 // Configure ADC object structures
Anna Bridge 181:96ed750bd169 71 obj->handle.State = HAL_ADC_STATE_RESET;
Anna Bridge 181:96ed750bd169 72 obj->handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2; // Asynchronous clock mode, input ADC clock
Anna Bridge 181:96ed750bd169 73 obj->handle.Init.Resolution = ADC_RESOLUTION_12B;
Anna Bridge 181:96ed750bd169 74 obj->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
Anna Bridge 181:96ed750bd169 75 obj->handle.Init.ScanConvMode = DISABLE; // Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1)
Anna Bridge 181:96ed750bd169 76 obj->handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // On STM32L1xx ADC, overrun detection is enabled only if EOC selection is set to each conversion (or transfer by DMA enabled, this is not the case in this example).
Anna Bridge 181:96ed750bd169 77 obj->handle.Init.LowPowerAutoWait = DISABLE;
Anna Bridge 181:96ed750bd169 78 obj->handle.Init.ContinuousConvMode = DISABLE; // Continuous mode disabled to have only 1 conversion at each conversion trig
Anna Bridge 181:96ed750bd169 79 obj->handle.Init.NbrOfConversion = 1; // Parameter discarded because sequencer is disabled
Anna Bridge 181:96ed750bd169 80 obj->handle.Init.DiscontinuousConvMode = DISABLE; // Parameter discarded because sequencer is disabled
Anna Bridge 181:96ed750bd169 81 obj->handle.Init.NbrOfDiscConversion = 1; // Parameter discarded because sequencer is disabled
Anna Bridge 181:96ed750bd169 82 obj->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; // Software start to trig the 1st conversion manually, without external event
Anna Bridge 181:96ed750bd169 83 obj->handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
Anna Bridge 181:96ed750bd169 84 obj->handle.Init.DMAContinuousRequests = DISABLE;
Anna Bridge 181:96ed750bd169 85 obj->handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; // DR register is overwritten with the last conversion result in case of overrun
Anna Bridge 181:96ed750bd169 86 obj->handle.Init.OversamplingMode = DISABLE; // No oversampling
Anna Bridge 181:96ed750bd169 87
Anna Bridge 181:96ed750bd169 88 // Enable ADC clock
Anna Bridge 181:96ed750bd169 89 __HAL_RCC_ADC_CLK_ENABLE();
Anna Bridge 181:96ed750bd169 90 __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_SYSCLK);
Anna Bridge 181:96ed750bd169 91
Anna Bridge 181:96ed750bd169 92 if (HAL_ADC_Init(&obj->handle) != HAL_OK) {
Anna Bridge 181:96ed750bd169 93 error("Cannot initialize ADC");
Anna Bridge 181:96ed750bd169 94 }
Anna Bridge 181:96ed750bd169 95
Anna Bridge 181:96ed750bd169 96 // ADC calibration is done only once
Anna Bridge 181:96ed750bd169 97 if (!adc_calibrated) {
Anna Bridge 181:96ed750bd169 98 adc_calibrated = true;
Anna Bridge 181:96ed750bd169 99 HAL_ADCEx_Calibration_Start(&obj->handle, ADC_SINGLE_ENDED);
Anna Bridge 181:96ed750bd169 100 }
Anna Bridge 181:96ed750bd169 101 }
Anna Bridge 181:96ed750bd169 102
Anna Bridge 181:96ed750bd169 103 uint16_t adc_read(analogin_t *obj)
Anna Bridge 181:96ed750bd169 104 {
Anna Bridge 181:96ed750bd169 105 ADC_ChannelConfTypeDef sConfig = {0};
Anna Bridge 181:96ed750bd169 106
Anna Bridge 181:96ed750bd169 107 // Configure ADC channel
Anna Bridge 181:96ed750bd169 108 switch (obj->channel) {
Anna Bridge 181:96ed750bd169 109 case 0:
Anna Bridge 181:96ed750bd169 110 sConfig.Channel = ADC_CHANNEL_VREFINT;
Anna Bridge 181:96ed750bd169 111 break;
Anna Bridge 181:96ed750bd169 112 case 1:
Anna Bridge 181:96ed750bd169 113 sConfig.Channel = ADC_CHANNEL_1;
Anna Bridge 181:96ed750bd169 114 break;
Anna Bridge 181:96ed750bd169 115 case 2:
Anna Bridge 181:96ed750bd169 116 sConfig.Channel = ADC_CHANNEL_2;
Anna Bridge 181:96ed750bd169 117 break;
Anna Bridge 181:96ed750bd169 118 case 3:
Anna Bridge 181:96ed750bd169 119 sConfig.Channel = ADC_CHANNEL_3;
Anna Bridge 181:96ed750bd169 120 break;
Anna Bridge 181:96ed750bd169 121 case 4:
Anna Bridge 181:96ed750bd169 122 sConfig.Channel = ADC_CHANNEL_4;
Anna Bridge 181:96ed750bd169 123 break;
Anna Bridge 181:96ed750bd169 124 case 5:
Anna Bridge 181:96ed750bd169 125 sConfig.Channel = ADC_CHANNEL_5;
Anna Bridge 181:96ed750bd169 126 break;
Anna Bridge 181:96ed750bd169 127 case 6:
Anna Bridge 181:96ed750bd169 128 sConfig.Channel = ADC_CHANNEL_6;
Anna Bridge 181:96ed750bd169 129 break;
Anna Bridge 181:96ed750bd169 130 case 7:
Anna Bridge 181:96ed750bd169 131 sConfig.Channel = ADC_CHANNEL_7;
Anna Bridge 181:96ed750bd169 132 break;
Anna Bridge 181:96ed750bd169 133 case 8:
Anna Bridge 181:96ed750bd169 134 sConfig.Channel = ADC_CHANNEL_8;
Anna Bridge 181:96ed750bd169 135 break;
Anna Bridge 181:96ed750bd169 136 case 9:
Anna Bridge 181:96ed750bd169 137 sConfig.Channel = ADC_CHANNEL_9;
Anna Bridge 181:96ed750bd169 138 break;
Anna Bridge 181:96ed750bd169 139 case 10:
Anna Bridge 181:96ed750bd169 140 sConfig.Channel = ADC_CHANNEL_10;
Anna Bridge 181:96ed750bd169 141 break;
Anna Bridge 181:96ed750bd169 142 case 11:
Anna Bridge 181:96ed750bd169 143 sConfig.Channel = ADC_CHANNEL_11;
Anna Bridge 181:96ed750bd169 144 break;
Anna Bridge 181:96ed750bd169 145 case 12:
Anna Bridge 181:96ed750bd169 146 sConfig.Channel = ADC_CHANNEL_12;
Anna Bridge 181:96ed750bd169 147 break;
Anna Bridge 181:96ed750bd169 148 case 13:
Anna Bridge 181:96ed750bd169 149 sConfig.Channel = ADC_CHANNEL_13;
Anna Bridge 181:96ed750bd169 150 break;
Anna Bridge 181:96ed750bd169 151 case 14:
Anna Bridge 181:96ed750bd169 152 sConfig.Channel = ADC_CHANNEL_14;
Anna Bridge 181:96ed750bd169 153 break;
Anna Bridge 181:96ed750bd169 154 case 15:
Anna Bridge 181:96ed750bd169 155 sConfig.Channel = ADC_CHANNEL_15;
Anna Bridge 181:96ed750bd169 156 break;
Anna Bridge 181:96ed750bd169 157 case 16:
Anna Bridge 181:96ed750bd169 158 sConfig.Channel = ADC_CHANNEL_16;
Anna Bridge 181:96ed750bd169 159 break;
Anna Bridge 181:96ed750bd169 160 case 17:
Anna Bridge 181:96ed750bd169 161 sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
Anna Bridge 181:96ed750bd169 162 break;
Anna Bridge 181:96ed750bd169 163 case 18:
Anna Bridge 181:96ed750bd169 164 sConfig.Channel = ADC_CHANNEL_VBAT;
Anna Bridge 181:96ed750bd169 165 break;
Anna Bridge 181:96ed750bd169 166 default:
Anna Bridge 181:96ed750bd169 167 return 0;
Anna Bridge 181:96ed750bd169 168 }
Anna Bridge 181:96ed750bd169 169
Anna Bridge 181:96ed750bd169 170 sConfig.Rank = ADC_REGULAR_RANK_1;
Anna Bridge 181:96ed750bd169 171 sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5;
Anna Bridge 181:96ed750bd169 172 sConfig.SingleDiff = ADC_SINGLE_ENDED;
Anna Bridge 181:96ed750bd169 173 sConfig.OffsetNumber = ADC_OFFSET_NONE;
Anna Bridge 181:96ed750bd169 174 sConfig.Offset = 0;
Anna Bridge 181:96ed750bd169 175
Anna Bridge 181:96ed750bd169 176 HAL_ADC_ConfigChannel(&obj->handle, &sConfig);
Anna Bridge 181:96ed750bd169 177
Anna Bridge 181:96ed750bd169 178 HAL_ADC_Start(&obj->handle); // Start conversion
Anna Bridge 181:96ed750bd169 179
Anna Bridge 181:96ed750bd169 180 // Wait end of conversion and get value
Anna Bridge 181:96ed750bd169 181 if (HAL_ADC_PollForConversion(&obj->handle, 10) == HAL_OK) {
Anna Bridge 181:96ed750bd169 182 return (uint16_t)HAL_ADC_GetValue(&obj->handle);
Anna Bridge 181:96ed750bd169 183 } else {
Anna Bridge 181:96ed750bd169 184 return 0;
Anna Bridge 181:96ed750bd169 185 }
Anna Bridge 181:96ed750bd169 186 }
Anna Bridge 181:96ed750bd169 187
Anna Bridge 181:96ed750bd169 188 #endif