xm_api_external_io.h — External Extension Port GPIO/ADC Control¶
Header:
XM_FW/XM_API/xm_api_external_io.h(shared file across Rev1.1 / Rev2.0 — some pin mappings and the power-select API are Rev2.0-only, see the 🟢 badges below) Related concept doc: 04. External IO Control API Related examples: 04_Ext_IO_Basic · 05_Ext_IO_analog · 05a_Ext_IO_DIO_to_ADC · 05b_Ext_IO_FSR_8ch · 05c_Ext_IO_Mixed_ADC · 05d_Ext_IO_DIO_ADC_Hybrid · 06_Ext_IO_Safety_Switch · 40_EMG_Proportional_Assist (power voltage switch)
This is the API for the board's side-mounted Extension Port: 8 digital I/O (DIO) pins and 4 analog input (ADC) pins. If needed, DIO pins can be dynamically switched to ADC mode to get up to 12 analog input channels. On Rev2.0, this header also includes switching the extension port's supply voltage (3.3V/5V).
When to Use¶
Use this API when you want to read values from external sensors (FSR, switches, potentiometers, etc.) connected to the board, or control external digital devices such as LEDs or relays. It's designed to feel similar to Arduino's pinMode/digitalWrite/analogRead. It's recommended to read 04. External IO Control API first for the operating principle, electrical cautions, and a list of common mistakes — this page only covers the exact signature/parameters of each function.
Function List¶
| Function / Macro | One-line description |
|---|---|
XM_SetPinMode |
Set a DIO pin's input/output/pull-up/pull-down mode |
XM_DigitalWrite |
Drive a DIO pin HIGH/LOW |
XM_DigitalRead |
Read a DIO pin's current logic level |
XM_AnalogRead |
Read an ADC pin's voltage as a normalized integer (unified across ADC1/2/3) |
XM_AnalogReadMillivolts |
Read an ADC pin's voltage in millivolts (mV) |
XM_SetAnalogReadResolution |
Set the output resolution of XM_AnalogRead's return value |
XM_GetAnalogResolution |
Query an ADC pin's native hardware resolution |
XM_GetAnalogReadResolution |
Query the currently configured output resolution |
XM_SwitchDioToAdc |
Switch a single DIO pin to a high-speed ADC3 input |
XM_SwitchAllDioToAdc |
Switch all 8 DIO pins to ADC3 inputs at once |
XM_IsDioSwitchedToAdc |
Check whether a DIO pin has been switched to ADC mode |
XM_DIO_TO_ADC_PIN (macro) |
Convert a DIO pin number to its corresponding ADC pin number |
XM_SetExtPowerVoltage 🟢 Rev 2.0 Only |
Switch the extension port's supply voltage to 3.3V/5V |
XM_AttachExternalUart 🟢 Rev 2.0 only |
Start External UART reception and register a callback |
XM_SetExternalUartBaudrate 🟢 Rev 2.0 only |
Set the External UART baud rate |
XM_SendExternalUartData 🟢 Rev 2.0 only |
Non-blocking send (max 128 B per call) |
XM_SendExternalUartDataBlocking 🟢 Rev 2.0 only |
Blocking send (Control_Setup() only) |
XM_EnsureExternalUartRxArmed 🟢 Rev 2.0 only |
Revive stalled reception (call every ~100 ms) |
XM_AttachXsensMTi630 ⚠️ not in the default build |
Attach a Xsens MTi-630 IMU to the External UART |
XM_ConfigureXsensMTi630 |
Send the Xsens MTi-630 Output Configuration once |
Function Details¶
1. Digital I/O (DIO)¶
XM_SetPinMode¶
Sets a DIO pin's operating mode (input/output/pull-up/pull-down). Must be called before using any other DIO function on that pin.
Parameters
| Name | Type | Description |
|---|---|---|
pin |
XmDioPin_t |
Pin to configure (XM_EXT_DIO_1 ~ XM_EXT_DIO_8) |
mode |
XmPinMode_t |
Target mode (XM_EXT_DIO_MODE_INPUT/_PULLUP/_PULLDOWN/_OUTPUT) |
Returns: None (void)
⚠️ Calling context: Non-real-time function. It calls HAL_GPIO_Init() internally, so do not call it inside the 1ms(1kHz) Control_Loop() — configure it once in Control_Setup().
Header wording note: the Rev2.0 source comment says "do not call inside a 2ms real-time loop," while the Rev1.1 source comment says "1ms real-time loop" — the wording differs between the two revision headers. Since the SDK-wide
Control_Loop()period is 1ms(1kHz) (see 09. Auxiliary Tasks + Data Sharing, Architecture Overview), this page standardizes on 1ms.
Example
void Control_Setup(void)
{
XM_SetPinMode(XM_EXT_DIO_3, XM_EXT_DIO_MODE_INPUT_PULLUP); // for a switch
XM_SetPinMode(XM_EXT_DIO_4, XM_EXT_DIO_MODE_OUTPUT); // for an LED
}
See also: XmPinMode_t — full list of modes
XM_DigitalWrite¶
Drives a DIO pin to a voltage level (HIGH/LOW). Only takes effect on a pin configured as XM_EXT_DIO_MODE_OUTPUT.
Parameters
| Name | Type | Description |
|---|---|---|
pin |
XmDioPin_t |
Target pin |
level |
XmLogicLevel_t |
Output level (XM_HIGH = 3.3V, XM_LOW = 0V) |
Returns: None (void)
⚠️ Calling context: Assume Control_Setup() / Control_Loop() context.
If the pin has already been switched to ADC mode via
XM_SwitchDioToAdc(), anXM_DigitalWritecall is silently ignored by a guard mechanism (see 04. External IO — Common Mistakes).
Example
See also: XM_IsDioSwitchedToAdc — check whether a pin has been switched to ADC mode
XM_DigitalRead¶
Reads a DIO pin's current voltage state.
Parameters
| Name | Type | Description |
|---|---|---|
pin |
XmDioPin_t |
Pin to check |
Returns: XmLogicLevel_t — XM_HIGH (near 3.3V) or XM_LOW (near 0V)
⚠️ Calling context: Assume Control_Setup() / Control_Loop() context.
Example
2. Analog Input (ADC) — Unified Read API¶
XM_AnalogRead¶
Reads an ADC pin's voltage as a normalized integer value. The function automatically determines which of ADC1/2/3 the pin belongs to, so the caller only needs to specify the pin number. Every pin's return value is normalized to the same output resolution (16-bit by default), so you don't need to worry about differing hardware resolutions across pins.
Parameters
| Name | Type | Description |
|---|---|---|
pin |
XmAdcPin_t |
Pin to read (XM_EXT_ADC_1 ~ XM_EXT_ADC_12) |
Returns: Normalized ADC value (0~65535 by default, range depends on the configured output resolution). 0 on an invalid pin.
XM_EXT_ADC_5~_12(the ADC3 group) only return valid values after being switched viaXM_SwitchDioToAdc(). Reading before the switch returns0(indistinguishable from a genuine 0V reading); on Rev2.0 this condition can be checked via theg_xm_adc_read_before_switchdiagnostic variable.
⚠️ Calling context: Assume Control_Setup() / Control_Loop() context. This is a read-only query, so it is safe to call repeatedly inside the 1ms loop.
Example
void Control_Setup(void) {
XM_SetAnalogReadResolution(12); // 12-bit mode (0~4095)
XM_SwitchDioToAdc(XM_EXT_DIO_1);
XM_SwitchDioToAdc(XM_EXT_DIO_2);
}
void Control_Loop(void) {
uint16_t fsr1 = XM_AnalogRead(XM_EXT_ADC_5); // 0~4095
uint16_t fsr2 = XM_AnalogRead(XM_EXT_ADC_6); // 0~4095
}
See also: XM_AnalogReadMillivolts, XM_SetAnalogReadResolution
XM_AnalogReadMillivolts¶
Reads an ADC pin's voltage in millivolts (mV). This converts directly from the native raw value, so it always keeps the same accuracy regardless of the XM_SetAnalogReadResolution() setting.
Parameters
| Name | Type | Description |
|---|---|---|
pin |
XmAdcPin_t |
Pin to read (XM_EXT_ADC_1 ~ XM_EXT_ADC_12) |
Returns: Voltage in millivolts (0 ~ 3300, based on VREF = 3.3V). 0 on an invalid pin.
⚠️ Calling context: Assume Control_Setup() / Control_Loop() context.
Example
uint16_t mv = XM_AnalogReadMillivolts(XM_EXT_ADC_1);
float voltage = mv / 1000.0f; // mv == 1650 → 1.65V
XM_SetAnalogReadResolution¶
Sets the output resolution of XM_AnalogRead()'s return value (compatible with Arduino's analogReadResolution()). This does not change the actual hardware ADC resolution — it normalizes the value in software via left/right bit shifting.
Parameters
| Name | Type | Description |
|---|---|---|
bits |
uint8_t |
Output resolution (8, 10, 12, 14, 16) |
Returns: None (void). Default is 16.
⚠️ Calling context: Call it once in Control_Setup(), not from an ISR. The setting applies globally to every subsequent XM_AnalogRead() call.
Example
XM_GetAnalogResolution¶
Queries the specified ADC pin's hardware-native resolution. Use this to check what bit depth the actual ADC operates at.
Parameters
| Name | Type | Description |
|---|---|---|
pin |
XmAdcPin_t |
ADC pin to query |
Returns: Native resolution (bit count). 0 on an invalid pin.
Per-pin native resolution differs by board revision — see the XmAdcPin_t table below.
⚠️ Header wording inconsistency (flagged): The
@codeexample comment inside the Rev2.0xm_api_external_io.hstatesXM_EXT_ADC_1=12-bit andXM_EXT_ADC_2=16-bit (this appears to be copied verbatim from the Rev1.1 example). However, the same file'sXmAdcPin_tenum comment (/* ADC1 fixed pins (Rev2.0: all ADC1 16-bit, always available) */) and the Rev 2.0 hardware pinmap document both state thatXM_EXT_ADC_1~4are 16-bit. This page follows the latter (the enum comment + pinmap doc). To be certain, callXM_GetAnalogResolution()on the actual board.
Example
XM_GetAnalogReadResolution¶
Queries the output resolution currently configured by XM_SetAnalogReadResolution().
Parameters: None
Returns: Current output resolution (bit count, default 16)
⚠️ Calling context: Assume Control_Setup() / Control_Loop() context.
Example
3. DIO → ADC Dynamic Switching (10kHz High-Speed Analog Input)¶
XM_SwitchDioToAdc¶
Switches an external DIO pin to a high-speed ADC3 input. By default, DIO pins (D1~D8) are digital I/O; calling this function switches the given pin to a 16-bit ADC3 analog input. ADC3 supports up to 8 simultaneous scan channels at 10kHz sampling.
Parameters
| Name | Type | Description |
|---|---|---|
pin |
XmDioPin_t |
DIO pin to switch (XM_EXT_DIO_1 ~ XM_EXT_DIO_8) |
Returns: bool — true (success), false (failure)
⚠️ Calling context: Non-real-time function. Call it only during initialization (Control_Setup()).
After switching, the pin can no longer be restored to digital GPIO (a reboot is required) — this is intentional, safety-oriented behavior.
Example
void Control_Setup(void) {
XM_SetAnalogReadResolution(12);
for (int i = 0; i < 8; i++) {
XM_SwitchDioToAdc(XM_EXT_DIO_1 + i); // DIO 1~8 → ADC3
}
}
void Control_Loop(void) {
uint16_t fsr[8];
for (int i = 0; i < 8; i++) {
fsr[i] = XM_AnalogRead(XM_EXT_ADC_5 + i); // all 0~4095
}
}
See also: XM_SwitchAllDioToAdc — batch-switch version for all 8 pins, XM_DIO_TO_ADC_PIN — conversion macro
XM_SwitchAllDioToAdc¶
A convenience function that switches all DIO pins (D1~D8) to ADC3 inputs at once. Use this to switch all 8 channels without a loop.
Parameters: None
Returns: bool — true (all succeeded), false (one or more failed)
⚠️ Calling context: Non-real-time function. Like XM_SwitchDioToAdc(), call it only in Control_Setup().
Example
void Control_Setup(void) {
XM_SetAnalogReadResolution(12);
XM_SwitchAllDioToAdc(); // Batch-switch DIO 1~8 → ADC3
}
XM_IsDioSwitchedToAdc¶
Checks whether a DIO pin is currently switched to ADC mode.
Parameters
| Name | Type | Description |
|---|---|---|
pin |
XmDioPin_t |
DIO pin to check (XM_EXT_DIO_1 ~ XM_EXT_DIO_8) |
Returns: bool — true (ADC mode), false (GPIO mode or an invalid pin)
⚠️ Calling context: Assume Control_Setup() / Control_Loop() context.
Example
XM_SwitchDioToAdc(XM_EXT_DIO_1);
if (XM_IsDioSwitchedToAdc(XM_EXT_DIO_1)) {
// ADC mode — XM_AnalogRead() is now usable
}
XM_DIO_TO_ADC_PIN (macro)¶
Converts a DIO pin number to its corresponding ADC pin number. Use this after XM_SwitchDioToAdc() to intuitively obtain the ADC pin value to pass into XM_AnalogRead().
Parameters
| Name | Type | Description |
|---|---|---|
dio |
XmDioPin_t |
DIO pin number (XM_EXT_DIO_1 ~ XM_EXT_DIO_8) |
Returns: The corresponding XmAdcPin_t value (XM_EXT_ADC_5 ~ XM_EXT_ADC_12)
⚠️ Calling context: A preprocessor macro — no restriction (compile-time substitution).
Example
XM_SwitchDioToAdc(XM_EXT_DIO_1);
uint16_t val = XM_AnalogRead(XM_DIO_TO_ADC_PIN(XM_EXT_DIO_1)); // reads XM_EXT_ADC_5
4. Extension Port Power Voltage 🟢 Rev 2.0 Only¶
XM_SetExtPowerVoltage¶
🟢 Rev 2.0 Only — This function and the
XmExtPwrVoltage_ttype do not exist in the Rev1.1 header.
Switches the extension port's sensor supply voltage to 3.3V or 5V (controls the power MUX via the EXT_PWR_SEL_5V board signal, PE3 GPIO). The default is 3.3V; switch to 5V when using an external sensor that operates at 5V.
Parameters
| Name | Type | Description |
|---|---|---|
voltage |
XmExtPwrVoltage_t |
XM_EXT_PWR_3V3 (3.3V, default) or XM_EXT_PWR_5V (5V) |
Returns: None (void)
⚠️ Calling context: Non-real-time function (per the header). Call it in Control_Setup().
⚠️ This voltage powers (drives) the sensor. The ADC signal input range is always 0~3.3V, regardless of the supply voltage. If a sensor driven at 5V outputs a signal above 3.3V, the ADC pin can be damaged — verify the signal line stays within 0~3.3V, and add a voltage divider if needed.
Example
void Control_Setup(void) {
XM_SetExtPowerVoltage(XM_EXT_PWR_5V); // Drive a 5V sensor
XM_SwitchDioToAdc(XM_EXT_DIO_1); // DIO_1 → ADC (XM_EXT_ADC_5)
// Then read the sensor voltage (mV) with XM_AnalogReadMillivolts(XM_EXT_ADC_5)
}
See also: XmExtPwrVoltage_t, 40_EMG_Proportional_Assist example
5. External UART IMU Attachment (Xsens MTi-630)¶
⚠️ As of v2.7.0 these two functions are not in the default build. The single External UART port cannot be shared between the general-purpose Serial API and the Xsens driver (there is only one receive-callback slot per port, and whoever registers last silently overwrites the other).
XM_EXTERNAL_UART_XSENS_ENABLEinXM_FW/System/Config/module.htherefore selects one or the other at build time, and it defaults to0(general-purpose Serial).
- Default build (
0) → use the general-purpose External Serial API. Calling the two functions below gives an "undeclared function" compile error.- To use the Xsens driver, set
XM_EXTERNAL_UART_XSENS_ENABLEto1inmodule.hand rebuild. The general-purpose Serial API then disappears instead.This is deliberate: the build stops rather than misbehaving silently.
XM_AttachXsensMTi630¶
Attaches an external Xsens MTi-630 IMU sensor to the External UART port. Call it once in Control_Setup(); afterward you can access sensor data through the XM.status.ext_imu.* fields. It is safe to call even when no sensor is physically connected — plugging in the cable automatically transitions it to the OPERATIONAL state.
⚠️ Revision-specific behavior — the function signature and user code are identical across both revisions, but the underlying hardware port they attach to differs. - Rev 2.0: Attaches to a dedicated USART2 port (PD5=TX, PD6=RX, 921600bps). No resource conflict with any ADC/DIO pin currently in use. - Rev 1.1: Attaches by switching PA0/PA1 to UART4 internally and dynamically. After this call,
XM_EXT_ADC_1/XM_EXT_ADC_3(PA0/PA1) can no longer be used as ADC — useXM_EXT_ADC_2/XM_EXT_ADC_4(PA0_C/PA1_C) instead. If not called, PA0/PA1 remain available as ADC.
Parameters: None
Returns: None (void)
⚠️ Calling context: Call once in Control_Setup() (per the header). Not intended for repeated calls inside Control_Loop().
Example
void Control_Setup(void)
{
XM_AttachXsensMTi630();
// If this is a brand-new/factory-reset sensor:
// XM_ConfigureXsensMTi630();
}
See also: XM_ConfigureXsensMTi630, 04. External IO — Note on External IMU Usage
XM_ConfigureXsensMTi630¶
Sends the Xsens MTi-630's Output Configuration (1kHz Quaternion + Acc + Gyro output) once. This is only needed for a brand-new or factory-reset sensor — if the sensor's EEPROM already retains its configuration (a sensor being reused), this call is unnecessary.
Parameters: None
Returns: None (void)
⚠️ Calling context: Blocks for about 1 second, so do not call it inside the 1ms Control_Loop(). Call it only in Control_Setup() or an equivalent non-real-time point, and only after calling XM_AttachXsensMTi630() first.
Example
void Control_Setup(void)
{
XM_AttachXsensMTi630();
XM_ConfigureXsensMTi630(); // One-time setup for a new sensor (blocks ~1s)
}
See also: XM_AttachXsensMTi630
6. General-purpose External Serial API 🟢 Rev 2.0 only¶
New in v2.7.0. Use the External UART port with whatever message format you decide. The peer can be another XM10, an Arduino, a PC, a Raspberry Pi — anything. Framing, checksums and parsing are yours to define (raw bytes are transferred).
The hardware settings are fixed — configure your peer to match.
| Item | Value | Changeable |
|---|---|---|
| Peripheral / pins | USART2, TX=PD5 (EXT_UART_TX) / RX=PD6 (EXT_UART_RX) |
✗ |
| Logic level | 3.3 V — never wire 5 V directly | ✗ |
| Default baud | 921600 bps | ✅ XM_SetExternalUartBaudrate() |
| Data / parity / stop | 8 / none / 1 | ✗ |
| Flow control | None (RTS/CTS unused) | ✗ |
| Max bytes per send | 128 (XM_EXT_UART_TX_MAX_BYTES) |
✗ |
🛑 Do not use this wiring on a Rev 1.1 board. Rev 1.1 does not have this port, and PD6 there is
USB_PWR_ON— an output that switches USB power. Connecting a peer's TX to it puts two outputs against each other. This API is also absent from the Rev 1.1 SDK.
Related example: 43_External_UART_PingPong
XM_AttachExternalUart¶
typedef void (*XmExternalUartRxFunc_t)(const uint8_t* data, uint32_t len);
bool XM_AttachExternalUart(XmExternalUartRxFunc_t rx_callback);
Starts External UART reception and registers a callback. Call it once in Control_Setup().
Passing NULL detaches reception.
Returns: true = registered / false = port not ready
⚠️ Copy, and nothing else, inside the callback. It runs on the XM10's shared receive task, and that same task also handles the 1 kHz foot-sensor (GRF) stream. Parsing, computing or waiting here delays GRF data by exactly that much.
⚠️ The
datapointer is invalid once the callback returns. It points at an internal scratch buffer — copy the contents, do not store the pointer.⚠️ One callback is not one message. Reception arrives in chunks of up to 128 bytes and may split or concatenate messages. You must find the message boundaries yourself.
Example
static volatile uint8_t s_rx[256];
static volatile uint16_t s_rx_len;
static void OnSerialRx(const uint8_t* data, uint32_t len)
{
for (uint32_t i = 0; i < len && s_rx_len < sizeof(s_rx); i++) {
s_rx[s_rx_len++] = data[i]; /* copy only! */
}
}
void Control_Setup(void)
{
XM_SetExternalUartBaudrate(XM_UART_BAUD_115200);
XM_AttachExternalUart(OnSerialRx);
}
XM_SetExternalUartBaudrate¶
Changes the baud rate. It must match the peer device. Call it before
XM_AttachExternalUart().
Parameters: XM_UART_BAUD_9600 / _19200 / _38400 / _57600 / _115200 / _230400 /
_460800 / _921600 (boot default)
Returns: true = success / false = port not ready, or value out of range
XM_SendExternalUartData¶
Sends data. It does not wait.
Parameters: data payload / len byte count (1 – XM_EXT_UART_TX_MAX_BYTES = 128)
Returns: true = transmission started / false = previous transmission still in flight,
or invalid argument
falseis not an error — it means "busy right now". Calling this every tick from a 1 kHzControl_Loop()will not stall the loop; onfalse, just retry next tick. More than 128 bytes is rejected withfalse, so split longer payloads.
XM_SendExternalUartDataBlocking¶
Waits until transmission completes.
⚠️ Call context: Control_Setup() only. It can block for up to 5 seconds, so calling
it from Control_Loop() breaks the control period, and calling it from the receive callback
stalls GRF reception too. Use it only to send a one-off setup command.
XM_EnsureExternalUartRxArmed¶
Revives reception if it has stalled. Unplugging and replugging a cable, or a framing error caused by noise, can leave hardware reception stopped; calling this periodically recovers it automatically. When everything is fine it does nothing — it is a cheap call.
Call period: ~100 ms recommended (use a counter inside Control_Loop()).
Types / Macros¶
XmDioPin_t¶
All 8 DIO pins map to the same physical pins on both revisions.
| Value | Physical Pin | Description |
|---|---|---|
XM_EXT_DIO_1 = 0 |
PF3 | |
XM_EXT_DIO_2 |
PF4 | |
XM_EXT_DIO_3 |
PF5 | |
XM_EXT_DIO_4 |
PF6 | |
XM_EXT_DIO_5 |
PF7 | |
XM_EXT_DIO_6 |
PF8 | |
XM_EXT_DIO_7 |
PF9 | |
XM_EXT_DIO_8 |
PF10 | |
XM_EXT_DIO_COUNT |
— | (internal) pin count |
XmAdcPin_t¶
The physical pin and native resolution of the 4 fixed ADC pins (XM_EXT_ADC_1~4) differ by revision. The dynamic ADC3 group (XM_EXT_ADC_5~12) is identical on both revisions.
| Value | Rev 1.1 | Rev 2.0 | Notes |
|---|---|---|---|
XM_EXT_ADC_1 = 0 |
PA0, ADC1 12-bit native [Shared: UART4_TX] | PB0 (ADC1_INP9), ADC1 16-bit native | Rev1.1: occupied by UART4 once the IMU is attached |
XM_EXT_ADC_2 |
PA0_C, ADC2 16-bit native | PB1 (ADC1_INP5), ADC1 16-bit native | Rev1.1: use this instead of ADC_1 after IMU attach |
XM_EXT_ADC_3 |
PA1, ADC1 12-bit native [Shared: UART4_RX] | PF11 (ADC1_INP2), ADC1 16-bit native | Rev1.1: occupied by UART4 once the IMU is attached |
XM_EXT_ADC_4 |
PA1_C, ADC2 16-bit native | PF12 (ADC1_INP6), ADC1 16-bit native | Rev1.1: use this instead of ADC_3 after IMU attach |
XM_EXT_ADC_5 |
PF3 (DIO 1 → ADC3, 16-bit) | PF3 (DIO 1 → ADC3, 16-bit) | Requires XM_SwitchDioToAdc() |
XM_EXT_ADC_6 |
PF4 (DIO 2 → ADC3, 16-bit) | PF4 (DIO 2 → ADC3, 16-bit) | ditto |
XM_EXT_ADC_7 |
PF5 (DIO 3 → ADC3, 16-bit) | PF5 (DIO 3 → ADC3, 16-bit) | ditto |
XM_EXT_ADC_8 |
PF6 (DIO 4 → ADC3, 16-bit) | PF6 (DIO 4 → ADC3, 16-bit) | ditto |
XM_EXT_ADC_9 |
PF7 (DIO 5 → ADC3, 16-bit) | PF7 (DIO 5 → ADC3, 16-bit) | ditto |
XM_EXT_ADC_10 |
PF8 (DIO 6 → ADC3, 16-bit) | PF8 (DIO 6 → ADC3, 16-bit) | ditto |
XM_EXT_ADC_11 |
PF9 (DIO 7 → ADC3, 16-bit) | PF9 (DIO 7 → ADC3, 16-bit) | ditto |
XM_EXT_ADC_12 |
PF10 (DIO 8 → ADC3, 16-bit) | PF10 (DIO 8 → ADC3, 16-bit) | ditto |
XM_EXT_ADC_COUNT |
— | — | (internal) pin count |
The Rev2.0
XM_EXT_ADC_1~4resolutions in this table are based on the enum comment and the Rev 2.0 hardware pinmap document — see the header-wording inconsistency note underXM_GetAnalogResolutionas well.
Common input range: 0~3.3V, sampling at 10kHz (fixed pins) / 10kHz (ADC3 group). Output can be selected among 8/10/12/14/16-bit via XM_SetAnalogReadResolution().
XmPinMode_t¶
| Value | Description |
|---|---|
XM_EXT_DIO_MODE_INPUT |
Digital input (floating) |
XM_EXT_DIO_MODE_INPUT_PULLUP |
Digital input (internal pull-up resistor) |
XM_EXT_DIO_MODE_INPUT_PULLDOWN |
Digital input (internal pull-down resistor) |
XM_EXT_DIO_MODE_OUTPUT |
Digital output |
XmLogicLevel_t¶
| Value | Description |
|---|---|
XM_LOW = 0 |
0V (GND) |
XM_HIGH = 1 |
3.3V (VCC) |
XmExtPwrVoltage_t 🟢 Rev 2.0 Only¶
Not defined in the Rev1.1 header.
| Value | Description |
|---|---|
XM_EXT_PWR_3V3 = 0 |
3.3V output (default, Low) |
XM_EXT_PWR_5V = 1 |
5V output (High) |
Diagnostic Global Variable 🟢 Rev 2.0 Only¶
g_xm_adc_read_before_switch¶
🟢 Rev 2.0 Only — This variable does not exist in the Rev1.1 header.
A diagnostic bitmask that records, one bit per pin, whether an ADC3-group pin (XM_EXT_ADC_5~12) was read via XM_AnalogRead()/XM_AnalogReadMillivolts() without first being switched via XM_SwitchDioToAdc(). bit0 = XM_EXT_ADC_5 (DIO_1) … bit7 = XM_EXT_ADC_12 (DIO_8). Reading an ADC3 pin before switching causes the lower layer to return 0 (indistinguishable from a genuine 0V reading); that situation is recorded per-channel in this bitmask. A value of 0 means every ADC read so far has been valid.
Type: volatile uint16_t (extern) — the header provides no write API, so treat this as read-only.
⚠️ Calling context: Can be read from Control_Loop(), STM32CubeIDE Live Expressions, or anywhere in user code (observable even in a USB-less, SWD-only setup — it does not depend on any particular output channel). Being volatile, every read fetches the actual memory value.
Example
// When ADC reads keep coming back as 0 and you want to find out why:
if (g_xm_adc_read_before_switch != 0U) {
// One of bit0=ADC_5(DIO1) ... bit7=ADC_12(DIO8) is missing its XM_SwitchDioToAdc() call
}
See also: XM_SwitchDioToAdc, XM_IsDioSwitchedToAdc
Internal Only (Do Not Call)¶
No functions, types, or variables defined in this header are marked [Internal] or System-only — all 14 functions, 1 macro, 5 types, and 1 diagnostic variable covered above are public API.
Rev1.1 / Rev2.0 Differences Summary¶
| Item | Rev1.1 | Rev2.0 |
|---|---|---|
Basic DIO control (XM_SetPinMode/DigitalWrite/DigitalRead) for all 8 pins |
✅ | ✅ |
Unified ADC read API (XM_AnalogRead, etc.) |
✅ | ✅ |
XM_EXT_ADC_1~4 physical pins / native resolution |
PA0/PA0_C/PA1/PA1_C — mix of ADC1 12-bit + ADC2 16-bit | PB0/PB1/PF11/PF12 — all ADC1 16-bit |
DIO → ADC3 dynamic switching (XM_SwitchDioToAdc, etc.) |
✅ | ✅ |
XM_AttachXsensMTi630 internal attach method |
PA0/PA1 dynamically switched to UART4 (occupies XM_EXT_ADC_1/_3) |
Dedicated USART2 (PD5/PD6), no ADC resource occupied |
XM_SetExtPowerVoltage / XmExtPwrVoltage_t (3.3V/5V power switch) |
❌ Not available | 🟢 Only |
g_xm_adc_read_before_switch diagnostic variable |
❌ Not available | 🟢 Only |
Related Documents¶
- 04. External IO Control API (concept) — operating principle, common mistakes, example mapping
- Hardware Pinmap — Rev 1.1 / Rev 2.0
- Board Revision Comparison