From 68c43c5adef03f00836d83b37cb83a294d8b0354 Mon Sep 17 00:00:00 2001
From: yincheng.zhong <634916154@qq.com>
Date: 星期四, 13 十一月 2025 17:04:28 +0800
Subject: [PATCH] 晚上SBUS信号解析,成功控制车走
---
STM32H743/FML/SBUS_使用说明.md | 412 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 412 insertions(+), 0 deletions(-)
diff --git "a/STM32H743/FML/SBUS_\344\275\277\347\224\250\350\257\264\346\230\216.md" "b/STM32H743/FML/SBUS_\344\275\277\347\224\250\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..7a32083
--- /dev/null
+++ "b/STM32H743/FML/SBUS_\344\275\277\347\224\250\350\257\264\346\230\216.md"
@@ -0,0 +1,412 @@
+# SBUS 鑸ā閬ユ帶鍣ㄦ帴鏀舵ā鍧椾娇鐢ㄨ鏄�
+
+## 姒傝堪
+鏈ā鍧楀疄鐜颁簡 SBUS 鍗忚锛團utaba SBUS锛夌殑瑙f瀽锛岀敤浜庢帴鏀惰埅妯¢仴鎺у櫒淇″彿銆�
+
+### 纭欢閰嶇疆
+- **UART**: UART4 (STM32H743)
+- **娉㈢壒鐜�**: 100kbps
+- **鏍煎紡**: 8E2 (8 鏁版嵁浣�, 鍋舵牎楠�, 2 鍋滄浣�)
+- **鎺ユ敹妯″紡**: DMA 寰幆鎺ユ敹
+- **淇″彿鍙嶅悜**: 宸插惎鐢� RX 鍙嶅悜鍔熻兘锛堥�傞厤 SBUS 鍙嶅悜閫昏緫锛�
+
+### 鍗忚瑙勬牸
+- **甯ч暱搴�**: 25 瀛楄妭
+- **甯уご**: 0x0F
+- **甯у熬**: 0x00
+- **閫氶亾鏁�**: 16 涓ā鎷熼�氶亾 (11-bit, 0~2047) + 2 涓暟瀛楅�氶亾 (CH17/CH18)
+- **鏍囧織浣�**: Frame Lost銆丗ailsafe
+- **甯х巼**: 绾� 7~14 ms/甯� (鍙栧喅浜庡彂灏勬満)
+
+---
+
+## API 鎺ュ彛
+
+### 1. 鍒濆鍖�
+```c
+#include "SBUS.h"
+
+void app_task(void *pvParameters)
+{
+ // 鍦ㄤ换鍔″垵濮嬪寲闃舵璋冪敤锛堝凡闆嗘垚鍒� app.c锛�
+ SBUS_Init();
+
+ while(1)
+ {
+ // 涓诲惊鐜疆璇�
+ SBUS_Poll();
+ // ...
+ }
+}
+```
+
+### 2. 鑾峰彇瀹屾暣閫氶亾鏁版嵁
+```c
+ST_SBUSData sbusData;
+
+if (SBUS_GetData(&sbusData) == HIDO_TRUE)
+{
+ // 鎴愬姛鑾峰彇鏁版嵁锛堜俊鍙锋湁鏁堬級
+ printf("CH0: %u, CH1: %u, CH2: %u\n",
+ sbusData.m_au16Channels[0],
+ sbusData.m_au16Channels[1],
+ sbusData.m_au16Channels[2]);
+
+ // 妫�鏌ュけ鎺т繚鎶ゆ爣蹇�
+ if (sbusData.m_u8Failsafe)
+ {
+ printf("WARNING: Failsafe activated!\n");
+ }
+
+ // 妫�鏌ュ抚涓㈠け鏍囧織
+ if (sbusData.m_u8FrameLost)
+ {
+ printf("WARNING: Frame lost!\n");
+ }
+
+ // 鏁板瓧閫氶亾
+ printf("CH17: %u, CH18: %u\n", sbusData.m_u8Ch17, sbusData.m_u8Ch18);
+}
+else
+{
+ // 淇″彿瓒呮椂鎴栨棤鏁版嵁
+ printf("SBUS signal lost\n");
+}
+```
+
+### 3. 鑾峰彇鍗曚釜閫氶亾鍊�
+```c
+// 鑾峰彇娌归棬閫氶亾 (鍋囪 CH2 涓烘补闂�)
+HIDO_UINT16 throttle = SBUS_GetChannel(2); // 0~2047
+
+// 褰掍竴鍖栧埌 [-1.0, 1.0]
+float throttle_normalized = (throttle - 1024.0f) / 1024.0f;
+
+// 鏄犲皠鍒扮數鏈洪�熷害 (0~100%)
+uint8_t motor_speed = (throttle * 100) / 2047;
+```
+
+### 4. 鑾峰彇鏁板瓧閫氶亾
+```c
+// 鑾峰彇寮�鍏崇姸鎬� (CH17 閫氬父瀵瑰簲閬ユ帶鍣ㄥ紑鍏�)
+HIDO_UINT8 switch_state = SBUS_GetDigitalChannel(17); // 0 鎴� 1
+
+if (switch_state == 1)
+{
+ printf("Switch ON\n");
+}
+else
+{
+ printf("Switch OFF\n");
+}
+```
+
+### 5. 妫�鏌ヤ俊鍙锋湁鏁堟��
+```c
+// 妫�鏌ユ渶杩� 100ms 鍐呮槸鍚︽敹鍒� SBUS 甯�
+if (SBUS_IsSignalValid(100) == HIDO_TRUE)
+{
+ printf("SBUS signal OK\n");
+}
+else
+{
+ printf("SBUS signal LOST (timeout)\n");
+ // 杩涘叆澶辨帶淇濇姢妯″紡
+ // ...
+}
+```
+
+### 6. 鑾峰彇缁熻淇℃伅
+```c
+HIDO_UINT32 frameCount, errorCount;
+
+SBUS_GetStats(&frameCount, &errorCount);
+
+printf("Total frames: %u, Errors: %u (%.2f%%)\n",
+ frameCount, errorCount,
+ (frameCount > 0) ? (errorCount * 100.0f / frameCount) : 0.0f);
+```
+
+---
+
+## 鏁版嵁缁撴瀯璇﹁В
+
+### ST_SBUSData
+```c
+typedef struct
+{
+ HIDO_UINT16 m_au16Channels[16]; // 16 涓ā鎷熼�氶亾, 鑼冨洿 0~2047
+ HIDO_UINT8 m_u8Ch17; // 鏁板瓧閫氶亾 17, 鍊� 0 鎴� 1
+ HIDO_UINT8 m_u8Ch18; // 鏁板瓧閫氶亾 18, 鍊� 0 鎴� 1
+ HIDO_UINT8 m_u8FrameLost; // 甯т涪澶辨爣蹇� (鍙戝皠鏈烘爣璁�)
+ HIDO_UINT8 m_u8Failsafe; // 澶辨帶淇濇姢鏍囧織 (鎺ユ敹鏈烘爣璁�)
+ HIDO_UINT32 m_u32LastUpdateTick; // 鏈�鍚庢洿鏂版椂鍒� (HAL_GetTick)
+ HIDO_UINT32 m_u32FrameCount; // 绱鎺ユ敹甯ф暟
+ HIDO_UINT32 m_u32ErrorCount; // 绱閿欒甯ф暟 (甯уご/甯у熬鏍¢獙澶辫触)
+} ST_SBUSData;
+```
+
+### 閫氶亾鏄犲皠绀轰緥锛堝父瑙侀仴鎺у櫒甯冨眬锛�
+| 閫氶亾 | 甯歌鍔熻兘 | 鍊艰寖鍥� | 涓績鍊� |
+|------|----------|--------|--------|
+| CH0 | 妯粴 (Aileron) | 0~2047 | 1024 |
+| CH1 | 淇话 (Elevator) | 0~2047 | 1024 |
+| CH2 | 娌归棬 (Throttle) | 0~2047 | 172 (鏈�浣�) |
+| CH3 | 鏂瑰悜 (Rudder) | 0~2047 | 1024 |
+| CH4 | 杈呭姪寮�鍏� 1 | 0~2047 | - |
+| CH5 | 杈呭姪寮�鍏� 2 | 0~2047 | - |
+| ... | 鍏朵粬鑷畾涔� | 0~2047 | - |
+| CH17 | 鏁板瓧寮�鍏� 1 | 0/1 | - |
+| CH18 | 鏁板瓧寮�鍏� 2 | 0/1 | - |
+
+---
+
+## 鍏稿瀷搴旂敤鍦烘櫙
+
+### 鍦烘櫙1锛氭墜鍔ㄩ仴鎺ц崏鍧満
+```c
+void Manual_Control_Task(void)
+{
+ ST_SBUSData sbus;
+
+ if (SBUS_GetData(&sbus) != HIDO_TRUE)
+ {
+ // 淇″彿涓㈠け锛屽仠姝㈢數鏈�
+ Motor_Stop();
+ return;
+ }
+
+ // 澶辨帶淇濇姢瑙﹀彂锛屽仠姝�
+ if (sbus.m_u8Failsafe)
+ {
+ Motor_Stop();
+ return;
+ }
+
+ // 鎻愬彇鎺у埗閲� (鍋囪 CH1=鍓嶈繘/鍚庨��, CH3=宸﹀彸杞悜)
+ int16_t forward = (int16_t)sbus.m_au16Channels[1] - 1024; // -1024~+1023
+ int16_t turn = (int16_t)sbus.m_au16Channels[3] - 1024; // -1024~+1023
+
+ // 褰掍竴鍖栧埌 [-100, 100]
+ int8_t forward_cmd = (forward * 100) / 1024;
+ int8_t turn_cmd = (turn * 100) / 1024;
+
+ // 鍙戦�佸埌宸�熺數鏈烘帶鍒跺櫒
+ DiffDrive_SetCommand(forward_cmd, turn_cmd);
+}
+```
+
+### 鍦烘櫙2锛氭ā寮忓垏鎹紙鑷姩/鎵嬪姩锛�
+```c
+void Mode_Switch_Task(void)
+{
+ static uint8_t last_switch = 0;
+ uint8_t current_switch = SBUS_GetDigitalChannel(17);
+
+ // 妫�娴嬪紑鍏崇姸鎬佸彉鍖�
+ if (current_switch != last_switch)
+ {
+ if (current_switch == 1)
+ {
+ // 鍒囨崲鍒拌嚜鍔ㄦā寮�
+ System_SetMode(MODE_AUTO);
+ printf("Switched to AUTO mode\n");
+ }
+ else
+ {
+ // 鍒囨崲鍒版墜鍔ㄦā寮�
+ System_SetMode(MODE_MANUAL);
+ printf("Switched to MANUAL mode\n");
+ }
+ last_switch = current_switch;
+ }
+}
+```
+
+### 鍦烘櫙3锛氬け鎺т繚鎶ょ洃鎺�
+```c
+void Failsafe_Monitor_Task(void)
+{
+ static uint32_t last_valid_tick = 0;
+
+ if (SBUS_IsSignalValid(200) == HIDO_TRUE)
+ {
+ last_valid_tick = HAL_GetTick();
+ }
+ else
+ {
+ uint32_t lost_duration = HAL_GetTick() - last_valid_tick;
+
+ if (lost_duration > 1000) // 淇″彿涓㈠け瓒呰繃 1 绉�
+ {
+ // 瑙﹀彂绱ф�ュ仠姝�
+ Emergency_Stop();
+ printf("EMERGENCY: SBUS signal lost for %u ms\n", lost_duration);
+ }
+ }
+}
+```
+
+---
+
+## 璋冭瘯涓庤瘖鏂�
+
+### 鎵撳嵃瀹炴椂閫氶亾鍊�
+```c
+void SBUS_Debug_Print(void)
+{
+ ST_SBUSData sbus;
+
+ if (SBUS_GetData(&sbus) == HIDO_TRUE)
+ {
+ printf("SBUS Channels:\n");
+ for (uint8_t i = 0; i < 16; i++)
+ {
+ printf(" CH%02u: %4u", i, sbus.m_au16Channels[i]);
+ if ((i + 1) % 4 == 0) printf("\n");
+ }
+ printf(" CH17: %u, CH18: %u\n", sbus.m_u8Ch17, sbus.m_u8Ch18);
+ printf(" FrameLost: %u, Failsafe: %u\n", sbus.m_u8FrameLost, sbus.m_u8Failsafe);
+ printf(" Stats: Frames=%u, Errors=%u\n", sbus.m_u32FrameCount, sbus.m_u32ErrorCount);
+ }
+ else
+ {
+ printf("SBUS: No signal\n");
+ }
+}
+```
+
+### 淇″彿璐ㄩ噺妫�娴�
+```c
+void SBUS_Quality_Check(void)
+{
+ HIDO_UINT32 frames, errors;
+ SBUS_GetStats(&frames, &errors);
+
+ if (frames > 1000) // 绱Н瓒冲鏍锋湰
+ {
+ float error_rate = (errors * 100.0f) / frames;
+
+ if (error_rate > 5.0f)
+ {
+ printf("WARNING: High SBUS error rate: %.2f%%\n", error_rate);
+ printf(" -> Check cable connection\n");
+ printf(" -> Check RX pin inversion setting\n");
+ }
+ else
+ {
+ printf("SBUS quality: Good (error rate: %.2f%%)\n", error_rate);
+ }
+ }
+}
+```
+
+---
+
+## 娉ㄦ剰浜嬮」
+
+### 1. 淇″彿鍙嶅悜
+- SBUS 鍗忚浣跨敤鍙嶅悜閫昏緫锛坕dle high = 0V, idle low = 3.3V锛�
+- STM32H7 UART4 宸插惎鐢� `UART_ADVFEATURE_RXINV_ENABLE`
+- 濡傛灉鏀跺埌鐨勬暟鎹叏鏄敊璇抚锛屾鏌ユ槸鍚﹂渶瑕佺鐢ㄥ弽鍚戝姛鑳�
+
+### 2. 娉㈢壒鐜囧宸�
+- SBUS 鏍囧噯娉㈢壒鐜囦负 100kbps
+- STM32 鍐呴儴鏃堕挓璇樊闇�鎺у埗鍦� 卤2% 浠ュ唴
+- 濡傛灉甯ч敊璇巼楂橈紝鍙井璋冩尝鐗圭巼 (99000 鎴� 101000)
+
+### 3. DMA 缂撳啿鍖哄ぇ灏�
+- 褰撳墠璁剧疆涓� 128 瀛楄妭锛堝彲瀹圭撼 5 甯э級
+- 濡傛灉涓诲惊鐜疆璇㈤棿闅旇緝闀匡紙>50ms锛夛紝寤鸿澧炲ぇ缂撳啿鍖�
+
+### 4. 甯х巼涓庡欢杩�
+- SBUS 甯ч棿闅旂害 7~14ms
+- `SBUS_Poll()` 搴旇嚦灏戜互 20Hz 棰戠巼璋冪敤锛堝綋鍓� app_task 绾� 74Hz锛�
+- 鎺у埗寤惰繜: 閲囨牱寤惰繜 + 瑙f瀽寤惰繜 < 20ms
+
+### 5. 澶辨帶淇濇姢绛栫暐
+- 寤鸿鍚屾椂鐩戞帶 `m_u8Failsafe` 鏍囧織鍜� `SBUS_IsSignalValid()` 瓒呮椂
+- 澶辨帶鏃剁珛鍗冲仠姝㈡墍鏈夎繍鍔ㄨ緭鍑�
+- 鎭㈠淇″彿鍚庨渶鎵嬪姩閲嶆柊浣胯兘锛堥槻姝㈡剰澶栧惎鍔級
+
+### 6. 澶氱嚎绋嬪畨鍏�
+- 褰撳墠瀹炵幇鏈娇鐢ㄤ复鐣屽尯淇濇姢
+- 濡傞渶鍦� ISR 鎴栧叾浠栭珮浼樺厛绾т换鍔′腑璁块棶锛岄渶娣诲姞浜掓枼閿�
+
+---
+
+## 鏁呴殰鎺掓煡
+
+| 闂 | 鍙兘鍘熷洜 | 瑙e喅鏂规 |
+|------|----------|----------|
+| 鏃犳硶鎺ユ敹鏁版嵁 | UART4 鏈纭垵濮嬪寲 | 妫�鏌� `MX_UART4_Init()` 璋冪敤椤哄簭 |
+| 甯ч敊璇巼 100% | RX 淇″彿鍙嶅悜璁剧疆閿欒 | 鍒囨崲 `UART_ADVFEATURE_RXINV` 鐘舵�� |
+| 淇″彿瓒呮椂 | 鍙戝皠鏈烘湭寮�鍚垨璺濈杩囪繙 | 妫�鏌ラ仴鎺у櫒鐢垫簮鍜屽ぉ绾� |
+| 閫氶亾鍊兼姈鍔� | 骞叉壈鎴栨帴瑙︿笉鑹� | 妫�鏌ユ帴绾垮睆钄藉拰鎺ュ湴 |
+| 閮ㄥ垎閫氶亾鏃犳晥 | 鍙戝皠鏈洪�氶亾鏈縺娲� | 妫�鏌ュ彂灏勬満閫氶亾閰嶇疆 |
+| DMA 鏈Е鍙� | DMA 鍒濆鍖栨湭瀹屾垚 | 纭 `HAL_UART_Receive_DMA()` 宸茶皟鐢� |
+
+---
+
+## 鎺ョ嚎鍙傝��
+
+### 鏍囧噯 SBUS 鎺ュ彛锛�3 绾匡級
+```
+SBUS 妯″潡 STM32H743
+--------- ----------
+ GND -------> GND
+ 5V -------> 5V (鎴� VCC)
+ SBUS -------> UART4_RX (PA1 鎴栨牴鎹疄闄呭紩鑴�)
+```
+
+### 娉ㄦ剰
+- SBUS 淇″彿鐢靛钩涓� 3.3V TTL锛堥儴鍒嗘ā鍧楅渶瑕佺數骞宠浆鎹級
+- 纭繚 SBUS 杈撳嚭绔笌 STM32 RX 寮曡剼鐩磋繛锛堟棤闇�涓婃媺/涓嬫媺鐢甸樆锛�
+
+---
+
+## 鎵╁睍鍔熻兘寤鸿
+
+### 1. 涓綅鏍″噯
+```c
+void SBUS_CalibrateCenter(uint8_t channel)
+{
+ uint16_t center_value = SBUS_GetChannel(channel);
+ // 淇濆瓨鍒� Flash 鎴栭厤缃枃浠�
+ Config_SetChannelCenter(channel, center_value);
+}
+```
+
+### 2. 閫氶亾鏄犲皠閲嶅畾涔�
+```c
+typedef enum {
+ RC_AILERON = 0,
+ RC_ELEVATOR = 1,
+ RC_THROTTLE = 2,
+ RC_RUDDER = 3,
+ RC_SWITCH_A = 4,
+ RC_SWITCH_B = 5,
+} E_RCChannel;
+
+uint16_t RC_GetMappedChannel(E_RCChannel ch)
+{
+ return SBUS_GetChannel(g_channel_map[ch]);
+}
+```
+
+### 3. 鎸囨暟鏇茬嚎璋冩暣
+```c
+int16_t RC_ApplyExpo(int16_t raw_value, float expo_factor)
+{
+ float normalized = raw_value / 1024.0f; // -1.0 ~ 1.0
+ float expo = expo_factor * normalized * normalized * normalized +
+ (1 - expo_factor) * normalized;
+ return (int16_t)(expo * 1024.0f);
+}
+```
+
+---
+
+鐢熸垚鏃堕棿锛�2025-11-13
+妯″潡鐗堟湰锛歷1.0
+缁存姢鑰咃細椤圭洰鍥㈤槦
--
Gitblit v1.9.3