普冉PY32系列(四) PY32F002A/003/030的時鐘設置

来源:https://www.cnblogs.com/milton/archive/2023/02/11/17111286.html
-Advertisement-
Play Games

PY32F002A, PY32F003, PY32F030 三個系列硬體相同, 下麵以 PY32F030的時鐘樹結構為例說明 內部時鐘有32KHz和24MHz(從代碼上看其實是8MHz),外部時鐘是直接接入, PLL只有2倍. 使用外置晶振時如果要達到標稱的48MHz, 晶振頻率就必須用24MHz,... ...


目錄

PY32F030 的系統時鐘

PY32F002A, PY32F003, PY32F030 三個系列硬體相同, 代碼通用. 下麵以 PY32F030的時鐘樹結構為例說明

從圖中可以看到內部時鐘有32KHz和24MHz(從代碼上看其實是8MHz),外部時鐘是直接接入, PLL只有2倍(按PY32F072的PLL寄存器試過, 寫入無效, 因此沒法做再高的倍頻了).

使用外置晶振時如果要達到標稱的48MHz, 晶振頻率就必須用24MHz, 而不是常見的8MHz了. 在示例代碼中有備註在PLL啟用時, 外置晶振的頻率需要大於12MHz, 因此外部晶振的頻率可以選擇的是12MHz - 24MHz, 更低的頻率應該也行就是不能上PLL.

系統時鐘和DMA時鐘都是通過 AHB 分頻, 其它的外設通過 APB 再次分頻.

時鐘設置代碼

以下區分HAL和LL外設庫, 對內置高速振蕩源和外置高速晶振分別說明

使用內置高速振蕩源

內部高速時鐘頻率為24MHz, 可選的頻率有4MHz, 8MHz, 16MHz, 22.12MHz 和 24MHz, 這些是通過寄存器還原出廠校準的RC值設置達到的. 可以通過調整這些值調節頻率.

使用HAL外設庫, 24MHz

首先是在 py32f0xx_hal_conf.h 中設置 HSI_VALUE, 預設是8MHz, 這個不需要改

#if !defined  (HSI_VALUE) 
  #define HSI_VALUE              ((uint32_t)8000000)     /*!< Value of the Internal oscillator in Hz */
#endif /* HSI_VALUE */

然後在代碼中

static void APP_SystemClockConfig(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  // 設置振蕩源類型
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE
                                    | RCC_OSCILLATORTYPE_HSI
                                    | RCC_OSCILLATORTYPE_LSE
                                    | RCC_OSCILLATORTYPE_LSI;
  // 開啟內部高速時鐘
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  // 設置內部高速時鐘頻率為24MHz
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_24MHz;
  // 內部高速時鐘不分頻, 分頻繫數可以設置為 1, 2, 4, 8, 16, 32, 64, 128
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
  // 關閉其它時鐘: 外置高速, 內置低速, 外置低速
  RCC_OscInitStruct.HSEState = RCC_HSE_OFF;
  RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
  RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
  // 關閉PLL
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF;
  // 應用設置
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    APP_ErrorHandler();
  }
  // 修改時鐘後, 重新初始化 AHB,APB 時鐘
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK
                                | RCC_CLOCKTYPE_SYSCLK
                                | RCC_CLOCKTYPE_PCLK1;
  // 設置 SYSCLK 時鐘源為內部高速時鐘
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  // AHB 不分頻
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  // APB 不分頻
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  // 啟用設置, flash等待時間為0
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    APP_ErrorHandler();
  }
}

對於flash的等待時間, 普冉的示例代碼中的建議是 小於等於24MHz的使用0, 大於24MHz的使用不到

   * -- clock <= 24MHz: FLASH_LATENCY_0
   * -- clock > 24MHz:  FLASH_LATENCY_1

使用LL外設庫, 24MHz

