# Titania (AMB3626) UART 指令與回應值完整指南

> **模組型號：** Würth Titania 2607011111100x (AMB3626)  
> **通訊標準：** 9600 8N1（出廠預設），可改為 1200~115200 baud  
> **頻段：** 169.4125~169.4625 MHz (Band D, EN 300 220)  
> **文檔參考：** Manual-um-titania-260701111100x (rev4.5)

---

## 📋 快速參考表

| 指令名稱 | CMD Code | Request | Response | 用途 |
|---------|----------|---------|----------|------|
| **軟體重置** | 0x05 | `02 05 00 07` | `02 45 01 00 46` | 軟重啟，讓新設定生效 |
| **設定頻道（揮發）** | 0x06 | `02 06 01 [CH] [CS]` | `02 46 01 [CH] [CS]` | 臨時改當前頻道，斷電失效 |
| **設定 UserSetting（非揮發）** | 0x09 | `02 09 [LEN+2] [MEM] [BYTES] [DATA...] [CS]` | `02 49 [LEN] [STATUS] [CS]` | 寫入 flash 參數（baudrate、NetID 等） |
| **讀取 UserSetting** | 0x0B | `02 0B 01 [MEM] [CS]` | `02 4B [LEN] [STATUS] [DATA...] [CS]` | 讀出 flash 參數現在的值 |
| **工廠重置** | 0x0D | `02 0D 00 4D` | `02 4C 00 4E` | 清所有 UserSettings，回到出廠預設（UART 回 9600） |
| **透明模式傳送（MAC）** | 0x80 | `02 80 [LEN] [MAC DATA...] [CS]` | `02 C0 [LEN] [STATUS] [CS]` | 透明模式下發送無線訊號 |
| **Command Mode 進入** | — | —  | — | 接 /CONFIG 腳下降邊緣可進入 |

---

## 🔧 詳細指令說明

### 1️⃣ 軟體重置（CMD_RESET_REQ）

**用途：** 讓 Titania 重啟，新的 UserSettings（如 baudrate 變更）會在重啟後生效。

**指令：**
```
Start   CMD  LEN  Checksum
  02    05   00      07
```

**回應：**
```
Start   CMD  LEN  Status  Checksum
  02    45   01   00        46
```

- **Status = 0x00**：成功，模組重啟中
- **回應出現延遲：** 模組需要 100~500 ms 才會完全重啟

**C 程式碼：**
```c
HAL_StatusTypeDef st = Titania_SendCommand(huart, 0x05, NULL, 0);
uint8_t resp[5];
HAL_UART_Receive(huart, resp, 5, 500);  // 等待重啟完成
```

---

### 2️⃣ 設定當前頻道（揮發）— CMD_SET_CHANNEL_REQ

**用途：** 臨時改變無線頻道（runtime），重啟模組後會失效（回到預設頻道）。

**頻道對應表：**

| 頻道 | 頻率 (MHz) | 指令值 |
|------|-----------|--------|
| 0 | 169.4125 | 0x00 |
| 1 | 169.4250 | 0x01 |
| 2 | 169.4375 | 0x02 |
| 3 | 169.4500 | 0x03 |
| 4 | 169.4625 | 0x04 |

**指令格式：**
```
Start  CMD  LEN  Channel  Checksum
  02   06   01   [0~4]    [CS]
```

**計算 Checksum：** `0x02 ^ 0x06 ^ 0x01 ^ [Channel]`

**範例 - 設定 Channel 2：**
```
發送：02 06 01 02 01
回應：02 46 01 02 43

Checksum 計算：
  0x02 ^ 0x06 ^ 0x01 ^ 0x02 = 0x01 ✓
  0x02 ^ 0x46 ^ 0x01 ^ 0x02 = 0x43 ✓
```

**回應解析：**
```
02        Start
46        CMD_SET_CHANNEL_CNF
01        Length
[02]      新頻道 (0~4)
[43]      Checksum
```

