Skip to content

Commit 45fe617

Browse files
author
Jan Kamidra
committed
add ADC and DAC
1 parent f016f1d commit 45fe617

File tree

5 files changed

+372
-28
lines changed

5 files changed

+372
-28
lines changed

targets/TARGET_STM/TARGET_STM32U0/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ add_library(mbed-stm32u0 INTERFACE)
99
target_sources(mbed-stm32u0
1010
INTERFACE
1111
clock_cfg/system_clock.c
12+
analogin_device.c
13+
analogout_device.c
1214
gpio_irq_device.c
1315
serial_device.c
1416
)

targets/TARGET_STM/TARGET_STM32U0/TARGET_STM32U083xC/TARGET_NUCLEO_U083RC/PeripheralPinMaps.h

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,30 +55,30 @@
5555
//*** ADC ***
5656

5757
MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_ADC[] = {
58-
{PA_0, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 4, 0)}, // ADC1_IN4
59-
{PA_1, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC1_IN5
60-
{PA_2, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC1_IN6 // ST-Link VCP TX
61-
{PA_3, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC1_IN7 // ST-Link VCP RX
62-
{PA_4, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC1_IN8
63-
{PA_5, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC1_IN9 // Mbed LED1
64-
{PA_6, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 10, 0)}, // ADC1_IN10
65-
{PA_7, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 14, 0)}, // ADC1_IN14
66-
{PB_0, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 17, 0)}, // ADC1_IN17
67-
{PB_1, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 18, 0)}, // ADC1_IN18
68-
{PC_0, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 0, 0)}, // ADC1_IN0
69-
{PC_1, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // ADC1_IN1
70-
{PC_2, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // ADC1_IN2
71-
{PC_3, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC1_IN3
72-
{PC_4, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 15, 0)}, // ADC1_IN15
73-
{PC_5, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 16, 0)}, // ADC1_IN16
58+
{PA_0, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 4, 0)}, // ADC1_IN4
59+
{PA_1, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC1_IN5
60+
{PA_2, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC1_IN6 // ST-Link VCP TX
61+
{PA_3, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC1_IN7 // ST-Link VCP RX
62+
{PA_4, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC1_IN8
63+
{PA_5, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC1_IN9 // Mbed LED1
64+
{PA_6, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 10, 0)}, // ADC1_IN10
65+
{PA_7, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 14, 0)}, // ADC1_IN14
66+
{PB_0, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 17, 0)}, // ADC1_IN17
67+
{PB_1, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 18, 0)}, // ADC1_IN18
68+
{PC_0, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 0, 0)}, // ADC1_IN0
69+
{PC_1, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // ADC1_IN1
70+
{PC_2, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // ADC1_IN2
71+
{PC_3, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC1_IN3
72+
{PC_4, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 15, 0)}, // ADC1_IN15
73+
{PC_5, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 16, 0)}, // ADC1_IN16
7474
{NC, NC, 0}
7575
};
7676