static void APP_SystemClockConfig(void)
{
  // 啟用內部高速振蕩源
  LL_RCC_HSI_Enable();
  // 校準為 24MHz
  LL_RCC_HSI_SetCalibFreq(LL_RCC_HSICALIBRATION_24MHz);
  // 等待穩定標誌位
  while(LL_RCC_HSI_IsReady() != 1);
  // 設置 AHB 不分頻
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
  // 設置系統時鐘源為內部高速時鐘
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSISYS);
  // 等待設置完成
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSISYS);
  // 設置flash等待時間
  LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
  // 設置APB 不分頻
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
  /* 更新全局變數 SystemCoreClock(或者通過函數 SystemCoreClockUpdate) */
  LL_SetSystemCoreClock(24000000);
  /* 更新 SysTick 的時鐘源設置, 頻率為24MHz */
  LL_InitTick(24000000, 1000U);
}

使用內置晶振帶PLL

PLL帶2倍頻, 可以將24MHz的內置/外置頻率翻倍成48MHz. 手冊上 PY32F030的最高工作頻率. 實際上 PY32F002A 和 PY32F003 工作在這個頻率上也毫無問題.

使用HAL外設庫, 48MHz

首先在 py32f0xx_hal_conf.h 中設置 HSI_VALUE, 預設是8MHz 不需要改

#if !defined  (HSI_VALUE) 
  #define HSI_VALUE              ((uint32_t)8000000)     /*!< Value of the Internal oscillator in Hz */
#endif /* HSI_VALUE */

然後在代碼中

static void APP_SystemClockConfig(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE
                                    | RCC_OSCILLATORTYPE_HSI
                                    | RCC_OSCILLATORTYPE_LSE
                                    | RCC_OSCILLATORTYPE_LSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;                            /* HSI ON */
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;                            /* No division */
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_16MHz;   /* HSI =16MHz */
  RCC_OscInitStruct.HSEState = RCC_HSE_OFF;                           /* OFF */
  RCC_OscInitStruct.HSEFreq = RCC_HSE_16_32MHz;
  RCC_OscInitStruct.LSIState = RCC_LSI_OFF;                           /* OFF */
  RCC_OscInitStruct.LSEState = RCC_LSE_OFF;                           /* OFF */
  // 以上部分和使用HSI作為時鐘源是一樣的, 以下是PLL相關的設置, 首先是開啟PLL
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  // 將PLL時鐘源設置為內部高速, HSI頻率需要高於12MHz
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  // 應用設置
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    APP_ErrorHandler();
  }
  // 設置系統時鐘
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1;
  // 設置PLL為系統時鐘源
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  // AHB 不分頻
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  // APB 不分頻
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  // 應用設置
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    APP_ErrorHandler();
  }
}

使用LL外設庫, 48MHz

LL外設庫的PLL設置比較簡潔

static void APP_SystemClockConfig(void)
{
  LL_UTILS_ClkInitTypeDef UTILS_ClkInitStruct;
  // 啟用內部高速
  LL_RCC_HSI_Enable();
  // 設置為24MHz, 這裡可以微調頻率, 值越大頻率越快
  LL_RCC_HSI_SetCalibFreq(LL_RCC_HSICALIBRATION_24MHz + 15);
  // 等待穩定
  while (LL_RCC_HSI_IsReady() != 1);
  // AHB 不分頻
  UTILS_ClkInitStruct.AHBCLKDivider = LL_RCC_SYSCLK_DIV_1;
  // APB 不分頻
  UTILS_ClkInitStruct.APB1CLKDivider = LL_RCC_APB1_DIV_1;
  // 設置系統時鐘源為PLL+HSI, 註意這個方法名 
  LL_PLL_ConfigSystemClock_HSI(&UTILS_ClkInitStruct);
  // 更新 SysTick的設置
  LL_InitTick(48000000, 1000U);
}

使用外部晶振

不開PLL時, 外部晶振支持的最大頻率為32MHz. 用32MHz的晶振測試過沒問題. 以下代碼基於24MHz的外部晶振, 如果使用其它頻率的晶振要對應調整.

使用HAL外設庫, 24MHz