**C 程式碼：**
```c
uint8_t payload[1] = { channel };
Titania_SendCommand(huart, 0x06, payload, 1);
uint8_t resp[5];
HAL_UART_Receive(huart, resp, 5, 100);
```

---

### 3️⃣ 設定 UserSettings（非揮發）— CMD_SET_REQ ⭐ 重要

**用途：** 寫入 flash 中的永久設定（UART baudrate、預設頻道、NetID、Addr 等）。重啟後仍保持。

**常用 UserSettings 參數表：**

| 參數名 | Memory Position (Dec / Hex) | 長度 | 值範圍 | 預設值 | 說明 |
|--------|---------------------------|------|--------|--------|------|
| `PHY_DefaultChannel` | 42 / 0x2A | 1 byte | 0~4 | 2 | 重啟後使用的頻道 |
| `UART_Baudrate` | 80 / 0x50 | 4 bytes | 1200~115200 | 9600 | UART 速率（小端序 LSB first） |
| `MAC_DefaultDestNetID` | TODO | 2 bytes | 0x0000~0xFFFF | 0x0000 | 預設目的 NetID |
| `MAC_DefaultDestAddrLSB` | TODO | 2 bytes | 0x0000~0xFFFF | 0x0000 | 預設目的位址 LSB |
| `UART_Timeout` | TODO | 2 bytes | [見表] | [見表] | UART 無字元多久後自動送包 |
| `PHY_PAPower` | TODO | 1 byte | [見表] | [見表] | 發射功率索引 (-11~+15 dBm) |
| `RF_ConfigIndex` | TODO | 1 byte | [見表] | 2 | RF 設定（data rate、調變） |
| `MAC_NumRetrys` | TODO | 1 byte | 0~N | [見表] | 重送次數 |

**指令格式：**
```
Start  CMD  LEN    MPOS  NBYTES  DATA...  Checksum
  02   09  [2+N]  [MP]  [LEN]   [...]     [CS]
```

- **LEN = 2 + 資料長度** （包括 MPOS + NBYTES 欄位）
- **MPOS = Memory Position** （十進位或十六進位）
- **NBYTES = 要寫多少 bytes**
- **DATA = 實際資料**
- **Checksum = 從 0x02 到 最後一個 DATA 的 XOR**

**範例 1 - 設定預設頻道為 Channel 3（非揮發）：**
```
發送：02 09 03 2A 01 03 4B
      02 09 03 2A 01 03 4B
      ↑  ↑  ↑  ↑  ↑  ↑  ↑
     ST CMD LEN MP NB DC CS

回應：02 49 00 00 4B
      ↑  ↑  ↑  ↑  ↑
     ST CMD LEN ST CS

Checksum 計算:
  發送: 0x02 ^ 0x09 ^ 0x03 ^ 0x2A ^ 0x01 ^ 0x03 = 0x4B ✓
  回應: 0x02 ^ 0x49 ^ 0x00 ^ 0x00 = 0x4B ✓
```

**範例 2 - 設定 UART Baudrate 為 57600（非揮發）：**

57600 = 0x0000E100 (十六進位)  
小端序 (LSB first)：[0x00, 0xE1, 0x00, 0x00]

```
發送：02 09 06 50 04 00 E1 00 00 CS
      ↑  ↑  ↑  ↑  ↑  ↑ ↑ ↑ ↑ ↑ ↑
     ST CMD LEN MP NB D0 D1 D2 D3 CS

MPOS = 0x50 (80 十進位)
NBYTES = 04
DATA = [00 E1 00 00]
LEN = 2 + 4 = 06
Checksum = 0x02 ^ 0x09 ^ 0x06 ^ 0x50 ^ 0x04 ^ 0x00 ^ 0xE1 ^ 0x00 ^ 0x00 = ?

回應：02 49 00 00 4B
     (Status=0x00 表示成功)
```

**回應解析：**
```
02            Start
49            CMD_SET_CNF (確認)
00            Length
00            Status (0x00 = 成功, 非 0 = 失敗)
4B            Checksum
```

