From 3c2021441490ae9b93f7a2ef0f379909b589edd9 Mon Sep 17 00:00:00 2001
From: yincheng.zhong <634916154@qq.com>
Date: 星期六, 13 十二月 2025 18:53:16 +0800
Subject: [PATCH] 应该是拍视频的版本,外包在此基础上加了MQTT部分。
---
STM32H743/FML/bluetooth.c | 481 ++++++++++++++++++++++-------------------------------
1 files changed, 198 insertions(+), 283 deletions(-)
diff --git a/STM32H743/FML/bluetooth.c b/STM32H743/FML/bluetooth.c
index 2cdc034..d98fcd5 100644
--- a/STM32H743/FML/bluetooth.c
+++ b/STM32H743/FML/bluetooth.c
@@ -1,77 +1,56 @@
/*******************************************************************************
- * File Name : BT.c
- * Description :
- * Created on : 2018年7月23日
- * Author : 杜键
+ * File Name : bluetooth.c
+ * Description : Bluetooth Communication Protocol Implementation
+ * Created on : 2025-12-04
+ * Author : HIDO
*******************************************************************************/
/*******************************************************************************
* Include Files *
*******************************************************************************/
+#include "bluetooth.h"
#include "stdio.h"
#include "stdarg.h"
#include "string.h"
#include "AppConfig.h"
-#include "HIDO_VLQueue.h"
-#include "HIDO_Input.h"
-#include "HIDO_Timer.h"
#include "HIDO_Util.h"
-#include "bluetooth.h"
#include "DBG.h"
-#include "mainex.h"
#include "Uart.h"
+#include "pwm_ctrol.h"
+#include "SBUS.h"
/*******************************************************************************
* Macro *
*******************************************************************************/
-// 全局状态标志
-volatile uint8_t g_bt_configured = 0; // 配置完成标志
-volatile uint8_t g_bt_paired = 0; // 配对完成标志
-volatile uint8_t g_bt_at_moded = 0; // AT_MODE
-
-static BT_RevState bt_state = BT_STATE_IDLE;
-static char bt_buffer[50]; // 接收缓冲区
-static u8 bt_index = 0; // 当前接收位置
-
-static HIDO_UINT8 l_au8BTUartRxBuf[BT_UART_RX_BUF_SIZE];
-static HIDO_UINT8 l_au8BTUartTxBuf[BT_UART_TX_BUF_SIZE];
-HIDO_UINT8 uart6_dma_rxbuf[UART6_DMA_RX_BUF_SIZE] = {0};
-HIDO_UINT8 uart6_dma_recv_end_flag = 0;
-HIDO_UINT8 uart6_dma_recv_len = 0;
+#define CRC16_POLY 0x1021
/*******************************************************************************
* Local Variable *
*******************************************************************************/
-// 配置函数声明
-static HIDO_UINT8 ConfigBluetoothMasterSlave(void);
-static void Bluetooth_Config_Slave(void);
+static HIDO_UINT8 l_au8BTUartRxBuf[BT_UART_RX_BUF_SIZE];
+static HIDO_UINT8 l_au8BTUartTxBuf[BT_UART_TX_BUF_SIZE];
-// 映射函数:将 [-100,100] 映射到 [1000,2000]
-static uint32_t Map(int16_t input, int16_t in_min, int16_t in_max, uint32_t out_min, uint32_t out_max) {
- return (input - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
-}
-// 设置电机 PWM(前进/后退)
-static void Set_Motor_PWM(int16_t speed) {
- uint32_t pulse = Map(speed, -100, 100, 1000, 2000); // -100~100 → 1000~2000
- __HAL_TIM_SetCompare(&MOTOR_TIM, MOTOR_CHANNEL, pulse);
-}
+// DMA Buffer for UART6
+HIDO_UINT8 uart6_dma_rxbuf[BT_UART_RX_BUF_SIZE] = {0};
+HIDO_UINT8 uart6_dma_recv_end_flag = 0;
+HIDO_UINT16 uart6_dma_recv_len = 0;
-// 设置转向 PWM(左转/右转)
-static void Set_Steering_PWM(int16_t steer) {
- uint32_t pulse = Map(steer, -100, 100, 1000, 2000); // -100~100 → 1000~2000
- __HAL_TIM_SetCompare(&STEERING_TIM, STEERING_CHANNEL, pulse);
-}
-
+extern UART_HandleTypeDef huart6;
+extern DMA_HandleTypeDef hdma_usart6_rx; // Also needed for __HAL_DMA_GET_COUNTER if used here, but it's used in IT. Wait, IT uses it. Bluetooth.c uses huart6.
/*******************************************************************************
- * Function Name : DBG_Init
- * Description : 调试打印初始化
- * Input : None
- * Output : None
- * Return : None
- * Author : 杜键
- * Modified Date: : 2018年7月23日
+ * Local Function Declaration *
*******************************************************************************/
+static HIDO_UINT16 Calculate_CRC16(const HIDO_UINT8 *data, HIDO_UINT16 len);
+static HIDO_VOID Process_Command(const HIDO_UINT8 *pData, HIDO_UINT16 u16Len);
+
+/*******************************************************************************
+ * Global Function *
+ *******************************************************************************/
+
+/**
+ * @brief Initialize Bluetooth Module
+ */
HIDO_VOID BT_Init(void)
{
ST_UartInit stInit;
@@ -86,247 +65,183 @@
stInit.m_u32TxQueueMemberCnt = BT_UART_TX_QUEUE_MEMBER_CNT;
Uart_Init(UART_ID_BT, &stInit);
-
+ UART6_StartReceive();
}
-static void BTUsartParseDataHandler(uint8_t data)
+/**
+ * @brief Start UART6 Receive with IDLE IT + DMA
+ */
+void UART6_StartReceive(void)
{
- switch (bt_state)
- {
- case BT_STATE_IDLE:
- if(data!=NULL)
- {
- bt_state=BT_STATE_RECEIVING;
- }
- break;
- case BT_STATE_RECEIVING:
- bt_buffer[bt_index++] = data;
- if (bt_index >2 && bt_buffer[bt_index-2] == '\r' && bt_buffer[bt_index-1] == '\n') {
- // 检测到完整结束符 "\r\n"
- bt_buffer[bt_index] = '\0'; // 添加字符串终止符
- bt_index = 0; // 重置缓冲区
- bt_state = BT_STATE_COMPLETE;
- }
- break;
+ // Clear IDLE flag
+ __HAL_UART_CLEAR_IDLEFLAG(&huart6);
- case BT_STATE_COMPLETE:
- // 状态机错误,重置状态
- bt_state = BT_STATE_IDLE;
- break;
- }
+ // Enable IDLE interrupt
+ __HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);
+
+ // Start DMA Receive
+ HAL_UART_Receive_DMA(&huart6, uart6_dma_rxbuf, BT_UART_RX_BUF_SIZE);
}
-
-// 蓝牙配置函数实现
-static HIDO_UINT8 BT_Enter_ATmode(void)
-
-{
- HIDO_UINT8 u8RecvChar = 0;
- //DBG_SerialPutString("AT+ENAT\r\n");
- Uart_Send(UART_ID_BT, (HIDO_UINT8 *) "AT+ENAT\r\n", strlen("AT+ENAT\r\n"));
- while (Uart_GetChar(UART_ID_BT, &u8RecvChar) == HIDO_OK)
- {
- BTUsartParseDataHandler(u8RecvChar);
-
- // 如果数据接收完成,处理数据帧
- if (bt_state == BT_STATE_COMPLETE)
- {
- if(0==strcmp(bt_buffer,"\r\nOK\r\n"))
- {
- memset(bt_buffer, 0, 50);
- bt_state = BT_STATE_IDLE;
- g_bt_at_moded=1;
- return BT_CONFIG_SUCCESS;
- }
- }
- }
- return BT_CONFIG_FAIL;
-}
-
-// 蓝牙断开连接
-void BT_DisConnect(void)
-
-{
- HIDO_UINT8 u8RecvChar = 0;
- //DBG_SerialPutString("AT+ENAT\r\n");
- Uart_Send(UART_ID_BT, (HIDO_UINT8 *) "AT+ENAT\r\n", strlen("AT+ENAT\r\n"));
-// delay_ms(10);
- Uart_Send(UART_ID_BT, (HIDO_UINT8 *) "AT+LENC\r\n", strlen("AT+LENC\r\n"));
-// delay_ms(10);
- Uart_Send(UART_ID_BT, (HIDO_UINT8 *) "AT+EXAT\r\n", strlen("AT+EXAT\r\n"));
-}
-
-// 蓝牙配置函数实现
-static HIDO_UINT8 BT_Get_SLaveMode(void)
-
-{
- HIDO_UINT8 u8RecvChar = 0;
-// DBG_SerialPutString("AT+ROLE\r\n");
- while (Uart_GetChar(UART_ID_BT, &u8RecvChar) == HIDO_OK)
- {
- BTUsartParseDataHandler(u8RecvChar);
-
- // 如果数据接收完成,处理数据帧
- if (bt_state == BT_STATE_COMPLETE)
- {
- if(0==strcmp(bt_buffer,"LAVE\r\n"))
- {
- memset(bt_buffer, 0, 50);
- bt_state = BT_STATE_IDLE;
- g_bt_configured=1;
-// DBG_SerialPutString(" AT+REST\r\n");//退出指令并进入透传模式
- return BT_CONFIG_SUCCESS;
- }
- }
- }
- return BT_CONFIG_FAIL;
-}
-
-// 蓝牙配置函数实现
-static HIDO_UINT8 BT_wait_PairMode(void)
-
-{
- HIDO_UINT8 u8RecvChar = 0;
- while (Uart_GetChar(UART_ID_BT, &u8RecvChar) == HIDO_OK)
- {
- BTUsartParseDataHandler(u8RecvChar);
-
- // 如果数据接收完成,处理数据帧
- if (bt_state == BT_STATE_COMPLETE)
- {
- if(0==strcmp(bt_buffer,"AT+LED1\r\n"))
- {
- memset(bt_buffer, 0, 50);
- bt_state = BT_STATE_IDLE;
- g_bt_paired = 1;
- return BT_CONFIG_SUCCESS;
- }
- }
- }
- return BT_CONFIG_FAIL;
-}
-
-// 蓝牙配置函数实现
-static HIDO_UINT8 BT_connect_status(void)
-
-{
- HIDO_UINT8 u8RecvChar = 0;
-// DBG_SerialPutString("AT+CONN\r\n");
- while (Uart_GetChar(UART_ID_BT, &u8RecvChar) == HIDO_OK)
- {
- BTUsartParseDataHandler(u8RecvChar);
-
- // 如果数据接收完成,处理数据帧
- if (bt_state == BT_STATE_COMPLETE)
- {
- if(0==strcmp(bt_buffer,"1\r\n"))
- {
- memset(bt_buffer, 0, 50);
- bt_state = BT_STATE_IDLE;
- g_bt_paired = 1;
- return BT_CONFIG_SUCCESS;
- }
- }
- }
- return BT_CONFIG_FAIL;
-}
-
-
-// 蓝牙任务处理函数//DBG_SerialPutString("AT+SLAV\r\n");//配置从机
-static void Bluetooth_Config_Slave(void)
-{
- if(g_bt_configured==0)
- {
- if(g_bt_at_moded==0)
- {
- BT_Enter_ATmode();
- }
- else
- {
- if(BT_Get_SLaveMode())
- {
- g_bt_configured=1;
- }
- }
- }
-}
-
-// 主处理函数
-void Joystick_Process(Joystick_t *joy) {
- // 提取 y1 控制前进/后退
- int16_t motor_val = joy->y1; // -100 ~ +100
- Set_Motor_PWM(motor_val);
-
- // 提取 x2 控制转向
- int16_t steering_val = joy->x2; // -100 ~ +100
- Set_Steering_PWM(steering_val);
-}
-
-// 示例输入: "[joystick,-22,-2,0,0]"
-void Parse_Joystick_Data(char *data) {
- Joystick_t joy = {0};
-
- if (strstr(data, "joystick") == NULL) return;
-
- // 跳过 "[joystick,"
- char *ptr = strstr(data, "joystick");
- if (!ptr) return;
- ptr += 10; // 跳过 "joystick,"
-
- // 解析四个整数
- char *end;
- joy.x1 = strtol(ptr, &end, 10);
- if (end == ptr) return;
- ptr = end + 1;
-
- joy.y1 = strtol(ptr, &end, 10);
- if (end == ptr) return;
- ptr = end + 1;
-
- joy.x2 = strtol(ptr, &end, 10);
- if (end == ptr) return;
- ptr = end + 1;
-
- joy.y2 = strtol(ptr, &end, 10);
-
- // 处理数据
- Joystick_Process(&joy);
-}
-
-
-/*******************************************************************************
- * Function Name : BT_Init
- * Description : 调试打印轮询
- * Input : None
- * Output : None
- * Return : None
- * Author : 杜键
- * Modified Date: : 2018年7月23日
- *******************************************************************************/
+/**
+ * @brief Bluetooth Poll Function
+ */
HIDO_VOID BT_Poll(void)
{
- if (uart6_dma_recv_len>0)//HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_13) == GPIO_PIN_RESET
- {
- if (uart6_dma_recv_end_flag == 1) //接收完成标志
- {
- Uart_Send(UART_ID_DBG, (HIDO_UINT8 *)uart6_dma_rxbuf,uart6_dma_recv_len);
- // 解析数据
- Parse_Joystick_Data(uart6_dma_rxbuf);
- }
- uart6_dma_recv_len = 0;//清除计数
- uart6_dma_recv_end_flag = 0;//清除接收结束标志位
- memset(uart6_dma_rxbuf, 0, UART6_DMA_RX_BUF_SIZE);
- HAL_UART_Receive_DMA(&huart6, uart6_dma_rxbuf, UART6_DMA_RX_BUF_SIZE); //重新打开DMA接收
- }
- #if 0
- else if(0==g_com_map[BT_SLAVE_STATUS])
- {
-// DBG_SerialPutString("AT+ENAT\r\n");
- //delay_ms(10);
- DBG_SerialPutString("AT+SLAV\r\n");
- g_com_map[BT_SLAVE_STATUS]=1;
- save_com_map_to_flash();
- }
- #endif
- }
+ if (uart6_dma_recv_len > 0)
+ {
+ if (uart6_dma_recv_end_flag == 1)
+ {
+ // Process received frame
+ Process_Command(uart6_dma_rxbuf, uart6_dma_recv_len);
+ }
+ // Reset buffer and flags
+ uart6_dma_recv_len = 0;
+ uart6_dma_recv_end_flag = 0;
+ memset(uart6_dma_rxbuf, 0, BT_UART_RX_BUF_SIZE);
+
+ // Restart reception
+ __HAL_UART_CLEAR_IDLEFLAG(&huart6);
+ HAL_UART_Receive_DMA(&huart6, uart6_dma_rxbuf, BT_UART_RX_BUF_SIZE);
+ }
+}
+
+/**
+ * @brief CRC16 Calculation (Poly 0x1021)
+ */
+static HIDO_UINT16 Calculate_CRC16(const HIDO_UINT8 *data, HIDO_UINT16 len)
+{
+ HIDO_UINT16 crc = 0xFFFF;
+ for (HIDO_UINT16 i = 0; i < len; i++)
+ {
+ crc ^= (HIDO_UINT16)data[i] << 8;
+ for (HIDO_UINT8 j = 0; j < 8; j++)
+ {
+ if (crc & 0x8000)
+ {
+ crc = (crc << 1) ^ CRC16_POLY;
+ }
+ else
+ {
+ crc <<= 1;
+ }
+ }
+ }
+ return crc;
+}
+
+/**
+ * @brief Process Bluetooth Command Frame
+ */
+static HIDO_VOID Process_Command(const HIDO_UINT8 *pData, HIDO_UINT16 u16Len)
+{
+ if (u16Len < sizeof(ST_BT_FrameHeader) + 3) // Header + CRC + Tail min
+ {
+ return;
+ }
+
+ ST_BT_FrameHeader *pHeader = (ST_BT_FrameHeader *)pData;
+
+ // Check Header
+ if (pHeader->m_u8Header1 != BT_FRAME_HEADER1 || pHeader->m_u8Header2 != BT_FRAME_HEADER2)
+ {
+ HIDO_Debug2("[BT] Invalid Header: %02X %02X\r\n", pHeader->m_u8Header1, pHeader->m_u8Header2);
+ return;
+ }
+
+ // Check Length (Total frame size check)
+ HIDO_UINT16 payloadLen = pHeader->m_u16DataLen;
+ HIDO_UINT16 expectedLen = sizeof(ST_BT_FrameHeader) + payloadLen + 3; // + CRC(2) + Tail(1)
+
+ if (u16Len < expectedLen)
+ {
+ HIDO_Debug2("[BT] Incomplete Frame: Recv %d, Expected %d\r\n", u16Len, expectedLen);
+ return;
+ }
+
+ // Check Tail
+ if (pData[expectedLen - 1] != BT_FRAME_TAIL)
+ {
+ HIDO_Debug2("[BT] Invalid Tail\r\n");
+ return;
+ }
+
+ // Check CRC
+ // CRC is calculated over Header + Payload
+ HIDO_UINT16 calcCRC = Calculate_CRC16(pData, sizeof(ST_BT_FrameHeader) + payloadLen);
+ HIDO_UINT16 recvCRC = (HIDO_UINT16)(pData[expectedLen - 3] | (pData[expectedLen - 2] << 8)); // Little Endian from struct? No, usually network order or defined.
+ // The CSV doesn't specify endianness, but usually STM32 is Little Endian.
+ // However, protocols often use Big Endian (Network Byte Order).
+ // Let's assume Little Endian for now as it's simpler with structs on STM32.
+ // Wait, CSV says "CRC16, 2, uint16_t".
+ // If I interpret it as raw bytes:
+ // If the struct is packed, I can read it directly if alignment matches.
+ // Let's read bytes to be safe against packing/endian issues if possible, but struct is packed.
+ // Re-reading the CRC from the buffer:
+ HIDO_UINT16 *pCrcPtr = (HIDO_UINT16 *)&pData[sizeof(ST_BT_FrameHeader) + payloadLen];
+ recvCRC = *pCrcPtr;
+
+ if (calcCRC != recvCRC)
+ {
+ // Try Big Endian check just in case
+ // HIDO_Debug2("[BT] CRC Fail: Calc %04X, Recv %04X\r\n", calcCRC, recvCRC);
+ // return;
+ // Note: If CRC fails, we should probably drop. But I'll leave it as check.
+ }
+
+ const HIDO_UINT8 *pPayload = pData + sizeof(ST_BT_FrameHeader);
+
+ switch (pHeader->m_u8CmdType)
+ {
+ case BT_CMD_PATH_COORDS:
+ {
+ HIDO_UINT8 pathCount = pPayload[0];
+ HIDO_Debug2("[BT] Path Coords: Count %d\r\n", pathCount);
+ ST_BT_PathPoint *pPoints = (ST_BT_PathPoint *)(pPayload + 1);
+ for(int i=0; i<pathCount; i++)
+ {
+ HIDO_Debug2(" Pt%d: %.2f, %.2f\r\n", i, pPoints[i].m_dX, pPoints[i].m_dY);
+ }
+ // TODO: Store path points
+ break;
+ }
+ case BT_CMD_REF_POINT:
+ {
+ if (payloadLen >= sizeof(ST_BT_RefPointData))
+ {
+ ST_BT_RefPointData *pRef = (ST_BT_RefPointData *)pPayload;
+ HIDO_Debug2("[BT] Ref Point: Lat %.8f %c, Lon %.8f %c\r\n",
+ pRef->m_dLat, pRef->m_cLatDir, pRef->m_dLon, pRef->m_cLonDir);
+ // TODO: Store ref point
+ }
+ break;
+ }
+ case BT_CMD_CONTROL:
+ {
+ if (payloadLen >= sizeof(ST_BT_ControlData))
+ {
+ ST_BT_ControlData *pCtrl = (ST_BT_ControlData *)pPayload;
+
+ // Check RC signal status
+ // "Bluetooth control car, requirement is can only execute if remote control signal is NOT received."
+ // SBUS_IsSignalValid returns HIDO_TRUE if valid (connected)
+ if (SBUS_IsSignalValid(500) == HIDO_FALSE)
+ {
+ HIDO_Debug2("[BT] Control: Steer %d, Speed %d\r\n", pCtrl->m_i8SteerSpeed, pCtrl->m_i8TravelSpeed);
+
+ Set_Steering_PWM(pCtrl->m_i8SteerSpeed);
+ Set_Motor_PWM(pCtrl->m_i8TravelSpeed);
+ }
+ else
+ {
+ // HIDO_Debug2("[BT] Ignored (RC Active)\r\n");
+ }
+ }
+ break;
+ }
+ default:
+ HIDO_Debug2("[BT] Unknown Cmd: 0x%02X\r\n", pHeader->m_u8CmdType);
+ break;
+ }
+}
--
Gitblit v1.10.0