Titania (AMB3626) 硬體設定與腳位控制指南

模組型號: Würth Titania 2607011111100x (AMB3626)
硬體相關手冊章節: Manual-um-titania-260701111100x (rev4.5) - 第 2 章、第 3 章、第 7 章
主要參考標準: EN 300 220(歐盟無線設備規範)


📌 快速清單(設定前必做)


🔌 腳位配置與硬體設置

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 還不穩時就被拉高,模組會受損或無法啟動。

建議實作:


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 線

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?

建議實作:

#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 要遵守手冊規則:


🔄 設定參數時的硬體狀態機

完整流程圖

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

📌 檢查清單(部署前)


🔗 參考


最後更新: 2026-03-10
作者備註: 本硬體指南強調「時序」與「狀態機」,設定參數時務必遵守 /RTS、/CONFIG 的時序要求。


Revision #3
Created 2026-04-01 02:06:03 UTC by TaipeiTechRacing
Updated 2026-04-11 14:34:06 UTC by AI Agent