**C 程式碼：**
```c
// 設定 UART Baudrate 為 57600
uint32_t baudrate = 57600;
uint8_t payload[6];
payload[0] = 0x50;                              // Memory Position (UART_Baudrate)
payload[1] = 0x04;                              // 資料長度 4 bytes
payload[2] = (uint8_t)(baudrate & 0xFF);
payload[3] = (uint8_t)((baudrate >> 8) & 0xFF);
payload[4] = (uint8_t)((baudrate >> 16) & 0xFF);
payload[5] = (uint8_t)((baudrate >> 24) & 0xFF);

Titania_SendCommand(huart, 0x09, payload, 6);
uint8_t resp[5];
HAL_UART_Receive(huart, resp, 5, 200);

// 檢查 resp[3] == 0x00 (Status OK)
```

---

### 4️⃣ 讀取 UserSettings — CMD_GET_REQ

**用途：** 讀出 flash 中現在儲存的設定值（例如確認現在 baudrate 是多少）。

**指令格式：**
```
Start  CMD  LEN  MPOS   CS
  02   0B   01   [MP]  [CS]
```

**範例 - 讀取 PHY_DefaultChannel：**
```
發送：02 0B 01 2A 21
      ↑  ↑  ↑  ↑  ↑
     ST CMD LEN MP CS

Checksum = 0x02 ^ 0x0B ^ 0x01 ^ 0x2A = 0x21 ✓

回應：02 4B 02 00 03 4D
      ↑  ↑  ↑  ↑  ↑  ↑
     ST CMD LEN ST DA CS

解析：
  Status = 0x00 (成功)
  Data = 0x03 (目前預設頻道是 Channel 3)
  Checksum = 0x02 ^ 0x4B ^ 0x02 ^ 0x00 ^ 0x03 = 0x4D ✓
```

**C 程式碼：**
```c
uint8_t mem_pos = 0x2A;  // PHY_DefaultChannel
Titania_SendCommand(huart, 0x0B, &mem_pos, 1);

uint8_t resp[6];  // Start + CMD + LEN + Status + Data + CS
HAL_UART_Receive(huart, resp, 6, 200);

uint8_t current_channel = resp[4];  // 第 5 byte 是資料
```

---

### 5️⃣ 工廠重置 — CMD_FACTORY_RESET_REQ ⭐ 救急指令

**用途：** 清除所有 UserSettings，回到出廠預設值。

| 項目 | 回復值 |
|------|--------|
| UART Baudrate | 9600 |
| PHY_DefaultChannel | 2 (169.4375 MHz) |
| MAC_DefaultDestNetID | 0x0000 |
| MAC_DefaultDestAddrLSB | 0x0000 |
| 所有其他設定 | 出廠預設 |

**指令：**
```
Start  CMD  LEN  CS
  02   0D   00   4D
```

Checksum = 0x02 ^ 0x0D ^ 0x00 = 0x4D ✓

**回應：**
```
Start  CMD  LEN  Status  CS
  02   4C   00   00      4E
```

Checksum = 0x02 ^ 0x4C ^ 0x00 ^ 0x00 = 0x4E ✓

**C 程式碼：**
```c
Titania_SendCommand(huart, 0x0D, NULL, 0);
uint8_t resp[5];
HAL_UART_Receive(huart, resp, 5, 500);

// 模組會重啟，UART 變回 9600，所有設定清零
```

---

### 6️⃣ 透明模式傳送 — CMD_DATA_REQ

**用途：** 在透明模式下，透過 UART 送進來的資料會被打包成 MAC 訊號透過無線送出。

**指令格式：**
```
Start  CMD  LEN    MAC_DATA...  CS
  02   80   [N]    [...]        [CS]
```

- **LEN = MAC 訊號的長度（bytes）**
- **MAC_DATA = 你要發送的內容（payload）**
- **Checksum = 從 0x02 到最後一個 DATA 的 XOR**