77-
// !!! SECTION TO BE CHECKED WITH DEVICE REFERENCE MANUAL
77+
// ADC internall according to REFERENCE MANUAL
7878
MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_ADC_Internal[] = {
79-
// {ADC_TEMP, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 16, 0)},
80-
// {ADC_VREF, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 17, 0)},
81-
// {ADC_VBAT, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 18, 0)},
79+
{ADC_TEMP, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 11, 0)}, // ADC1_IN11
80+
{ADC_VREF, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 12, 0)}, // ADC1_IN12
81+
{ADC_VBAT, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 13, 0)}, // ADC1_IN13
8282
{NC, NC, 0}
8383
};
8484

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
/* mbed Microcontroller Library
2+
* SPDX-License-Identifier: BSD-3-Clause
3+
******************************************************************************
4+
*
5+
* Copyright (c) 2025 STMicroelectronics.
6+
* All rights reserved.
7+
*
8+
* This software component is licensed by ST under BSD 3-Clause license,
9+
* the "License"; You may not use this file except in compliance with the
10+
* License. You may obtain a copy of the License at:
11+
* opensource.org/licenses/BSD-3-Clause
12+
*
13+
******************************************************************************
14+
*/
15+
16+
#include "mbed_assert.h"
17+
#include "analogin_api.h"
18+
19+
#if DEVICE_ANALOGIN
20+
21+
#include "mbed_wait_api.h"
22+
#include "cmsis.h"
23+
#include "pinmap.h"
24+
#include "mbed_error.h"
25+
#include "PeripheralPins.h"
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
34+
{
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;
39+
40+
// ADC Internal Channels "pins" (Temperature, Vref, Vbat, ...)
41+
// are described in PinNames.h and PeripheralPins.c
42+
// Pin value must be between 0xF0 and 0xFF
43+
if ((pinmap->pin < 0xF0) || (pinmap->pin >= 0x100)) {
44+
// Configure GPIO
45+
pin_function(pinmap->pin, pinmap->function);
46+
pin_mode(pinmap->pin, PullNone);
47+
} else {
48+
// Internal channels
49+
obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pinmap->pin, PinMap_ADC_Internal);
50+
function = pinmap_function(pinmap->pin, PinMap_ADC_Internal);
51+
}
52+
MBED_ASSERT(obj->handle.Instance != (ADC_TypeDef *)NC);
53+
MBED_ASSERT(function != (uint32_t)NC);
54+
55+
obj->channel = STM_PIN_CHANNEL(function);
56+
57+
// Save pin number for the read function
58+
obj->pin = pinmap->pin;
59+
60+
if (obj->handle.Instance == ADC1) {
61+
__HAL_RCC_ADC_CLK_ENABLE();
62+
} else {
63+
error("ADC instance error\n");
64+
}
65+
66+
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
67+
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
68+
PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_SYSCLK;
69+
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
70+
error("HAL_RCCEx_PeriphCLKConfig\n");
71+
}
72+
73+
// Configure ADC object structures
74+
obj->handle.State = HAL_ADC_STATE_RESET;
75+
obj->handle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
76+
obj->handle.Init.Resolution = ADC_RESOLUTION_12B;
77+
obj->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
78+
obj->handle.Init.ScanConvMode = ADC_SCAN_DISABLE;
79+
obj->handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
80+
obj->handle.Init.LowPowerAutoWait = DISABLE;
81+
obj->handle.Init.LowPowerAutoPowerOff = DISABLE;
82+
obj->handle.Init.ContinuousConvMode = DISABLE;
83+
obj->handle.Init.NbrOfConversion = 1;
84+
obj->handle.Init.DiscontinuousConvMode = DISABLE;
85+
obj->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
86+
obj->handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
87+
obj->handle.Init.DMAContinuousRequests = DISABLE;
88+
obj->handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
89+
obj->handle.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_12CYCLES_5;
90+
obj->handle.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_1CYCLE_5;
91+
obj->handle.Init.OversamplingMode = DISABLE;
92+
obj->handle.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
93+
if (HAL_ADC_Init(&obj->handle) != HAL_OK) {
94+
error("Cannot initialize ADC\n");
95+
}
96+
97+
if (HAL_ADCEx_Calibration_Start(&obj->handle) != HAL_OK) {
98+
error("HAL_ADCEx_Calibration_Start\n");
99+
}
100+
}
101+
102+
void analogin_init(analogin_t *obj, PinName pin)
103+
{
104+
int peripheral;
105+
int function;
106+
107+
if ((pin < 0xF0) || (pin >= 0x100)) {
108+
peripheral = (int)pinmap_peripheral(pin, PinMap_ADC);
109+
function = (int)pinmap_find_function(pin, PinMap_ADC);
110+
} else {
111+
peripheral = (int)pinmap_peripheral(pin, PinMap_ADC_Internal);
112+
function = (int)pinmap_find_function(pin, PinMap_ADC_Internal);
113+
}
114+
115+
const PinMap static_pinmap = {pin, peripheral, function};
116+
117+
ANALOGIN_INIT_DIRECT(obj, &static_pinmap);
118+
}
119+
120+
121+
uint16_t adc_read(analogin_t *obj)
122+
{
123+
ADC_ChannelConfTypeDef sConfig = {0};
124+
125+
// Configure ADC channel
126+
sConfig.Rank = ADC_REGULAR_RANK_1;
127+
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
128+
switch (obj->channel) {
129+
case 0:
130+
sConfig.Channel = ADC_CHANNEL_0;
131+
break;
132+
case 1:
133+
sConfig.Channel = ADC_CHANNEL_1;
134+
break;
135+
case 2:
136+
sConfig.Channel = ADC_CHANNEL_2;
137+
break;
138+
case 3:
139+
sConfig.Channel = ADC_CHANNEL_3;
140+
break;
141+
case 4:
142+
sConfig.Channel = ADC_CHANNEL_4;
143+
break;
144+
case 5:
145+
sConfig.Channel = ADC_CHANNEL_5;
146+
break;
147+
case 6:
148+
sConfig.Channel = ADC_CHANNEL_6;
149+
break;
150+
case 7:
151+
sConfig.Channel = ADC_CHANNEL_7;
152+
break;
153+
case 8:
154+
sConfig.Channel = ADC_CHANNEL_8;
155+
break;
156+
case 9:
157+
sConfig.Channel = ADC_CHANNEL_9;
158+
break;
159+
case 10:
160+
sConfig.Channel = ADC_CHANNEL_10;
161+
break;
162+
case 11:
163+
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
164+
break;
165+
case 12:
166+
sConfig.Channel = ADC_CHANNEL_VREFINT;
167+
break;
168+
case 13:
169+
sConfig.Channel = ADC_CHANNEL_VBAT;
170+
break;
171+
case 14:
172+
sConfig.Channel = ADC_CHANNEL_14;
173+
break;
174+
case 15:
175+
sConfig.Channel = ADC_CHANNEL_15;
176+
break;
177+
case 16:
178+
sConfig.Channel = ADC_CHANNEL_16;
179+
break;
180+
case 17:
181+
sConfig.Channel = ADC_CHANNEL_17;
182+
break;
183+
case 18:
184+
sConfig.Channel = ADC_CHANNEL_18;
185+
break;
186+
case 19:
187+
// ADC_CHANNEL_19 is for DAC
188+
default:
189+
error("ADC channel not expected\n");
190+
}
191+
192+
if (HAL_ADC_ConfigChannel(&obj->handle, &sConfig) != HAL_OK) {
193+
error("HAL_ADC_ConfigChannel\n");
194+
}
195+
196+
if (HAL_ADC_Start(&obj->handle) != HAL_OK) {
197+
error("HAL_ADC_Start\n");
198+
}
199+
200+
// Wait end of conversion and get value
201+
uint16_t adcValue = 0;
202+
if (HAL_ADC_PollForConversion(&obj->handle, 10) != HAL_OK) {
203+
error("HAL_ADC_PollForConversion error 0x%lx\n", obj->handle.State);
204+
} else {
205+
adcValue = (uint16_t)HAL_ADC_GetValue(&obj->handle);
206+
}
207+
208+
if (HAL_ADC_Stop(&obj->handle) != HAL_OK) {
209+
error("HAL_ADC_Stop\n");
210+
}
211+
212+
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE((&obj->handle)->Instance), LL_ADC_PATH_INTERNAL_NONE);
213+
214+
return adcValue;
215+
}
216+
217+
const PinMap *analogin_pinmap()
218+
{
219+
return PinMap_ADC;
220+
}
221+
222+
#endif

0 commit comments

Comments
 (0)