<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      一.程序功能講解:

      功能1:開關廣播

      AT+ADVEN=1   開啟廣播 正確設置返回OK/r/n

      AT+ADVEN=0   關閉廣播 正確設置返回OK/r/n

      AT+ADVEN=123  當參數長度不是1時返回ERROR:1(長度錯誤)

      AT+ADVEN=2   當參數不是0和1是返回ERROR:2(參數錯誤)

      功能2:設置廣播名稱

      AT+ADVDATA=WCH 正確設置廣播內容返回OK/r/n

      名字內容最長29字節,超過29字節返回ERROR:1(長度錯誤)

      功能3:設置配對密碼

      AT+PASS=123456 正確設置密碼返回OK/r/n

      密碼必須是6位,非6位時返回ERROR:1(長度錯誤)

      密碼必須是純數字,包含非數字內容返回ERROR:2(參數錯誤)

      未知指令返回ERROR:3

      緩沖區溢出返回ERROR:4

      二.程序詳細講解:

      1.串口初始化:

      cmd_uart_init

      2.串口中斷接收:

      UART_IRQHandler

      3.串口指令處理:

      Cmd_Process

      4.指令細節處理:

      CommandStatus HandleAdvertisingEnable和CommandStatus HandleAdvertisingData和HandlePasskey

      ble_cmd.c:

      #include "CONFIG.h"
      #include "HAL.h"
      #include "gattprofile.h"
      #include "peripheral.h"
      #include "stdlib.h"
      #include "ble_adv.h"
      
      // 硬件與緩沖區配置(確保觸發閾值與讀取長度一致)
      #define TRIGGER_BYTE_COUNT 6       // 與UART_7BYTE_TRIG匹配為觸發FIFO-1
      #define RX_BUFFER_SIZE     64      // 緩沖區大小
      #define MAX_ADVDATA_LENGTH 31      // 最大廣播數據長度
      
      /**
       * UART初始化:配置引腳、中斷模式
       */
      void cmd_uart_init(){
          GPIOA_SetBits(bTXD_0);
          GPIOA_ModeCfg(bTXD_0, GPIO_ModeOut_PP_5mA);  // TXD推挽輸出(先置高)
          UART_Remap(ENABLE, UART_TX_REMAP_PA3, UART_RX_REMAP_PA2);  // 引腳重映射
          UART_DefInit();  // 默認初始化
      
      #if 1  // 中斷模式:接收數據后處理
          UART_ByteTrigCfg(UART_7BYTE_TRIG);  // 7字節觸發中斷(與TRIGGER_BYTE_COUNT一致)
          UART_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_LINE_STAT);  // 使能接收就緒和線路狀態中斷
          PFIC_EnableIRQ(UART_IRQn);  // 使能UART中斷
      #endif
      }
      
      // 錯誤碼定義(明確錯誤類型)
      typedef enum {
          CMD_SUCCESS = 0,             // 成功
          CMD_ERROR_LENGTH,            // 長度錯誤
          CMD_ERROR_PARAM,             // 參數錯誤
          CMD_ERROR_UNKNOWN,           // 未知指令
          CMD_ERROR_BUFFER_OVERFLOW    // 緩沖區溢出
      } CommandStatus;
      
      // 指令結構:前綴、長度、處理函數
      typedef struct {
          const char* prefix;          // 指令前綴(如"AT+ADVEN=")
          uint8_t prefixLength;        // 前綴長度
          CommandStatus (*handler)(const uint8_t* data, uint8_t length);  // 處理函數
      } CommandDefinition;
      
      // 全局變量(volatile確保中斷與主循環可見性)
      uint8_t RxBuff[RX_BUFFER_SIZE];          // 接收緩沖區
      volatile uint8_t uart_end_flag = 0;      // 接收完成標志
      volatile uint8_t uart_len = 0;           // 當前接收長度
      volatile uint8_t buffer_overflow_flag=0; // 緩沖區溢出標志
      
      // 指令處理函數聲明
      static CommandStatus HandleAdvertisingEnable(const uint8_t* data, uint8_t length);
      static CommandStatus HandleAdvertisingData(const uint8_t* data, uint8_t length);
      static CommandStatus HandlePasskey(const uint8_t* data, uint8_t length);
      
      // 指令表(便于擴展新指令)
      static const CommandDefinition commands[] = {
          {"AT+ADVEN=", sizeof("AT+ADVEN=") - 1, HandleAdvertisingEnable},  // 使能/禁用廣播
          {"AT+ADVDATA=", sizeof("AT+ADVDATA=") - 1, HandleAdvertisingData}, // 設置廣播數據
          {"AT+PASS=", sizeof("AT+PASS=") - 1, HandlePasskey},              // 設置配對密碼
          {NULL, 0, NULL} // 結束標記
      };
      
      /**
       * 發送錯誤響應
       * @param status 錯誤碼
       */
      static void SendErrorResponse(CommandStatus status) {
          switch (status) {
              case CMD_ERROR_LENGTH:
                  UART_SendString("ERROR:1\r\n", 9);  // 長度錯誤
                  break;
              case CMD_ERROR_PARAM:
                  UART_SendString("ERROR:2\r\n", 9);  // 參數錯誤
                  break;
              case CMD_ERROR_UNKNOWN:
                  UART_SendString("ERROR:3\r\n", 9);  // 未知指令
                  break;
              case CMD_ERROR_BUFFER_OVERFLOW:
                  UART_SendString("ERROR:4\r\n", 9);  // 緩沖區溢出
                  break;
              default:
                  break;
          }
      }
      
      /**
       * 發送成功響應
       */
      static void SendSuccessResponse() {
          UART_SendString("OK\r\n", 4);
      }
      
      /**
       * 指令處理主函數(在主循環中調用)
       */
      __HIGH_CODE
      void Cmd_Process() {
          if (uart_end_flag) {
              uart_end_flag = 0;  // 清除標志
      
              CommandStatus status = CMD_ERROR_UNKNOWN;  // 默認未知指令
      
              // 遍歷指令表,查找匹配的指令
              for (int i = 0; commands[i].prefix != NULL; i++) {
                  // 檢查長度是否足夠,且前綴匹配(tmos_memcmp返回1表示相等)
                  if (uart_len >= commands[i].prefixLength &&
                      tmos_memcmp(commands[i].prefix, RxBuff, commands[i].prefixLength)) {
      
                      const uint8_t* cmdData = &RxBuff[commands[i].prefixLength];  // 指令參數
                      uint8_t cmdLength = uart_len - commands[i].prefixLength;     // 參數長度
                      status = commands[i].handler(cmdData, cmdLength);            // 調用處理函數
                      break;
                  }
              }
      
              // 發送響應
              if (status == CMD_SUCCESS) {
                  SendSuccessResponse();
              } else {
                  SendErrorResponse(status);
              }
      
              // 清理緩沖區
              uart_len = 0;
              tmos_memset(RxBuff, 0, RX_BUFFER_SIZE);
          }
      }
      
      /**
       * 處理AT+ADVEN指令(使能/禁用廣播)
       * 格式:AT+ADVEN=0(禁用)或1(使能)
       */
      static CommandStatus HandleAdvertisingEnable(const uint8_t* data, uint8_t length) {
          // 檢查參數長度(必須為1字節)
          if (length != 1) {
              return CMD_ERROR_LENGTH;
          }
      
          // 檢查參數合法性(必須是'0'或'1')
          if (data[0] != '0' && data[0] != '1') {
              return CMD_ERROR_PARAM;
          }
      
          // 設置廣播使能狀態
          uint8_t enable = (data[0] == '1');
          GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &enable);
          return CMD_SUCCESS;
      }
      
      /**
       * 處理AT+ADVDATA指令(設置廣播數據)
       * 格式:AT+ADVDATA=xxx(xxx為廣播內容,長度≤29)
       */
      static CommandStatus HandleAdvertisingData(const uint8_t* data, uint8_t length) {
          // 檢查長度(廣播數據總長度=參數長度+2≤31,故參數長度≤29)
          if (length > MAX_ADVDATA_LENGTH - 2) {
              return CMD_ERROR_LENGTH;
          }
      
          uint8_t advData[MAX_ADVDATA_LENGTH];
          uint8_t ble_sta = 0xff;  // BLE當前狀態
      
          // 構建廣播數據(符合BLE規范:長度+類型+內容)
          advData[0] = length + 1;  // 長度字段(類型+內容總長度)
          advData[1] = 0x09;        // 類型字段(0x09表示完整本地名稱)
          tmos_memcpy(&advData[2], data, length);  // 復制內容
      
          // 根據當前BLE狀態更新廣播數據
          GAPRole_GetParameter(GAPROLE_STATE, &ble_sta);
          if (ble_sta == 2) {  // 廣播狀態:實時更新
              GAP_UpdateAdvertisingData(Peripheral_TaskID, TRUE, length+2, advData);
          } else {  // 非廣播狀態:預設置
              GAPRole_SetParameter(GAPROLE_ADVERT_DATA, length+2, advData);
          }
      
          return CMD_SUCCESS;
      }
      
      /**
       * 處理AT+PASS指令(設置配對密碼)
       * 格式:AT+PASS=xxxxxx(6位數字)
       */
      static CommandStatus HandlePasskey(const uint8_t* data, uint8_t length) {
          // 檢查長度(必須為6字節)
          if (length != 6) {
              return CMD_ERROR_LENGTH;
          }
      
          // 檢查是否為數字
          for (uint8_t i = 0; i < length; i++) {
              if (data[i] < '0' || data[i] > '9') {
                  return CMD_ERROR_PARAM;
              }
          }
      
          // 轉換為數字(忽略前導零)
          uint32_t passkey = 0;
          uint8_t startIdx = 0;
          // 找到第一個非零數字的位置
          while (startIdx < 6 && data[startIdx] == '0') {
              startIdx++;
          }
          // 計算密碼(若全為零,結果為0)
          for (uint8_t i = startIdx; i < 6; i++) {
              passkey = passkey * 10 + (data[i] - '0');
          }
      
          // 設置配對密碼
          GAPBondMgr_SetParameter(GAPBOND_PERI_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
          return CMD_SUCCESS;
      }
      
      /**
       * 處理緩沖區溢出(統一邏輯,避免重復代碼)
       */
      __HIGH_CODE
      static void handleBufferOverflow(void) {
          uart_len = 0;
          tmos_memset(RxBuff, 0, RX_BUFFER_SIZE);
          buffer_overflow_flag = 1;
          SendErrorResponse(CMD_ERROR_BUFFER_OVERFLOW);
      }
      
      /**
       * UART中斷處理函數(高優先級)
       * 功能:處理UART接收中斷,將數據存入緩沖區并標記完成
       * 注意:采用中斷驅動,快速處理后返回,避免阻塞
       */
      __INTERRUPT
      __HIGH_CODE
      void UART_IRQHandler(void)
      {
          switch (UART_GetITFlag()) {
              case UART_II_LINE_STAT: // 線路狀態錯誤(幀錯誤、奇偶校驗等)
                  uint8_t LineSta=UART_GetLinSTA();    // 讀取狀態寄存器以清除中斷
                  break;
      
              case UART_II_RECV_RDY:  // 接收緩沖區達到觸發閾值(UART_7BYTE_TRIG)只收6個字節確保代碼進超時中斷
                  // 安全檢查:確保緩沖區有足夠空間接收觸發字節數
                  if (uart_len <= (RX_BUFFER_SIZE - TRIGGER_BYTE_COUNT)) {
                      // 批量讀取觸發字節數減1的數據
                      for (uint8_t i = 0; i < TRIGGER_BYTE_COUNT; i++) {
                          RxBuff[uart_len + i] = UART_RecvByte();
                      }
                      uart_len += TRIGGER_BYTE_COUNT;  // 更新緩沖區指針
                  } else {
                      handleBufferOverflow();  // 緩沖區即將溢出,執行清理
                  }
                  break;
      
              case UART_II_RECV_TOUT:  // 接收超時(數據傳輸暫停,一幀結束)
                  // 安全檢查:計算剩余空間是否足夠接收當前FIFO中的數據
                  if ((uart_len + R8_UART_RFC) <= RX_BUFFER_SIZE) {
                      // 讀取剩余數據(注意:此處假設UART_RecvString為讀取剩余全部數據)
                      uint8_t bytesRead = UART_RecvString(&RxBuff[uart_len]);
      
                      // 處理歷史溢出標志:若之前發生過溢出,丟棄當前數據
                      if (buffer_overflow_flag) {
                          buffer_overflow_flag = 0;        // 清除溢出標志
                          uart_len = 0;                    // 重置緩沖區
                          tmos_memset(RxBuff, 0, RX_BUFFER_SIZE);  // 清空緩沖區
                      } else {
                          // 正常接收:更新長度并標記接收完成
                          uart_len += bytesRead;
                          uart_end_flag = 1;  // 通知主循環有完整命令待處理
                      }
                  } else {
                      // 剩余空間不足,觸發溢出處理
                      handleBufferOverflow();
                  }
                  break;
      
              case UART_II_THR_EMPTY:  // 發送緩沖區空(當前未使用此功能)
                  break;
      
              default:
                  break;
          }
      }

      頭文件:

      #ifndef INCLUDE_BLE_ADV_H_
      #define INCLUDE_BLE_ADV_H_
      
      extern  uint8_t Peripheral_TaskID;
      
      extern void cmd_uart_init();
      
      extern void Cmd_Process();
      
      #endif /* INCLUDE_BLE_ADV_H_ */

      main.c

      #include "CONFIG.h"
      #include "HAL.h"
      #include "gattprofile.h"
      #include "peripheral.h"
      #include "ble_adv.h"
      
      __attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
      
      #if(defined(BLE_MAC)) && (BLE_MAC == TRUE)
      const uint8_t MacAddr[6] = {0x84, 0xC2, 0xE4, 0x03, 0x55 ,0xAA};
      #endif
      
       * @fn      Main_Circulation
       *
       * @brief   主循環
       *
       * @return  none
       */
      __HIGH_CODE
      __attribute__((noinline))
      void Main_Circulation()
      {
          while(1)
          {
              TMOS_SystemProcess();
              Cmd_Process();
          }
      }
      
      /*********************************************************************
       * @fn      main
       *
       * @brief   主函數
       *
       * @return  none
       */
      int main(void)
      {
          HSECFG_Capacitance(HSECap_18p);
          SetSysClock(CLK_SOURCE_HSE_PLL_100MHz);
      #if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE)
          GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
      #endif
      #ifdef DEBUG
          GPIOA_SetBits(bTXD_0);
          GPIOA_ModeCfg(bTXD_0, GPIO_ModeOut_PP_5mA); // TXD-配置推挽輸出,注意先讓IO口輸出高電平
          UART_Remap(ENABLE, UART_TX_REMAP_PA3, UART_RX_REMAP_PA2);
          UART_DefInit();
      #endif
          cmd_uart_init();
          PRINT("%s\n", VER_LIB);
          CH57x_BLEInit();
          HAL_Init();
          GAPRole_PeripheralInit();
          Peripheral_Init();
          Main_Circulation();
      }

       

      posted on 2025-10-09 13:59  WCH藍牙應用分享  閱讀(67)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 国产一区二区黄色在线观看| 内黄县| 国产成人亚洲欧美二区综合| 精品人妻av中文字幕乱| 国产suv精品一区二区五| 日韩有码中文字幕国产| 合水县| 国产亚洲精品成人aa片新蒲金| 国产激情艳情在线看视频| 免费观看日本污污ww网站69| 推特国产午夜福利在线观看| 亚洲深深色噜噜狠狠网站| 边添小泬边狠狠躁视频| 91精品国产午夜福利| 亚洲精品天堂在线观看| 亚洲国产青草衣衣一二三区| 国内自拍av在线免费| 高清中文字幕一区二区| 无码精品国产va在线观看dvd| 非会员区试看120秒6次| 永久无码天堂网小说区| 欧洲精品色在线观看| 久久亚洲综合精品成人网| 日本一区二区三区四区黄色| 国产日韩久久免费影院| 狠狠躁夜夜躁人人爽天天| 亚洲av无码成人影院一区| 日韩精品国产另类专区| 亚洲卡1卡2卡新区网站| 在线a亚洲老鸭窝天堂| 99热久久这里只有精品| 国产办公室秘书无码精品99 | 国产中文字幕久久黄色片| 国产偷窥熟女高潮精品视频| 无码中文字幕av免费放| 亚洲日韩久热中文字幕| 亚洲国产综合精品2020| 久久热这里这里只有精品| 凤阳县| 国产乱色国产精品免费视频| 亚洲A综合一区二区三区|