**範例 - 發送 5 bytes 資料 "Hello"：**
```
發送：02 80 05 48 65 6C 6C 6F CS
      ↑  ↑  ↑  ↑  ↑  ↑ ↑ ↑ ↑ ↑
     ST CMD LEN H  e  l l o CS

"Hello" 的 ASCII 值：
  H=0x48, e=0x65, l=0x6C, l=0x6C, o=0x6F

Checksum = 0x02 ^ 0x80 ^ 0x05 ^ 0x48 ^ 0x65 ^ 0x6C ^ 0x6C ^ 0x6F = ?

回應：02 C0 00 00 C0
      ↑  ↑  ↑  ↑  ↑
     ST CMD LEN ST CS

Status = 0x00 (成功，訊號已排隊發送)
```

**C 程式碼：**
```c
uint8_t payload[5] = { 0x48, 0x65, 0x6C, 0x6C, 0x6F };  // "Hello"
Titania_SendCommand(huart, 0x80, payload, 5);

uint8_t resp[5];
HAL_UART_Receive(huart, resp, 5, 100);
// resp[3] = Status
```

---

## 📊 Checksum 計算邏輯

**XOR 從 Start (0x02) 一路算到最後一個 Data，不含 Checksum 本身。**

```c
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;
}

// 使用方式：
uint8_t frame[10] = { 0x02, 0x09, 0x03, 0x2A, 0x01, 0x03, ... };
uint8_t cs = CalcChecksum(frame, 6);  // 不包括 Checksum 欄位本身
frame[6] = cs;
```

---

## 🎯 實務操作流程

### A. 初始化一個新 Titania 模組

1. **確認 UART 連線** → 用邏輯分析儀看波形確認 baudrate 是 9600
2. **讀取現在設定** → CMD_GET_REQ 讀 0x2A (PHY_DefaultChannel) 和 0x50 (UART_Baudrate)
3. **寫入新設定** → CMD_SET_REQ 改 UART_Baudrate、PHY_DefaultChannel、NetID、Addr 等
4. **軟重啟** → CMD_RESET_REQ，等 100~500 ms
5. **切換 STM32 UART 波特率** → 改成新的 baudrate
6. **驗證** → 再讀一次設定確認有存進去

### B. 忘記自己設的 baudrate

1. **用邏輯分析儀** 抓 Titania 上電時 TX 線的波形，反推現在是多少 baudrate
2. **用那個 baudrate 連接** STM32
3. **發送 CMD_FACTORY_RESET_REQ** 清所有設定（UART 回 9600）
4. **切換 STM32 UART 回 9600**
5. **重新用 CMD_SET_REQ 設定一次**

### C. 要改無線頻道（runtime 臨時改）

1. **發 CMD_SET_CHANNEL_REQ** (0x06) 改當前頻道
2. **不需要 reset**，立即生效
3. **但重啟後會失效**（回到預設頻道）
4. 若要永久改，用 CMD_SET_REQ (0x09) 改 PHY_DefaultChannel + CMD_RESET_REQ

### D. 要設定預設 NetID / Addr（MAC 層位址）

1. **用 CMD_SET_REQ (0x09)** 寫入：
   - `MAC_DefaultDestNetID` (memory position TODO)
   - `MAC_DefaultDestAddrLSB` (memory position TODO)
2. **再 CMD_RESET_REQ** 重啟讓設定生效
3. 之後所有透明模式的 MAC 訊號都會用這個 NetID/Addr 作為預設目的地

---

## 🔗 常用組合指令序列

### 序列 1：初始化 + 改速率 57600 + 頻道 3 + NetID 0x0001

```
Step 1: CMD_SET_REQ UART_Baudrate = 57600
  → 發送：02 09 06 50 04 00 E1 00 00 CS
  → 等待回應 02 49 00 00 4B

Step 2: CMD_SET_REQ PHY_DefaultChannel = 3
  → 發送：02 09 03 2A 01 03 4B
  → 等待回應 02 49 00 00 4B

Step 3: CMD_SET_REQ MAC_DefaultDestNetID = 0x0001
  → 發送：02 09 04 [MEM] 02 01 00 CS
  → 等待回應 02 49 00 00 4B

Step 4: CMD_RESET_REQ
  → 發送：02 05 00 07
  → 等待 500ms 讓模組重啟
  → 接收回應 02 45 01 00 46

Step 5: STM32 UART 改 57600 baud
  → 重新初始化 UART

Step 6: 驗證設定（可選）
  → CMD_GET_REQ 讀各個參數確認
```