首先是在 py32f0xx_hal_conf.h 中設置 HSE_VALUE, 使用的是24MHz的晶振, 這裡設置為 24000000

#if !defined  (HSE_VALUE) 
  #define HSE_VALUE              ((uint32_t)24000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */

然後在代碼中

static void APP_SystemClockConfig(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  // 啟用外部高速晶振
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  // 頻率範圍為 16-32MHz
  RCC_OscInitStruct.HSEFreq = RCC_HSE_16_32MHz;
  // 應用設置
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    APP_ErrorHandler();
  }

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1;
  // 設置時鐘源為外部高速晶振
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
  // AHB 和 APB 都不分頻
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  /* 
   * Re-initialize RCC clock
   * -- clock <= 24MHz: FLASH_LATENCY_0
   * -- clock > 24MHz:  FLASH_LATENCY_1
   */
  // 應用設置
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    APP_ErrorHandler();
  }
}

使用LL外設庫, 24MHz

static void APP_SystemClockConfig(void)
{
  // 啟用外部高速晶振
  LL_RCC_HSE_Enable();
  // 設置頻率範圍為 16 - 32MHz
  LL_RCC_HSE_SetFreqRegion(LL_RCC_HSE_16_32MHz);
  // 等待穩定
  while(LL_RCC_HSE_IsReady() != 1);
  // 設置 AHB 為不分頻
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
  // 設置系統時鐘源為外部高速晶振
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE);
  // 等待穩定
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE);
  // 設置 APB 不分頻
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
  // 更新系統時鐘值
  /* Update global SystemCoreClock(or through SystemCoreClockUpdate function) */
  LL_SetSystemCoreClock(HSE_VALUE);
  // 更新 SysTick
  /* Re-init frequency of SysTick source */
  LL_InitTick(HSE_VALUE, 1000U);
}

使用外部晶振帶PLL

開啟PLL後, 外部晶振支持的最大頻率為24MHz, 倍頻後為48MHz.

使用HAL外設庫, 48MHz

首先是在 py32f0xx_hal_conf.h 中設置 HSE_VALUE, 使用的是24MHz的晶振, 這裡設置為 24000000

#if !defined  (HSE_VALUE) 
  #define HSE_VALUE              ((uint32_t)24000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */

然後在代碼中

static void APP_SystemClockConfig(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;                            /* Turn on HSE */
  RCC_OscInitStruct.HSEFreq = RCC_HSE_16_32MHz;                       /* HSE frequency range */
  // 開啟 PLL
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  // 設置 PLL 時鐘源為外部高速晶振
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  // 應用設置
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    APP_ErrorHandler();
  }

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1;
  // 設置系統時鐘源為PLL
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  // AHB和APB都不分頻
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;                  /* APH no division */
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;                   /* APB no division */
  /* 
   * Re-initialize RCC clock
   * -- clock <= 24MHz: FLASH_LATENCY_0
   * -- clock > 24MHz:  FLASH_LATENCY_1
   */
  // 應用設置
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    APP_ErrorHandler();
  }
}

使用LL外設庫, 48MHz

static void APP_SystemClockConfig(void)
{
  LL_UTILS_ClkInitTypeDef UTILS_ClkInitStruct;
  // 啟用外部高速晶振
  LL_RCC_HSE_Enable();
  // 設置頻率範圍
  LL_RCC_HSE_SetFreqRegion(LL_RCC_HSE_16_32MHz);
  // 等待穩定
  while(LL_RCC_HSE_IsReady() != 1);

  // 設置 AHB 不分頻, APB 不分頻
  UTILS_ClkInitStruct.AHBCLKDivider = LL_RCC_SYSCLK_DIV_1;
  UTILS_ClkInitStruct.APB1CLKDivider = LL_RCC_APB1_DIV_1;
  // 設置系統時鐘源為外部高速晶振, 關閉 BYPASS (BYPASS開啟後外部時鐘源將會通過 PF0 輸入到晶元內部,PF1 作為 GPIO 使用)
  LL_PLL_ConfigSystemClock_HSE(24000000U, LL_UTILS_HSEBYPASS_OFF, &UTILS_ClkInitStruct);

  /* Re-init frequency of SysTick source, reload = freq/ticks = 48000000/1000 = 48000 */
  // 更新 SysTick
  LL_InitTick(48000000, 1000U);
}

