19
19
#include "mbed_assert.h"
20
20
#include "mbed_error.h"
21
21
#include "mbed_debug.h"
22
- #include "mbed_wait_api.h"
23
22
#include "cmsis.h"
24
23
#include "pinmap.h"
25
24
#include "PeripheralPins.h"
26
25
27
- void analogin_init (analogin_t * obj , PinName pin )
26
+
27
+ #if STATIC_PINMAP_READY
28
+ #define ANALOGIN_INIT_DIRECT analogin_init_direct
29
+ void analogin_init_direct (analogin_t * obj , const PinMap * pinmap )
30
+ #else
31
+ #define ANALOGIN_INIT_DIRECT _analogin_init_direct
32
+ static void _analogin_init_direct (analogin_t * obj , const PinMap * pinmap )
33
+ #endif
28
34
{
29
- uint32_t function = (uint32_t )NC ;
35
+ uint32_t function = (uint32_t )pinmap -> function ;
36
+
37
+ // Get the peripheral name from the pin and assign it to the object
38
+ obj -> handle .Instance = (ADC_TypeDef * )pinmap -> peripheral ;
30
39
31
40
// ADC Internal Channels "pins" (Temperature, Vref, Vbat, ...)
32
41
// are described in PinNames.h and PeripheralPins.c
33
42
// Pin value must be between 0xF0 and 0xFF
34
- if ((pin < 0xF0 ) || (pin >= 0x100 )) {
43
+ if ((pinmap -> pin < 0xF0 ) || (pinmap -> pin >= 0x100 )) {
35
44
// Normal channels
36
- // Get the peripheral name from the pin and assign it to the object
37
- obj -> handle .Instance = (ADC_TypeDef * )pinmap_peripheral (pin , PinMap_ADC );
38
- // Get the functions (adc channel) from the pin and assign it to the object
39
- function = pinmap_function (pin , PinMap_ADC );
45
+
40
46
// Configure GPIO
41
- pinmap_pinout (pin , PinMap_ADC );
47
+ pin_function (pinmap -> pin , pinmap -> function );
48
+ pin_mode (pinmap -> pin , PullNone );
42
49
} else {
43
50
// Internal channels
44
- obj -> handle .Instance = (ADC_TypeDef * )pinmap_peripheral (pin , PinMap_ADC_Internal );
45
- function = pinmap_function (pin , PinMap_ADC_Internal );
46
51
// No GPIO configuration for internal channels
47
52
}
48
53
MBED_ASSERT (obj -> handle .Instance != (ADC_TypeDef * )NC );
@@ -51,58 +56,77 @@ void analogin_init(analogin_t *obj, PinName pin)
51
56
obj -> channel = STM_PIN_CHANNEL (function );
52
57
53
58
// Save pin number for the read function
54
- obj -> pin = pin ;
59
+ obj -> pin = pinmap -> pin ;
55
60
56
61
// Configure ADC object structures
57
62
obj -> handle .State = HAL_ADC_STATE_RESET ;
58
- obj -> handle .Init .ClockPrescaler = ADC_CLOCK_ASYNC_DIV2 ; // Asynchronous clock mode, input ADC clock
63
+ obj -> handle .Init .ClockPrescaler = ADC_CLOCK_ASYNC_DIV2 ;
59
64
obj -> handle .Init .Resolution = ADC_RESOLUTION_12B ;
60
65
obj -> handle .Init .DataAlign = ADC_DATAALIGN_RIGHT ;
61
- obj -> handle .Init .ScanConvMode = ADC_SCAN_DISABLE ; // Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1)
62
- 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).
66
+ obj -> handle .Init .ScanConvMode = ADC_SCAN_DISABLE ;
67
+ obj -> handle .Init .EOCSelection = ADC_EOC_SINGLE_CONV ;
63
68
obj -> handle .Init .LowPowerAutoWait = DISABLE ;
64
- obj -> handle .Init .ContinuousConvMode = DISABLE ; // Continuous mode disabled to have only 1 conversion at each conversion trig
65
- obj -> handle .Init .NbrOfConversion = 1 ; // Parameter discarded because sequencer is disabled
66
- obj -> handle .Init .DiscontinuousConvMode = DISABLE ; // Parameter discarded because sequencer is disabled
67
- //obj->handle.Init.NbrOfDiscConversion = 1; // Parameter discarded because sequencer is disabled
68
- obj -> handle .Init .ExternalTrigConv = ADC_SOFTWARE_START ; // Software start to trig the 1st conversion manually, without external event
69
+ obj -> handle .Init .ContinuousConvMode = DISABLE ;
70
+ obj -> handle .Init .NbrOfConversion = 1 ;
71
+ obj -> handle .Init .DiscontinuousConvMode = DISABLE ;
72
+ obj -> handle .Init .ExternalTrigConv = ADC_SOFTWARE_START ;
69
73
obj -> handle .Init .ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE ;
70
74
obj -> handle .Init .DMAContinuousRequests = DISABLE ;
71
- obj -> handle .Init .Overrun = ADC_OVR_DATA_OVERWRITTEN ; // DR register is overwritten with the last conversion result in case of overrun
72
- obj -> handle .Init .OversamplingMode = DISABLE ; // No oversampling
73
-
74
- // Enable ADC core clock
75
- __HAL_RCC_ADC_CLK_ENABLE ();
76
-
77
- // Enable ADC conversion clock.
78
- // Only necessary with asynchronous clock source
75
+ obj -> handle .Init .Overrun = ADC_OVR_DATA_OVERWRITTEN ;
76
+ obj -> handle .Init .LowPowerAutoPowerOff = DISABLE ;
77
+ obj -> handle .Init .SamplingTimeCommon1 = ADC_SAMPLETIME_19CYCLES_5 ;
78
+ obj -> handle .Init .SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5 ;
79
+ obj -> handle .Init .OversamplingMode = DISABLE ;
80
+ obj -> handle .Init .Oversampling .Ratio = 0 ; // workaround
81
+ obj -> handle .Init .Oversampling .RightBitShift = 0 ; // workaround
82
+ obj -> handle .Init .Oversampling .TriggeredMode = 0 ; // workaround
83
+ obj -> handle .Init .TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH ;
84
+
85
+ // Enable ADC clock
79
86
__HAL_RCC_ADC_CONFIG (RCC_ADCCLKSOURCE_SYSCLK );
87
+ __HAL_RCC_ADC_CLK_ENABLE ();
80
88
81
89
if (HAL_ADC_Init (& obj -> handle ) != HAL_OK ) {
82
- error ("ADC initialization failed\r\n " );
90
+ error ("Cannot initialize ADC " );
83
91
}
84
92
85
93
// ADC calibration is done only once
86
- //if (!HAL_ADCEx_Calibration_GetValue(&obj->handle, ADC_SINGLE_ENDED)) {
87
- // HAL_ADCEx_Calibration_Start(&obj->handle, ADC_SINGLE_ENDED);
88
- //}
94
+ if (!HAL_ADCEx_Calibration_GetValue (& obj -> handle )) {
95
+ if (HAL_ADCEx_Calibration_Start (& obj -> handle ) != HAL_OK ) {
96
+ error ("HAL_ADCEx_Calibration_Start error" );
97
+ }
98
+ }
99
+ }
100
+
101
+ void analogin_init (analogin_t * obj , PinName pin )
102
+ {
103
+ int peripheral ;
104
+ int function ;
105
+
106
+ if ((pin < 0xF0 ) || (pin >= 0x100 )) {
107
+ peripheral = (int )pinmap_peripheral (pin , PinMap_ADC );
108
+ function = (int )pinmap_find_function (pin , PinMap_ADC );
109
+ } else {
110
+ peripheral = (int )pinmap_peripheral (pin , PinMap_ADC_Internal );
111
+ function = (int )pinmap_find_function (pin , PinMap_ADC_Internal );
112
+ }
113
+
114
+ const PinMap static_pinmap = {pin , peripheral , function };
115
+
116
+ ANALOGIN_INIT_DIRECT (obj , & static_pinmap );
89
117
}
90
118
119
+
91
120
uint16_t adc_read (analogin_t * obj )
92
121
{
93
122
ADC_ChannelConfTypeDef sConfig = {0 };
94
123
95
- // Configure ADC channel
96
124
sConfig .Rank = ADC_REGULAR_RANK_1 ;
97
- //sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5;
98
- //sConfig.SingleDiff = ADC_SINGLE_ENDED;
99
- //sConfig.OffsetNumber = ADC_OFFSET_NONE;
100
- //sConfig.Offset = 0;
125
+ sConfig .SamplingTime = ADC_SAMPLINGTIME_COMMON_1 ;
101
126
102
127
switch (obj -> channel ) {
103
128
case 0 :
104
- sConfig .Channel = ADC_CHANNEL_VREFINT ;
105
- //sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; // Minimum ADC sampling time when reading the internal reference voltage is 4us
129
+ sConfig .Channel = ADC_CHANNEL_0 ;
106
130
break ;
107
131
case 1 :
108
132
sConfig .Channel = ADC_CHANNEL_1 ;
@@ -138,55 +162,41 @@ uint16_t adc_read(analogin_t *obj)
138
162
sConfig .Channel = ADC_CHANNEL_11 ;
139
163
break ;
140
164
case 12 :
141
- sConfig .Channel = ADC_CHANNEL_12 ;
165
+ sConfig .Channel = ADC_CHANNEL_TEMPSENSOR ;
166
+ sConfig .SamplingTime = ADC_SAMPLINGTIME_COMMON_2 ;
142
167
break ;
143
168
case 13 :
144
- sConfig .Channel = ADC_CHANNEL_13 ;
169
+ sConfig .Channel = ADC_CHANNEL_VREFINT ;
170
+ sConfig .SamplingTime = ADC_SAMPLINGTIME_COMMON_2 ;
145
171
break ;
146
172
case 14 :
147
- sConfig .Channel = ADC_CHANNEL_14 ;
148
- break ;
149
- case 15 :
150
- sConfig .Channel = ADC_CHANNEL_15 ;
151
- break ;
152
- case 16 :
153
- sConfig .Channel = ADC_CHANNEL_16 ;
154
- break ;
155
- case 17 :
156
- sConfig .Channel = ADC_CHANNEL_TEMPSENSOR ;
157
- //sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; // Minimum ADC sampling time when reading the temperature is 5us
158
- break ;
159
- case 18 :
160
173
sConfig .Channel = ADC_CHANNEL_VBAT ;
161
- // sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5; // Minimum ADC sampling time when reading the VBAT is 12us
174
+ sConfig .SamplingTime = ADC_SAMPLINGTIME_COMMON_2 ;
162
175
break ;
163
176
default :
164
177
return 0 ;
165
178
}
166
179
167
180
if (HAL_ADC_ConfigChannel (& obj -> handle , & sConfig ) != HAL_OK ) {
168
- debug ("ADC channel configuration failed\r \n" );
181
+ debug ("HAL_ADC_ConfigChannel error \n" );
169
182
}
170
183
171
- // Start conversion
172
184
if (HAL_ADC_Start (& obj -> handle ) != HAL_OK ) {
173
- debug ("ADC start of conversion failed\r \n" );
185
+ debug ("HAL_ADC_Start error \n" );
174
186
}
175
187
176
188
// Wait end of conversion and get value
177
189
uint16_t adcValue = 0 ;
178
- if (HAL_ADC_PollForConversion (& obj -> handle , 10 ) == HAL_OK ) {
190
+ if (HAL_ADC_PollForConversion (& obj -> handle , 100 ) == HAL_OK ) {
179
191
adcValue = (uint16_t )HAL_ADC_GetValue (& obj -> handle );
180
192
}
181
193
182
- if (HAL_ADC_Stop (& obj -> handle ) != HAL_OK ) {
183
- debug ("HAL_ADC_Stop failed\r\n" );
184
- }
185
-
186
194
LL_ADC_SetCommonPathInternalCh (__LL_ADC_COMMON_INSTANCE ((& obj -> handle )-> Instance ), LL_ADC_PATH_INTERNAL_NONE );
195
+
187
196
return adcValue ;
188
197
}
189
198
199
+
190
200
const PinMap * analogin_pinmap ()
191
201
{
192
202
return PinMap_ADC ;
0 commit comments