### 序列 2：工廠重置（救急）

```
Step 1: CMD_FACTORY_RESET_REQ
  → 發送：02 0D 00 4D
  → 等待 500ms，模組重啟
  → 接收回應 02 4C 00 00 4E

Step 2: STM32 UART 改回 9600 baud
  → 重新初始化 UART

Step 3: 確認恢復（可選）
  → CMD_GET_REQ 讀 0x50 (UART_Baudrate)
  → 應該讀到 9600
```

---

## 📌 重要提醒

✅ **UART 設定改變後必須 reset**  
- 改 UART_Baudrate 或其他非揮發參數後，**必須** CMD_RESET_REQ，否則設定寫進 flash 但模組沒用新值運作。

✅ **Checksum 計算務必正確**  
- 差一個 bit 就會被模組拒絕或誤解。

✅ **記得同步 STM32 UART 波特率**  
- 改完 Titania UART_Baudrate 後，STM32 也要改成一樣的速率，否則無法通訊。

✅ **NetID / Addr 的 memory position 要對應手冊**  
- 上表中 TODO 的位置需要你查手冊第 8.13~8.16 章補上正確的十進位或十六進位位置。

✅ **工廠重置會清所有設定**  
- 包括 UART_Baudrate、頻道、NetID、Addr、RF_ConfigIndex 等，全部回到出廠預設。

---

## 🛠 STM32 快速範本代碼

```c
#include "stm32f1xx_hal.h"

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;
}

// 發送指令
void SendTitaniaCmd(uint8_t cmd, uint8_t *data, uint8_t len)
{
    uint8_t frame[64];
    uint8_t idx = 0;

    frame[idx++] = 0x02;  // Start
    frame[idx++] = cmd;
    frame[idx++] = len;
    for (uint8_t i = 0; i < len; i++)
        frame[idx++] = data[i];
    
    frame[idx] = CalcChecksum(frame, idx);
    idx++;

    HAL_UART_Transmit(&huart1, frame, idx, 100);
}

// 例子：改 baudrate 為 57600 + 頻道 3 + reset
void InitTitania(void)
{
    uint8_t payload[6];
    uint8_t resp[10];

    // 1. 改 UART Baudrate 57600
    payload[0] = 0x50;      // Memory Pos (UART_Baudrate)
    payload[1] = 0x04;      // Length
    payload[2] = 0x00;      // 57600 = 0x0000E100 (LE)
    payload[3] = 0xE1;
    payload[4] = 0x00;
    payload[5] = 0x00;
    SendTitaniaCmd(0x09, payload, 6);
    HAL_UART_Receive(&huart1, resp, 5, 200);

    // 2. 改預設頻道為 3
    payload[0] = 0x2A;      // Memory Pos (PHY_DefaultChannel)
    payload[1] = 0x01;      // Length
    payload[2] = 0x03;      // Channel 3
    SendTitaniaCmd(0x09, payload, 3);
    HAL_UART_Receive(&huart1, resp, 5, 200);

    // 3. Reset 讓設定生效
    SendTitaniaCmd(0x05, NULL, 0);
    HAL_Delay(500);  // 等模組重啟
    HAL_UART_Receive(&huart1, resp, 5, 500);

    // 4. 改 STM32 UART 為 57600
    huart1.Init.BaudRate = 57600;
    HAL_UART_Init(&huart1);
}
```

---

## 📚 參考文檔

- **Würth Titania Manual:** Manual-um-titania-260701111100x (rev4.5)
- **Titania 規格表:** 2607011111100x datasheet
- **Band D Frequencies:** EN 300 220 (歐盟標準)

---

**最後更新：** 2026-03-10  
**作者備註：** 本文檔整理自 Titania 官方手冊，所有指令與 memory position 須對應實際硬體版本。