示例代碼

上面的代碼已經放到倉庫

最後

PY32F002A/003/030的內置高速時鐘精度一般, 出廠預設校準值對應的時鐘基本上每秒都會偏慢10到15個毫秒, 如果把手按上去讓晶元升溫, 能看到間隔明顯變小. 也許這些晶元出廠校準的環境溫度較高, 而我測試的正好在冬天溫度偏低. 如果需要較高精度的, 建議使用外置晶振.


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 教程簡介 C#概述 - 從簡單和簡單的步驟學習C#從基本到高級概念,包括概述,環境設置,程式結構,基本語法,數據類型,類型轉換,變數,常量,運算符,決策,迴圈,方法,Nullables ,數組,字元串,結構,枚舉,文件I / O,類,封裝,介面,繼承,命名空間,多態性,運算符重載,封裝,反射,屬性, ...
  • 首先我們需要瞭解到分散式事件匯流排是什麼; 分散式事件匯流排是一種在分散式系統中提供事件通知、訂閱和發佈機制的技術。它允許多個組件或微服務之間的協作和通信,而無需直接耦合或瞭解彼此的實現細節。通過事件匯流排,組件或微服務可以通過發佈或訂閱事件來實現非同步通信。 例如,當一個組件完成了某項任務並生成了一個事件 ...
  • 前言 Web項目中很多網頁資源比如html、js、css通常會做伺服器端的緩存,加快網頁的載入速度 一些周期性變化的API數據也可以做緩存,例如廣告資源位數據,菜單數據,商品類目數據,商品詳情數據,商品列表數據,公共配置數據等,這樣就可以省去很多在服務端手動實現緩存的操作 最早資源緩存大部分都用Ex ...
  • 這是一個關於 ASP.NET 6 依賴註入的系列文章。 在這個系列中,我們將瞭解到什麼是依賴註入、控制反轉,它能夠做什麼,以及我們為什麼要使用它。 之後,我們會進一步瞭解 ASP.NET 6 依賴註入的生命周期、服務容器等重要概念。 最後,我們再深入瞭解服務作用域和更多的服務註冊與註入方式。 概述 ...
  • 設計原則系列文章 必知必會的設計原則——單一職責原則 必知必會的設計原則——開放封閉原則 必知必會的設計原則——依賴倒置原則 必知必會的設計原則——里氏替換原則 概述 1、 客戶端不應該依賴它不需要的介面。2、 一個類對另一個類的依賴應該建立在最小介面上。3、介面應儘量細分,不要在一個介面中放很多方 ...
  • 「CSDN」作為中國最具人氣的專業 IT 社區,一直是廣大 IT 技術博主的主選陣地。這些年 CSDN 在知識付費領域的探索也遠遠超過其它平臺,大家(尤其是創作型博主)對 CSDN 的認可度也越來越高,CSDN 上目前有很多非常優秀的技術專欄。 CSDN博客專家 是 CSDN 給予影響力較大的技術類 ...
  • 前言 AppImage 逐漸成為 Linux 常用的一種軟體包格式,本文將介紹如何將 AppImage 文件添加到 Ubuntu 的應用程式中。 如下圖中的 CAJViewer : 操作過程 設置相關許可權 對要操作的 AppImage 右擊 > 屬性進行如下圖的設置,必須勾選 允許執行文件 創建 d ...
  • JLink RTT(Real Time Transfer) 是用於嵌入式系統監控和交互的工具, 類似於SWO, 可以雙向通信, 特點是性能很高, 基本上不影響嵌入式應用的實時行為, 可以對比一下使用printf輸出日誌時的各種限制. 而且因為和 JLink 介面集成, 不需要再浪費一個串口輸出 pr... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...