nRF51/nRF51822 UART引脚映射修改及运行时切换技术咨询
Alright, let's break down your two questions about modifying UART pin mappings on the nRF51822—both statically in code and dynamically at runtime using the g_ADigitalPinMap structure. Here's how to tackle each one clearly:
If you just need a fixed pin mapping for your custom board, modify the UART initialization code directly:
- First, locate your project's UART setup function (usually named something like
uart_init()orapp_uart_init()—check files likeuart.corboard_support.c). - Look for the UART configuration structure (typically
nrf_uart_config_t). Update thepsel_txandpsel_rxfields with your desired physical pin numbers (nRF51 uses P0.x pins, so the value is just thexportion). For example, switching from P0.0/P0.1 to P0.10/P0.11:nrf_uart_config_t uart_config = { .psel_tx = 10, // Physical pin P0.10 for TX .psel_rx = 11, // Physical pin P0.11 for RX .psel_rts = NRF_UART_PSEL_DISCONNECTED, // Disable RTS if unused .psel_cts = NRF_UART_PSEL_DISCONNECTED, // Disable CTS if unused .hwfc = NRF_UART_HWFC_DISABLED, .parity = NRF_UART_PARITY_EXCLUDED, .baudrate = NRF_UART_BAUDRATE_115200, }; - If you're using the SoftDevice, ensure you update any SoftDevice-specific UART enable calls (like
sd_uart_enable()) to match the new pins—this avoids resource conflicts. - Rebuild and flash your code, and the new pin mapping will be active on boot.
g_ADigitalPinMap) To switch pins dynamically after communicating with one device and send data to another, follow these steps:
Step 1: Prepare Your Pin Configurations
First, define two sets of pin mappings (one for each serial device) and track the current state:
// Define pin sets for Device A and Device B #define DEV_A_TX_PIN 10 #define DEV_A_RX_PIN 11 #define DEV_B_TX_PIN 15 #define DEV_B_RX_PIN 16 // Track current active device typedef enum { DEVICE_A, DEVICE_B } active_device_t; active_device_t current_device = DEVICE_A;
Step 2: Safely Switch Pins at Runtime
You need to disable the UART first to release the current pins, then update the mapping and reinitialize:
- Disable the UART peripheral to free up the current pins:
nrf_uart_disable(NRF_UART0); // Use your UART instance (UART0/UART1) - Update
g_ADigitalPinMap: This global structure maps logical pin IDs to physical nRF51 pins. If your code uses logical pins for UART TX/RX, update those entries:// Assume LOGICAL_UART_TX and LOGICAL_UART_RX are your logical pin IDs if (current_device == DEVICE_A) { // Switch to Device B g_ADigitalPinMap[LOGICAL_UART_TX] = DEV_B_TX_PIN; g_ADigitalPinMap[LOGICAL_UART_RX] = DEV_B_RX_PIN; current_device = DEVICE_B; } else { // Switch back to Device A if needed g_ADigitalPinMap[LOGICAL_UART_TX] = DEV_A_TX_PIN; g_ADigitalPinMap[LOGICAL_UART_RX] = DEV_A_RX_PIN; current_device = DEVICE_A; } - Reconfigure the physical pins for UART functionality:
uint32_t new_tx_pin = g_ADigitalPinMap[LOGICAL_UART_TX]; uint32_t new_rx_pin = g_ADigitalPinMap[LOGICAL_UART_RX]; nrf_gpio_cfg_output(new_tx_pin); // Set TX as output nrf_gpio_cfg_input(new_rx_pin, NRF_GPIO_PIN_NOPULL); // Set RX as input (no pull-up/down) - Update the UART peripheral's pin registers or reinitialize the UART:
// Option 1: Direct register update (faster) NRF_UART0->PSELTXD = new_tx_pin; NRF_UART0->PSELRXD = new_rx_pin; // Option 2: Re-initialize with new config (safer if you need to reset other settings) nrf_uart_config_t new_uart_config = { .psel_tx = new_tx_pin, .psel_rx = new_rx_pin, .psel_rts = NRF_UART_PSEL_DISCONNECTED, .psel_cts = NRF_UART_PSEL_DISCONNECTED, .hwfc = NRF_UART_HWFC_DISABLED, .parity = NRF_UART_PARITY_EXCLUDED, .baudrate = NRF_UART_BAUDRATE_115200, }; nrf_uart_uninit(NRF_UART0); nrf_uart_init(NRF_UART0, &new_uart_config); - Re-enable the UART to start using the new pins:
nrf_uart_enable(NRF_UART0);
Step 3: Trigger the Switch After Communication Completion
To switch pins right after finishing with the first device:
- Implement a completion flag or callback. For example, if using interrupt-driven UART, set a flag in the TX/RX complete interrupt handler when communication with Device A is done.
- Once the flag is set, run the pin switching steps above, then initiate data transmission to Device B.
Critical Notes
- Avoid Pin Conflicts: Double-check that the new pins aren't used by other peripherals (SPI, I2C, GPIO) before switching.
- SoftDevice Compatibility: If using the SoftDevice, replace direct
nrf_uart_*functions withsd_uart_uninit()andsd_uart_enable(), and ensure pins are allocated via the SoftDevice's resource manager. - Timing: Add a short delay (1-2ms) after disabling the UART to ensure hardware releases the pins fully before reconfiguration.
内容的提问来源于stack exchange,提问作者MrEspin

