Titania (AMB3626) 硬體設定與腳位控制指南
模組型號: Würth Titania 2607011111100x (AMB3626)
硬體相關手冊章節: Manual-um-titania-260701111100x (rev4.5) - 第 2 章、第 3 章、第 7 章
主要參考標準: EN 300 220(歐盟無線設備規範)
📌 快速清單(設定前必做)
- VCC 已穩定供電(2.0–3.6 V,建議 3.3 V)
- /RESET 腳位已釋放(被 RC 電路或軟體拉高)
- TRX_DISABLE 接 GND(一定要)
- UART TX/RX 已接到 STM32
- /CONFIG 腳位接到 STM32 GPIO(選用,但建議接)
- /RTS 腳位接到 STM32GPIO 或監測(強烈建議)
- 沒有無線訊號、UART 也空閒時,才改設定
- 改完非揮發參數後,務必 CMD_RESET_REQ
🔌 腳位配置與硬體設置
1. VCC 與 /RESET 腳
腳位定義:
| 腳位 | 標號 | 用途 | 電壓 | 說明 |
|---|---|---|---|---|
| VCC | 1 | 電源正 | +3.3 V(範圍 2.0–3.6 V) | 模組主電源 |
| GND | 2(多個) | 地 | 0 V | 必須與 MCU 共地 |
| /RESET | 某腳 | 模組重置 | 開漏輸出或 RC 延遲 | 上電時 必須先低、再高 |
上電時序(極其重要):
時間線:
T=0 ms:VCC 開始上升
T=0~2 ms:VCC 還在上升,/RESET 必須保持 LOW(不要放高)
T=2 ms:VCC 穩定在 3.3 V
T=2~10 ms:/RESET 開始被 RC 電路或軟體拉高
T=10~50 ms:Titania 內部初始化進行中
T=50 ms+:模組完成啟動,UART + /CONFIG 開始工作
⚠️ 如果 /RESET 在 VCC 還不穩時就被拉高,模組會受損或無法啟動。
建議實作:
-
硬體 RC 延遲方案(最簡單):
VCC ──[10kΩ]──┬──/RESET ├──[100nF]──┴──GND └──外部按鍵到 GND(選用) 效果:上電時,/RESET 會被 100nF 電容延遲 ~10~50 ms 才慢慢被拉高, 自動保證 VCC 先穩定再放開 /RESET。 -
軟體方案(MCU 控制):
void Titania_PowerUp(void) { // 上電時 /RESET 已經被拉低(可能通過外部電路或預設狀態) HAL_GPIO_WritePin(RESET_PORT, RESET_PIN, GPIO_PIN_RESET); // 確保低 HAL_Delay(10); // 等 VCC 穩定 HAL_GPIO_WritePin(RESET_PORT, RESET_PIN, GPIO_PIN_SET); // 拉高 HAL_Delay(100); // 等模組啟動完成 }
2. TRX_DISABLE 腳(強制無線發射禁用)
功能: 當 TRX_DISABLE 被拉高時,模組無法傳送無線訊號(RX 仍可用)。用來省功耗或避免干擾。
設定參數時的用途: 雖然不是「必須」讓它 HIGH,但 強烈建議在整個參數設定過程中保持 LOW(讓無線 TX 可用,但我們不會在設定時送訊號)。
| 狀態 | 說明 |
|---|---|
| LOW(接 GND) | 無線 TX/RX 都啟用(正常工作模式) |
| HIGH | 無線 TX 被禁用,模組停止傳送(僅 RX) |
| 浮接 | 不允許,會造成無法預知的行為 |
建議實作:
方案 1(最簡單,出廠推薦):
TRX_DISABLE ──→ GND
(直接接地,永遠 LOW,模組正常工作)
方案 2(後期要動態禁用 TX 時):
TRX_DISABLE ──[10kΩ pull-down]──┬──STM32 GPIO(或保留浮接用軟體控制)
└──GND
HAL_GPIO_WritePin(TRX_DIS_PORT, TRX_DIS_PIN, GPIO_PIN_RESET); // 允許 TX
HAL_GPIO_WritePin(TRX_DIS_PORT, TRX_DIS_PIN, GPIO_PIN_SET); // 禁用 TX
3. /CONFIG 腳(Mode Selector:Transparent ↔ Command)
功能: 檢測「下降沿」(HIGH → LOW)來切換模式。
| 邊緣 | 狀態轉換 |
|---|---|
| 下降沿(HIGH → LOW) | 進入或跳出 Command Mode |
| LOW 狀態保持 | 停留在 Command Mode |
| HIGH 狀態保持 | Transparent Mode |
時序要求(最重要):
只有在「沒有無線收發、也沒有 UART 資料傳輸」的安全區間才能切模式。手冊建議看 /RTS 線:
/RTS = HIGH(模組忙,有 UART 活動) → 不要切模式/RTS = LOW(模組空閒) → 可以安全地做下降沿切模式
void Titania_EnterCommandMode(GPIO_TypeDef *cfg_port, uint16_t cfg_pin,
GPIO_TypeDef *rts_port, uint16_t rts_pin)
{
// 1. 等待 /RTS = LOW(模組空閒),timeout 100 ms
uint32_t timeout = 100;
while (HAL_GPIO_ReadPin(rts_port, rts_pin) == GPIO_PIN_SET && timeout--)
{
HAL_Delay(1);
}
// 2. 確認 /CONFIG 已經 HIGH(停留 Transparent Mode)
HAL_GPIO_WritePin(cfg_port, cfg_pin, GPIO_PIN_SET);
HAL_Delay(10);
// 3. 做下降沿
HAL_GPIO_WritePin(cfg_port, cfg_pin, GPIO_PIN_RESET);
HAL_Delay(5);
// 4. 保持 LOW 一段時間(表示「停留 Command Mode」)
// (不需要立即拉回 HIGH)
HAL_Delay(50); // 給模組時間完成模式切換
}
void Titania_ExitCommandMode(GPIO_TypeDef *cfg_port, uint16_t cfg_pin)
{
// 1. /CONFIG 保持 LOW 一段時間(已在 Command Mode 中)
// 2. 再做一次下降沿,跳出 Command Mode
HAL_GPIO_WritePin(cfg_port, cfg_pin, GPIO_PIN_SET); // 拉 HIGH
HAL_Delay(10);
HAL_GPIO_WritePin(cfg_port, cfg_pin, GPIO_PIN_RESET); // 拉 LOW(下降沿)
HAL_Delay(5);
// 3. 拉 HIGH 回 Transparent Mode
HAL_GPIO_WritePin(cfg_port, cfg_pin, GPIO_PIN_SET);
HAL_Delay(50);
}
4. UART 相關腳位(TX、RX、/RTS、/CTS)
最小硬體連接(必須):
| 訊號 | Titania 腳 | STM32 腳 | 說明 |
|---|---|---|---|
| UTXD | Titania TX | STM32 RXx | 模組發送,MCU 接收 |
| URXD | Titania RX | STM32 TXx | MCU 發送,模組接收 |
| GND | GND | GND | 必須共地 |
選用但強烈建議的流控腳位:
| 訊號 | Titania 腳 | STM32 腳 | 說明 |
|---|---|---|---|
| /RTS | 模組 RTS | STM32 GPIO 輸入 | 模組輸出,LOW = 可以發送,HIGH = 忙碌 |
| /CTS | 模組 CTS | STM32 GPIO 輸出 | 若不用 CTS flow control,直接接 GND |
為什麼要監測 /RTS?
/RTS = HIGH:模組 UART buffer 滿或正在無線收發,MCU 不應再丟資料。/RTS = LOW:安全區間,可以發 UART 命令或改設定。
建議實作:
#define UART_RX_PIN GPIO_PIN_10 // STM32 PA10(USART1 RX)
#define UART_TX_PIN GPIO_PIN_9 // STM32 PA9(USART1 TX)
#define RTS_PIN GPIO_PIN_11 // STM32 PA11(輸入,讀取 Titania /RTS)
#define CTS_PIN GPIO_PIN_12 // STM32 PA12(輸出,若不用直接接 GND)
void Titania_UART_Init(void)
{
// UART1 初始化為 9600 8N1
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
HAL_UART_Init(&huart1);
// GPIO 設定:/RTS 為輸入(讀模組狀態)
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = RTS_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// /CTS 為輸出且拉低(若不用 CTS flow,直接 LOW)
GPIO_InitStruct.Pin = CTS_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOA, CTS_PIN, GPIO_PIN_RESET);
}
HAL_StatusTypeDef Titania_SendUARTSafe(const uint8_t *data, uint16_t len)
{
// 先等 /RTS = LOW(模組空閒),timeout 100 ms
uint32_t timeout = 100;
while (HAL_GPIO_ReadPin(GPIOA, RTS_PIN) == GPIO_PIN_SET && timeout--)
{
HAL_Delay(1);
}
if (timeout == 0) return HAL_TIMEOUT;
// 發送
return HAL_UART_Transmit(&huart1, (uint8_t *)data, len, 100);
}
5. ANT(天線)腳位
最小設置: 不需要 MCU 控制,但 PCB layout 要遵守手冊規則:
- 天線線路 旁邊要有「淨空區」(通常 10~15 mm),不要拉數位線穿過。
- 天線匹配電路 按手冊 reference design 來,不要亂改。
- 若用外部天線,焊接要牢固,斷線會影響通訊距離。
🔄 設定參數時的硬體狀態機
完整流程圖
START
↓
[1] 上電 & /RESET 釋放
└─→ TRX_DISABLE = LOW(允許無線 TX/RX)
└─→ 等 100 ms 模組啟動完成
↓
[2] 初始化 STM32 UART(9600 8N1)
↓
[3] 監測 /RTS,等它變 LOW(模組空閒)
↓
[4] 進入 Command Mode(/CONFIG 下降沿)
└─→ 等 /CONFIG 穩定在 LOW 50 ms
↓
[5] 透過 UART 發送 CMD_SET_REQ(改 baudrate/channel/NetID…)
└─→ 等 50~200 ms 回應
↓
[6] 檢查回應 Status(0x00 = OK)
├─ OK → 步驟 [7]
└─ FAIL → 重試或 debug
↓
[7] 再監測 /RTS = LOW
↓
[8] 發送 CMD_RESET_REQ(軟重啟)
└─→ 等 500 ms 模組重啟完成
↓
[9] 改 STM32 UART 波特率(新的 baudrate)
↓
[10] 退出 Command Mode(/CONFIG 再做下降沿)
└─→ 拉 HIGH,再下降沿,再拉 HIGH
↓
[11] 回到 Transparent Mode,可以正常收發無線訊號
↓
DONE
⚡ 實作程式碼(完整初始化流程)
#include "stm32f1xx_hal.h"
// 腳位定義
#define RESET_PORT GPIOA
#define RESET_PIN GPIO_PIN_0
#define TRX_DIS_PORT GPIOA
#define TRX_DIS_PIN GPIO_PIN_1
#define CONFIG_PORT GPIOA
#define CONFIG_PIN GPIO_PIN_2
#define RTS_PORT GPIOA
#define RTS_PIN GPIO_PIN_3
extern UART_HandleTypeDef huart1;
// 計算 Checksum
static uint8_t CalcChecksum(uint8_t *buf, uint8_t len)
{
uint8_t cs = 0;
for (uint8_t i = 0; i < len; i++)
cs ^= buf[i];
return cs;
}
// 發送 UART 指令(封裝 Checksum)
static HAL_StatusTypeDef Titania_SendCommand(uint8_t cmd,
const uint8_t *data,
uint8_t data_len)
{
uint8_t frame[64];
uint8_t idx = 0;
frame[idx++] = 0x02; // Start
frame[idx++] = cmd;
frame[idx++] = data_len;
for (uint8_t i = 0; i < data_len; i++)
frame[idx++] = data[i];
uint8_t cs = CalcChecksum(frame, idx);
frame[idx++] = cs;
return HAL_UART_Transmit(&huart1, frame, idx, 100);
}
// 等待 /RTS = LOW(模組空閒)
static HAL_StatusTypeDef Titania_WaitReady(uint32_t timeout_ms)
{
while (HAL_GPIO_ReadPin(RTS_PORT, RTS_PIN) == GPIO_PIN_SET && timeout_ms--)
{
HAL_Delay(1);
}
return (timeout_ms == 0) ? HAL_TIMEOUT : HAL_OK;
}
// 進 Command Mode
static void Titania_EnterCmdMode(void)
{
Titania_WaitReady(100);
HAL_GPIO_WritePin(CONFIG_PORT, CONFIG_PIN, GPIO_PIN_SET); // HIGH
HAL_Delay(10);
HAL_GPIO_WritePin(CONFIG_PORT, CONFIG_PIN, GPIO_PIN_RESET); // 下降沿
HAL_Delay(50);
}
// 退出 Command Mode
static void Titania_ExitCmdMode(void)
{
Titania_WaitReady(100);
HAL_GPIO_WritePin(CONFIG_PORT, CONFIG_PIN, GPIO_PIN_SET); // HIGH
HAL_Delay(10);
HAL_GPIO_WritePin(CONFIG_PORT, CONFIG_PIN, GPIO_PIN_RESET); // 下降沿
HAL_Delay(5);
HAL_GPIO_WritePin(CONFIG_PORT, CONFIG_PIN, GPIO_PIN_SET); // 回 HIGH
HAL_Delay(50);
}
// 上電與初始化
void Titania_PowerUp(void)
{
// 1. GPIO 初始化
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = RESET_PIN | TRX_DIS_PIN | CONFIG_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = RTS_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 2. 確保 /RESET 低、TRX_DISABLE 低、/CONFIG 高
HAL_GPIO_WritePin(RESET_PORT, RESET_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(TRX_DIS_PORT, TRX_DIS_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CONFIG_PORT, CONFIG_PIN, GPIO_PIN_SET);
HAL_Delay(10);
// 3. 釋放 /RESET
HAL_GPIO_WritePin(RESET_PORT, RESET_PIN, GPIO_PIN_SET);
HAL_Delay(100); // 等模組啟動
}
// 完整設定函式
typedef struct
{
uint32_t baudrate; // 1200~115200
uint8_t channel; // 0~4
uint16_t netid; // NetID
uint16_t addr; // Addr LSB
} TitaniaSettings;
HAL_StatusTypeDef Titania_Configure(const TitaniaSettings *settings)
{
uint8_t payload[10];
uint8_t resp[10];
HAL_StatusTypeDef st;
// 1. 進 Command Mode
Titania_EnterCmdMode();
HAL_Delay(100);
// 2. 改 UART Baudrate(非揮發)
payload[0] = 0x50; // UART_Baudrate mem pos
payload[1] = 0x04; // 4 bytes
payload[2] = (uint8_t)(settings->baudrate & 0xFF);
payload[3] = (uint8_t)((settings->baudrate >> 8) & 0xFF);
payload[4] = (uint8_t)((settings->baudrate >> 16) & 0xFF);
payload[5] = (uint8_t)((settings->baudrate >> 24) & 0xFF);
Titania_SendCommand(0x09, payload, 6);
HAL_Delay(100);
HAL_UART_Receive(&huart1, resp, 5, 200);
if (resp[3] != 0x00) return HAL_ERROR; // Status check
// 3. 改頻道(非揮發)
payload[0] = 0x2A; // PHY_DefaultChannel mem pos
payload[1] = 0x01; // 1 byte
payload[2] = settings->channel;
Titania_SendCommand(0x09, payload, 3);
HAL_Delay(100);
HAL_UART_Receive(&huart1, resp, 5, 200);
if (resp[3] != 0x00) return HAL_ERROR;
// 4. 改 NetID(需要補上正確的 mem pos)
// payload[0] = 0xXX; // MAC_DefaultDestNetID mem pos (TODO)
// payload[1] = 0x02; // 2 bytes
// payload[2] = (uint8_t)(settings->netid & 0xFF);
// payload[3] = (uint8_t)(settings->netid >> 8);
// Titania_SendCommand(0x09, payload, 4);
// HAL_UART_Receive(&huart1, resp, 5, 200);
// 5. 軟重啟讓設定生效
Titania_SendCommand(0x05, NULL, 0);
HAL_Delay(100);
HAL_UART_Receive(&huart1, resp, 5, 500);
// 6. 改 STM32 UART 波特率
huart1.Init.BaudRate = settings->baudrate;
HAL_UART_Init(&huart1);
HAL_Delay(100);
// 7. 退出 Command Mode
Titania_ExitCmdMode();
return HAL_OK;
}
// 使用範例
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init(); // 先 9600
// 上電
Titania_PowerUp();
HAL_Delay(200);
// 設定參數
TitaniaSettings cfg = {
.baudrate = 57600,
.channel = 2,
.netid = 0x0001,
.addr = 0x0005
};
Titania_Configure(&cfg);
while (1)
{
// 主應用程式...
}
}
🚨 常見錯誤 & 排除
| 問題 | 原因 | 解決方案 |
|---|---|---|
| 上電後模組不回應 | /RESET 在 VCC 未穩時被拉高,或 /RESET 沒被正確拉高 | 檢查 RC 延遲電路、或用示波器看 /RESET 時序 |
| 無法進 Command Mode | /CONFIG 下降沿時機不對,或被拉高時間不足 | 確保 /RTS = LOW 後再做下降沿,並保持 LOW 50 ms+ |
| 改參數後 UART 通訊失敗 | 沒有做 CMD_RESET_REQ、或 STM32 UART 波特率沒同步改 | 一定要 reset,再改 STM32 baud rate |
| 頻道、NetID 沒生效 | memory position 填錯,或 status byte 不是 0x00 | 對照手冊第 8 章確認 memory position;檢查 Checksum |
| /RTS 一直高 | UART buffer 滿,或模組忙碌 | 等待、或檢查有沒有大量無線訊號干擾 |
📊 各項設定對應的硬體狀態
| 設定項目 | 需進 Command Mode | 需要 Reset | UART 切換 | 安全區間條件 |
|---|---|---|---|---|
| UART_Baudrate | ✅ | ✅ | ✅ 必須改 STM32 baud | /RTS=LOW |
| PHY_DefaultChannel | ✅ | ✅ | ❌ 不用改 | /RTS=LOW |
| MAC_DefaultDestNetID | ✅ | ✅ | ❌ 不用改 | /RTS=LOW |
| MAC_DefaultDestAddrLSB | ✅ | ✅ | ❌ 不用改 | /RTS=LOW |
| PHY_PAPower | ✅ | ✅ | ❌ 不用改 | /RTS=LOW |
| CMD_FACTORY_RESET | ✅ | ✅ | ✅ 必須改 STM32 baud 回 9600 | /RTS=LOW |
| CMD_SET_CHANNEL_REQ(揮發) | ✅ | ❌ | ❌ 不用改 | /RTS=LOW |
📌 檢查清單(部署前)
- PCB 佈局按手冊 reference layout
- VCC 穩壓、旁路電容(100 nF + 1 μF)
- /RESET 有 RC 延遲或軟體控制
- TRX_DISABLE 接 GND(正常模式)
- UART TX/RX 正確連接且沒反接
- /RTS 接到 GPIO 或監測
- /CONFIG 接到 GPIO(可進 Command Mode)
- 天線線路淨空、不穿過數位線
- 第一次設定時用邏輯分析儀監看時序確認
- 改完參數後驗證設定有沒有真的生效(CMD_GET_REQ 讀回來確認)
🔗 參考
- Würth Titania Manual: Manual-um-titania-260701111100x (rev4.5) - 第 2、3、7、8 章
- HAL Reference: STM32 HAL Driver 官方文檔
- EN 300 220: 歐盟無線設備規範
最後更新: 2026-03-10
作者備註: 本硬體指南強調「時序」與「狀態機」,設定參數時務必遵守 /RTS、/CONFIG 的時序要求。