步進電機中斷函數解釋

STM32 motor111.cHAL_TIM_PeriodElapsedCallback 函數逐行解釋

下面我們對 STM32 項目中 motor111.c 文件里的 HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 函數進行逐行解析,幫助初學者理解每一行代碼的作用。此函數是在定時器產生更新中斷時被調用的回調函數,用于控制兩個步進電機的運動。解析過程中,我們還將解釋 TIM5 定時器的作用、如何判斷哪個電機在運行、GPIO 如何驅動電機步進,以及 HAL_TIM_PWM_StopHAL_TIM_Base_Stop_IT 的作用,最后說明整個流程在系統控制邏輯中的作用。

1. 每一行代碼的含義

以下是 HAL_TIM_PeriodElapsedCallback 函數的代碼,并在每行添加中文注釋說明其含義:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {if (htim->Instance == TIM5) {                    // 如果觸發中斷的定時器實例是 TIM5,則處理電機邏輯uint8_t needStop = 1;                        // 標志是否需要停止定時器,初始值為1(假設需要停止)// 處理電機0 (如X軸電機)if (motor0_Running && stepCount[0] < targetSteps[0]) {HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_2);   // 翻轉PA2引腳電平(給電機0的步進引腳產生一個脈沖)stepCount[0]++;                          // 電機0的已執行步數加一needStop = 0;                            // 還有剩余步數,暫時不停止定時器} else if (motor0_Running) {HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL_3); // 停止TIM5通道3的PWM輸出(停止電機0的脈沖信號)HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_SET); // 將PE5引腳置高(關閉電機0的使能或剎車信號)motor0_Running = 0;                      // 標記電機0已停止運行}// 處理電機1 (如Y軸電機)if (motor1_Running && stepCount[1] < targetSteps[1]) {HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_3);   // 翻轉PA3引腳電平(給電機1的步進引腳產生一個脈沖)stepCount[1]++;                          // 電機1的已執行步數加一needStop = 0;                            // 還有剩余步數,暫時不停止定時器} else if (motor1_Running) {HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL _4); // 停止TIM5通道4的PWM輸出(停止電機1的脈沖信號)HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET); // 將PE3引腳置高(關閉電機1的使能或剎車信號)motor1_Running = 0;                      // 標記電機1已停止運行}// 如果兩個電機都已停止運行,則停止定時器中斷if (needStop) {HAL_TIM_Base_Stop_IT(&htim5);            // 停止TIM5基礎定時器及其中斷觸發}}
}

逐行說明:

  • 第1行: void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    定義了一個回調函數,當定時器更新事件發生時(定時器溢出或達到設定周期),HAL庫會調用此函數。參數 htim 指向觸發這個中斷的定時器句柄。

  • 第2行: if (htim->Instance == TIM5) {
    檢查觸發該回調的定時器是否為 TIM5。如果是 TIM5 更新中斷,才執行后續電機控制代碼。這樣可以防止其他定時器的中斷誤觸發此段邏輯(因為 HAL 的這個回調對所有定時器通用,需要自行判斷來源)。

  • 第3行: uint8_t needStop = 1;
    定義并初始化一個 8 位無符號變量 needStop 為 1。needStop 用作標志位,指示是否需要停止定時器。初始假定需要停止(置1),如果發現任一電機仍需繼續運行,則會將其置0,表示不停止。

  • 第5行(注釋): // 處理電機0 (如X軸電機)
    這是一個注釋,說明接下來要處理電機0的邏輯(假設電機0對應 X 軸)。

  • 第6行: if (motor0_Running && stepCount[0] < targetSteps[0]) {
    判斷條件:如果電機0的“運行標志”motor0_Running為真(表示電機0目前設定為在運行狀態),電機0已走的步數 stepCount[0] 小于目標步數 targetSteps[0](還沒走完設定的總步數),則進入該分支,執行電機0的步進操作。

  • 第7行: HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_2);
    使用 HAL 庫提供的函數翻轉(Toggle)GPIOA端口的2號引腳的電平狀態。由于 PA2 引腳連接到電機0的步進脈沖控制信號,每次翻轉該引腳電平就產生一個上升沿或下降沿的脈沖。這相當于給步進電機的驅動器發送一個脈沖信號,讓電機轉動 一步(步進電機每接收一個脈沖信號就轉動一個固定角度或前進一步 (STM32之步進電機 - Sakura_Ji - 博客園))。

  • 第8行: stepCount[0]++;
    將電機0的步進計數值加一。stepCount[0] 用于記錄電機0已經執行了多少步,每產生一次脈沖就累加1。這樣可以跟蹤電機是否已經走到目標步數。

  • 第9行: needStop = 0;
    needStop 置為0,表示目前不應停止定時器。之所以設置為0,是因為在這個定時器中斷周期內,發現電機0還有剩余步數要走(剛執行了一步且未達到目標),因此需要繼續讓定時器觸發后續中斷來完成剩下的步數。

  • 第10行: } else if (motor0_Running) {
    如果上一條 if 不滿足,但是 motor0_Running 為真(表示電機0標記為正在運行)——也就是說電機0 正在運行但已沒有剩余步數需要執行 (stepCount[0] 已達到或超過 targetSteps[0]),則進入此分支。這種情況表示電機0的運動已經完成目標步數。

  • 第11行: HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL_3);
    調用了 HAL 庫函數停止 TIM5 定時器的通道3上的 PWM輸出。根據代碼邏輯,TIM5通道3被用于電機0的脈沖產生。因此這行代碼停止電機0的PWM信號輸出,不再發出步進脈沖。換句話說,停止對電機0繼續發脈沖,讓它停下。

    提示:Start_Motors 函數中,曾經通過 HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_3) 啟動了 TIM5 通道3 的 PWM,用于電機0脈沖輸出。這里對應地將其關閉。

  • 第12行: HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_SET);
    將 GPIOE 端口的 5 號引腳拉高(設置為高電平)。從上文 Start_Motors 函數可知,在啟動電機時曾經把 PE5 拉低(RESET)以使能電機0驅動。因此推測 PE5 引腳可能是電機0驅動器的“使能”(Enable)控制或制動信號(比如一些驅動模塊需要拉低使能引腳才能運行)。在完成運動后,將該引腳置高,意味著關閉電機0的驅動輸出(禁用電機或上電剎車),確保電機停止轉動或鎖定。

  • 第13行: motor0_Running = 0;
    將電機0的運行標志置0,表示電機0不再運行。這樣做不僅在內部記錄電機狀態,也會被主循環察覺,用于后續邏輯(例如主程序可能正等待該標志變為0,以判斷運動完成)。

  • 第14行: }
    結束電機0的處理分支。

  • 第16行(注釋): // 處理電機1 (如Y軸電機)
    注釋:說明下面的代碼塊是處理電機1的邏輯(假設電機1對應 Y 軸)。

  • 第17行: if (motor1_Running && stepCount[1] < targetSteps[1]) {
    判斷電機1是否需要執行一步:條件與電機0類似,如果電機1標記為正在運行且尚未完成目標步數 (stepCount[1] < targetSteps[1]),則進入該分支。

  • 第18行: HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_3);
    翻轉 GPIOA 端口3號引腳的電平。PA3 引腳連接電機1的步進控制信號,因此每次翻轉 PA3 電平,會給電機1發送一個脈沖信號,讓電機1前進一步。

  • 第19行: stepCount[1]++;
    電機1的步數計數加一,記錄已經執行了一個步進脈沖。

  • 第20行: needStop = 0;
    needStop 置0,表示由于電機1仍有未完成的步數,定時器不應停止,還需繼續中斷以完成后續步數。

  • 第21行: } else if (motor1_Running) {
    如果電機1正在運行但已沒有剩余步數需要走(即目標步數已達到),則進入此分支,執行電機1停止運行的收尾工作。

  • 第22行: HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL_4);
    停止 TIM5 定時器通道4的 PWM輸出。TIM5通道4對應電機1的脈沖輸出通道,所以這將停止電機1的步進脈沖信號,終止電機1的運動。

  • 第23行: HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
    將 GPIOE 端口3號引腳置高電平。類似電機0的情況,PE3 在啟動時被拉低使能電機1驅動,在運動結束時拉高以關閉電機1驅動輸出。

  • 第24行: motor1_Running = 0;
    清零電機1的運行標志,表示電機1已停止運行。

  • 第25行: }
    結束電機1處理的分支。

  • 第27行: if (needStop) {
    檢查 needStop 標志。如果仍然為1,表示在此次中斷處理中并沒有執行任何一步(即兩個電機都沒有進入運行步進的分支)。換言之,要么兩個電機都不需要再運行(都已完成目標步數或根本未啟動),要么定時器在一個周期內沒有檢測到需要繼續的步數。

  • 第28行: HAL_TIM_Base_Stop_IT(&htim5);
    調用 HAL 函數停止 TIM5 基礎定時器的運行,并關閉其更新中斷 (_IT 表示中斷模式下停止)。當 needStop == 1 時意味著兩個電機都已經停止,因此可以安全地停止定時器,不再產生中斷。一旦停止TIM5,中斷回調將不再被調用,電機控制循環結束。這樣做也避免了 CPU 繼續進入中斷浪費資源。

  • 第29行: }
    結束 if (needStop) 分支。

  • 第30行: }
    結束 if (htim->Instance == TIM5) 主分支。至此,TIM5定時器中斷的處理邏輯結束。如果有其他定時器使用了這個回調函數,它們將被忽略(因為不在 TIM5 分支內)。

  • 第31行: }
    回調函數結束。

通過上述逐行解釋,可以看出該回調函數的主要作用是在 TIM5 定時器中斷時,為兩個步進電機(電機0和電機1)生成步進脈沖并計數步數,當達到目標步數時停止相應電機的脈沖輸出,并在兩個電機都停止后停止定時器中斷。

接下來,我們針對題目要求的具體問題進行說明和拓展。

2. TIM5 定時器的作用及為何用它觸發中斷

TIM5 定時器的作用: 在這個項目中,TIM5 被用作步進電機控制的基礎定時器。它的主要作用是按照設定的時間間隔周期性地產生中斷(更新事件),從而觸發上面的回調函數。在每次中斷中,系統對電機的步數進行更新和脈沖輸出。這實現了對步進電機運動速度和步數的精確控制。通過調節 TIM5 的定時周期,可以控制步進電機脈沖的頻率,從而控制電機的轉速。

具體來說,TIM5 配合其 PWM 通道一起使用:在 Start_Motors 函數中,調用了 HAL_TIM_Base_Start_IT(&htim5) 開啟 TIM5 的基礎定時器中斷,并通過 HAL_TIM_PWM_Start 啟動 TIM5 的通道3和通道4 PWM輸出。這樣TIM5就開始按照預先配置的頻率計數,并在每次計數周期溢出時(即達到自動重裝值ARR)觸發更新中斷,由回調函數輸出一步脈沖。

為什么使用 TIM5 來觸發中斷:

  • 精確定時與穩定脈沖: 硬件定時器能夠提供精確且穩定的定時基準,比純軟件延時可靠得多。TIM5 定時器觸發中斷的周期決定了步進脈沖的頻率,從而決定電機轉動速度。使用 TIM5 硬件定時,可以確保每一步的時間間隔均勻,一致地控制電機運動。

  • 多通道支持雙電機: TIM5 在許多 STM32 微控制器上是一個擁有多通道的通用定時器。例如在 STM32F4 系列中,TIM5 有4個通道(并且是32位定時器)。在本代碼中利用了通道3和通道4分別輸出兩個電機的PWM脈沖,一個定時器同時管理兩個電機的步進信號,保證兩電機脈沖同步在同一個時基下。這對于需要協調運動的軸來說很方便(雖然本例中未實現插補算法,但共用一個定時源可簡化控制)。

  • 資源獨立且優先級控制: 使用單獨的TIM5定時器來控制電機,不會干擾主CPU執行其他任務。定時器中斷可以設置優先級,確保電機控制的實時性。當TIM5中斷觸發時,由回調函數執行關鍵的步數更新和GPIO切換,而主循環可以并行處理其他邏輯或等待完成信號。

  • 觸發中斷的原因: 總結來說,TIM5用于觸發中斷是為了在硬件定時的基礎上執行電機步進控制代碼。每次 TIM5 溢出產生中斷,就相當于“時鐘敲一下”,驅動電機前進一小步,并檢查是否達到目標。相比在主循環中用延時或輪詢產生脈沖,中斷方式更加精準和高效。

簡而言之,TIM5 定時器充當了電機的“節拍器”,每一次節拍(中斷)讓電機邁出一步,并最終在完成指定步數時停止節拍。

3. 如何判斷哪個電機在運行

在該系統中,通過狀態標志變量來判斷電機的運行狀態。具體而言,有兩個全局變量:motor0_Runningmotor1_Running,分別對應電機0和電機1的運行狀態。它們的用法如下:

  • 在啟動電機運動時,這兩個標志會被置為1。例如,在 Start_Motors 函數中,啟動雙電機運動之前,代碼執行:motor0_Running = 1; motor1_Running = 1; 這表示電機0和電機1的運行標志均被設為“正在運行”。

  • HAL_TIM_PeriodElapsedCallback 回調函數中,根據這些標志決定是否產生脈沖并執行步進。當 motorX_Running 為真且步數未完成時,代碼對相應電機執行 HAL_GPIO_TogglePin 產生脈沖并累加步數(如代碼第6-9行所示)。如果 motorX_Running 為假,則意味著該電機當前沒有運動需求,回調中也不會對其產生脈沖。

  • 當電機完成其目標步數時(即 stepCount[x] 達到 targetSteps[x]),回調函數會執行對應的 “停止” 分支:調用 HAL_TIM_PWM_Stop 停止PWM輸出,拉高控制引腳,并將 motorX_Running 標志置0。將標志清零表示該電機的運動已結束。

  • 主程序或其他任務可以通過檢查 motor0_Runningmotor1_Running 來判斷電機是否還在運行。例如,在 MovePathWithCenterReturn 等上層邏輯中,代碼使用 while (motor0_Running || motor1_Running); 來等待,直到兩個電機的運行標志都變為0,才說明此次運動已經全部完成.

總結: 哪個電機在運行取決于對應的 motorX_Running 標志是否為1。標志為1表示電機正處于運動過程中;標志為0表示該電機已停止(要么尚未啟動,要么已經完成運動)。此外,還可以結合步數計數判斷:當 stepCount[x] 尚未達到 targetSteps[x] 時且 motorX_Running 為1,則該電機正在執行運動;一旦步數達到目標并標志被清零,即表示該電機運動結束。

4. GPIO 控制如何驅動步進電機

本項目中,步進電機采用脈沖+方向的控制方式,也就是常見的步進電機驅動控制:由一個引腳提供脈沖信號控制步進,另一個引腳提供方向信號控制電機轉動方向。GPIO 的控制具體體現在以下方面:

  • 方向控制(Direction): 在開始運動時,通過GPIO設置電機轉動方向。代碼中 Start_Motors 函數對幾個引腳進行了初始化:

    HAL_GPIO_WritePin(GPIOE, GPIO_PIN_6, dirX ? GPIO_PIN_RESET : GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, dirY ? GPIO_PIN_SET : GPIO_PIN_RESET);
    

    這里推測 GPIOE_Pin_6 控制電機0的方向、GPIOE_Pin_4 控制電機1的方向。dirX/dirY 是傳入的方向參數,根據其值決定將方向引腳拉高還是拉低,從而設定電機朝正轉或反轉方向運動。在步進電機驅動器中,方向引腳電平高低通常對應順時針或逆時針旋轉。

  • 步進脈沖控制(Step Pulse): 正是通過定時器中斷里的 GPIO 翻轉來實現的。比如電機0使用 PA2 引腳作為步進脈沖引腳,每次在中斷中執行 HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_2) 就會使 PA2 從低電平變高,或從高電平變低。這個電平的跳變沿即構成了一個脈沖信號,被步進驅動器識別為一步指令。通常,步進驅動器會在檢測到引腳從低->高的上升沿時讓電機走一步(也有的驅動對下降沿敏感,但無論哪種,每次 Toggle 產生一個完整的脈沖周期)。因此每進入一次定時中斷翻轉引腳,電機就前進一“步距角”。正如步進電機的特性所述:每輸入一個脈沖信號,電機轉子就轉過一個固定角度(前進一步) (STM32之步進電機 - Sakura_Ji - 博客園)。

  • 使能控制(Enable/Disable): 從代碼看,GPIOE_Pin_5 和 GPIOE_Pin_3 似乎用作電機驅動器的使能或相關控制信號。在啟動電機時,這兩個引腳被拉低 (GPIO_PIN_RESET),而在停止電機時被拉高 (GPIO_PIN_SET) 來關閉驅動。許多步進電機驅動模塊(如常見的TB6600、A4988模塊)都有使能引腳使能(ENABLE)或睡眠引腳等,通常低電平激活驅動,高電平關閉輸出。由此推斷:

    • 當開始運動時,將使能引腳拉低,使能驅動器輸出,使電機準備接收脈沖。
    • 當運動結束或需要停機時,將使能引腳拉高,禁用驅動器輸出,防止電機繼續受到脈沖(也減少電機功耗或鎖定位置)。
  • GPIO 引腳配置: 為了可靠驅動步進電機,這些引腳一般配置為輸出模式,推挽輸出,高速,以確保能夠產生清晰的方波脈沖。另外,最好在硬件上這些引腳連接到驅動器時有共地,驅動器根據脈沖信號變化驅動電機線圈。

簡要流程: 初始化時設定方向,引腳使能驅動器;運動過程中定時翻轉步進引腳產生持續的脈沖序列;結束時停止脈沖并禁用驅動。GPIO 的這種控制方式實現了步進電機的典型開環控制:脈沖數決定轉動角度,脈沖頻率決定轉動速度 (STM32之步進電機 - Sakura_Ji - 博客園)。整個過程中GPIO輸出的高低電平序列就是電機動作的直接指令。

5. HAL_TIM_PWM_StopHAL_TIM_Base_Stop_IT 的作用

在代碼中,我們看到了這兩個停止函數:

  • HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel): 停止指定定時器通道的 PWM 輸出。調用此函數會關閉對應通道的比較輸出,使其不再產生PWM波形。在本項目中,TIM5的通道3和通道4被用于產生電機步進脈沖信號(對應PA2和PA3引腳)。當調用 HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL_3) 時,通道3的PWM輸出被關閉,不再自動翻轉PA2引腳電平;同理,TIM_CHANNEL_4 停止后不再輸出脈沖。作用: 終止特定電機的脈沖信號輸出。從電機驅動的角度看,這意味著不再給該電機發送步進指令脈沖,電機將停止繼續轉動。

    值得注意的是,PWM輸出停止后,如果需要的話,我們仍然可以通過軟件手動控制GPIO引腳電平(正如代碼中緊接著通過 HAL_GPIO_WritePin 拉高引腳來鎖定電機狀態)。HAL_TIM_PWM_Stop 單純停止硬件定時器對引腳的控制。

  • HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim): 停止基礎定時器的計數,并且停用其更新中斷。當調用 HAL_TIM_Base_Stop_IT(&htim5) 時,會停止 TIM5 定時器的運行,也就是停止計數。這樣TIM5就不會再觸發中斷了(對應的 HAL_TIM_PeriodElapsedCallback 不會再被調用)。作用: 在確定無需再產生任何步進脈沖時,關閉定時器以結束整個定時中斷過程。停止定時器中斷有助于節省CPU資源(不再無謂地進入中斷處理),也表明當前一次運動控制流程正式結束。

結合本例,HAL_TIM_PWM_Stop 用于單個電機的停止,而 HAL_TIM_Base_Stop_IT 用于整個定時器的停止。當兩個電機都已經達到目標步數時,needStop 仍為1,觸發執行 HAL_TIM_Base_Stop_IT(&htim5),從而完全停止TIM5。這相當于:“兩個電機都走完了,該停表了。” 如果只有一個電機走完,另一個還在跑,則僅停止走完的那一路PWM,定時器仍繼續跑以服務另一個電機。

小結: HAL_TIM_PWM_Stop 針對定時器的某一通道關閉PWM信號輸出;HAL_TIM_Base_Stop_IT 則關閉整個定時器和中斷。當使用定時器+PWM組合控制電機時,經常會在任務完成時先停PWM再停定時器,確保不多發脈沖也不多占用中斷。

6. 整體流程在系統控制邏輯中的作用

綜合來看,這套基于 TIM5 定時器中斷的電機控制流程在系統中扮演了步進運動控制核心邏輯的角色,確保電機按照指令完成指定的移動。下面從系統層面說明其工作流程及作用:

  • 啟動階段: 上層代碼(例如控制邏輯函數 MovePathWithCenterReturn)在需要電機移動時會調用 Start_Motors(stepsX, dirX, stepsY, dirY) 等函數,傳入X、Y軸各自需要移動的步數和方向。Start_Motors 將目標步數保存到 targetSteps[0/1],將已走步數 stepCount[0/1] 清零,并設置方向引腳和使能引腳的初始狀態,然后開啟 TIM5 定時器中斷和PWM輸出 。這一步相當于發出了“讓兩個電機按照給定方向各走 N 步”的命令,并啟動了驅動裝置。

  • 運行階段: TIM5 定時器開始計時,并按照設定頻率周期性中斷。每一次 TIM5 更新中斷都會調用電機控制回調 HAL_TIM_PeriodElapsedCallback。在回調中,根據每個電機的運行標志和剩余步數:

    • 如果電機需要繼續運行(標志為1且步數未完),就翻轉對應步進引腳,產生一個脈沖,電機走一步,同時步數計數加一。
    • 如果電機不需要再運行了(標志為1但步數已完),則停止其PWM輸出、拉高停止引腳、清除運行標志。
    • 如此循環,定時器持續觸發中斷,“喂”給電機一個接一個脈沖,兩個電機各自推進各自的步數。當某個電機先完成目標時,其標志會被清零,但定時器不中止,另一個電機繼續運行。
  • 停止階段: 當且僅當檢測到兩個電機都無需再運行時(即本次中斷中沒有任何一個電機產生脈沖,needStop 保持為1),系統調用 HAL_TIM_Base_Stop_IT 停止定時器。這終止了進一步的中斷調用,意味著預定的運動已全部完成。此時兩個電機的運行標志都已清零,上層代碼通過檢測這些標志即可知道運動結束。

  • 后續處理: 主控制邏輯往往在發出運動命令后,會等待運動完成再進行下一步。例如代碼里 while (motor0_Running || motor1_Running); 就是忙等待兩個電機完成。完成后,主邏輯可能記錄當前位置(如更新 currentX, currentY)或者執行其他動作(如控制其它執行器)。整個過程保證了運動的確定性:不會多走少走步數,且結束時電機狀態明確。

控制邏輯作用總結: 該流程相當于實現了一個定長步進運動控制器。上層只需指定方向和步數,啟動運動后,底層通過定時器中斷精確輸出對應數量的脈沖給電機,達到步數后自動停止。一方面,它解放了主CPU(利用硬件定時+中斷來產生精確定時脈沖,而非軟件延時),另一方面,它確保了運動達到預期的位置:由于記錄了 targetSteps 和逐步比較 stepCount,不會遺漏或多發脈沖。通過標志變量的設置和清除,上層代碼也能方便地與此異步過程交互(如等待完成或提前停止等)。

在整個系統中,這段控制邏輯扮演著驅動底層執行機構(步進電機)的任務調度者角色:依據目標,對電機發出一系列脈沖“指令”,嚴格按計劃數量執行,然后在任務完成時善后(停止定時器、清標志)。對于雙電機同時運動的情況,它還能基本同步地驅動兩軸(在相同的時間基準下脈沖輸出),滿足簡單的直線運動要求。總之,該流程保證了步進電機按指令運動到位,是運動控制系統可靠運行的關鍵。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/81698.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/81698.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/81698.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

什么是Linux中的systemd?

寫在前面 為什么要回過頭來復習linux的system的&#xff0c;最近在研究DELL EMC的PowerStore存儲系統&#xff0c;其底層是基于CoreOS開發的&#xff0c;這套操作系統是基于Systemd來設計的。所以要深入了解PowerStore就必須對systemd做詳細了解。 systemd 是一個用于 Linux …

Linux 環境下 Mysql 5.7 數據定期備份

目錄 一、創建數據備份腳本二、查看備份日志三、數據庫數據恢復 備份策略&#xff1a; 系統環境 openEuler 22.03 (LTS-SP4) 單機備份 每天凌晨2點&#xff0c;指定數據庫表全量備份&#xff0c;只保留近7次備份數據 每次的腳本執行&#xff0c;將會記錄執行結果到日志&#xf…

C 語言字符輸入:掌握 getchar 和 scanf 的用法與陷阱

各類資料學習下載合集 ??https://pan.quark.cn/s/8c91ccb5a474?? C 語言字符輸入:掌握 getchar 和 scanf 的用法與陷阱 你好!在 C 語言編程中,與用戶進行交互最基本的方式就是通過標準輸入和標準輸出。我們之前探討了如何使用 ??printf?? 和 ??putchar?? 進行…

【React】 Hooks useTransition 解析與性能優化實踐

1.背景 useTransition 是 React 18 引入的一個并發模式下的 Hook&#xff0c;用于區分緊急和非緊急的狀態更新&#xff0c;提升應用的響應性和用戶體驗;它可以管理 UI 中的過渡狀態&#xff0c;特別是在處理長時間運行的狀態更新時。它允許你將某些更新標記為“過渡”狀態&…

蘑菇管理——AI與思維模型【94】

一、定義 蘑菇管理思維模型是一種形象地描述組織對待新員工或初入職場者的管理方式及相關現象的思維模型。它將新員工或初入職場者比作蘑菇&#xff0c;這些人在初期往往被置于陰暗的角落&#xff08;不受重視的部門&#xff0c;或打雜跑腿的工作&#xff09;&#xff0c;澆上…

c++STL——set和map的使用

文章目錄 set和map的使用set系列聲名和定義默認成員函數迭代器set的增刪查lower_bound和upper_boundInsert接口pair類 對于查找的另一種使用 set和multiset的區別 map系列聲名和定義pair類的進一步介紹默認成員函數map的增刪查map的數據修改map和multimap的差異 set和map的使用…

什么是DGI數據治理框架?

DGI數據治理框架是由數據治理研究所&#xff08;Data Governance Institute, DGI&#xff09;提出的一套系統性方法論&#xff0c;旨在幫助企業或組織建立有效的數據治理體系&#xff0c;確保數據資產的高質量管理、合規使用和價值釋放。以下是關于DGI數據治理框架的核心內容&a…

chrome 瀏覽器怎么不自動提示是否翻譯網站

每次訪問外國語網頁都會彈出這個對話框&#xff0c;很是麻煩&#xff0c;每次都得手動關閉一下。 不讓他彈出來方法&#xff1a; 設置》語言》首選語言》添加語言&#xff0c;搜索英語添加上 如果需要使用翻譯&#xff0c;就點擊三個點&#xff0c;然后選擇翻譯

LeetCode 熱題 100 54. 螺旋矩陣

LeetCode 熱題 100 | 54. 螺旋矩陣 大家好&#xff0c;今天我們來解決一道經典的算法題——螺旋矩陣。這道題在LeetCode上被標記為中等難度&#xff0c;要求我們按照順時針螺旋順序返回矩陣中的所有元素。下面我將詳細講解解題思路&#xff0c;并附上Python代碼實現。 問題描述…

生成式AI將重塑的未來工作

在人類文明的長河中,技術革命始終是推動社會進步的核心動力。從蒸汽機的轟鳴到互聯網的浪潮,每一次技術躍遷都在重塑著人類的工作方式與生存形態。而今,生成式人工智能(Generative AI)的崛起,正以超越以往任何時代的速度與深度,叩響未來工作范式變革的大門。這場變革并非…

【2025軟考高級架構師】——2024年05月份真題與解析

摘要 本文內容是關于2025年軟考高級架構師考試的相關資料&#xff0c;包含2024年05月份真題與解析。其中涉及體系結構演化的步驟、OSI協議中能提供安全服務的層次、數據庫設計階段中進行關系反規范化的環節等知識點&#xff0c;還提及了軟考高級架構師考試的多個模塊&#xff…

KAG:通過知識增強生成提升專業領域的大型語言模型(三)

目錄 摘要 Abstract 1 Schema 2 Prompt 3 KAG-Builder 3.1 reader 3.2 splitter 3.3 extractor 3.4 vectorizer 3.5 writer 3.6 可選組件 4 示例 總結 摘要 本周深入學習了 KAG 項目中的 Schema、Prompt 以及 KAG-Builder 相關代碼知識&#xff0c;涵蓋了其定義、…

Gitea windows服務注冊,服務啟動、停止、重啟腳本

修改配置文件 查看COMPUTERNAME echo %COMPUTERNAME%進入配置文件D:\gitea\custom\conf\app.ini&#xff0c;將 Gitea 設置為以本地系統用戶運行 如果結果是 USER-PC&#xff0c;那么 RUN_USER USER-PC$ RUN_USER COMPUTERNAME$SQLite3 PATH配置&#xff0c;更改為包含完整…

礦泉水瓶的繪制

1.制作中心矩形&#xff0c;大小為60&#xff0c;注意設置矩形的兩條邊相等 2.點擊拉伸&#xff0c;高度為150mm 3.使用圓角命令&#xff0c;點擊連接到開始面&#xff0c;同時選中4條邊&#xff0c;進行圓角轉化&#xff0c;圓角大小為10mm&#xff0c;點擊多半徑圓角&#xf…

【程序+論文】大規模新能源并網下的火電機組深度調峰經濟調度

目錄 1 主要內容 講解重點 2 講解視頻及代碼 1 主要內容 該視頻為《大規模新能源并網下的火電機組深度調峰經濟調度》代碼講解內容&#xff0c;該程序有完全對照的論文&#xff0c;以改進IEEE30節點作為研究對象&#xff0c;系統包括5個火電機組和2個新能源機組&#xff0c;…

??工業機器人智能編程:從示教器到AI自主決策??

工業機器人智能編程:從示教器到AI自主決策 引言 工業機器人作為智能制造的核心裝備,其編程方式正經歷革命性變革。傳統示教器編程效率低下,平均每個路徑點需要30秒人工示教,而復雜軌跡編程可能耗時數周。隨著AI技術的發展,工業機器人編程正朝著"所見即所得"的…

n8n 構建一個 ReAct AI Agent 示例

n8n 構建一個 ReAct AI Agent 示例 0. 引言1. 詳細步驟創建一個 "When Executed by Another Workflow"創建一個 "Edit Fields (Set)"再創建一個 "Edit Fields (Set)"創建一個 HTTP Request創建一個 If 節點在 true 分支創建一個 "Edit Fiel…

Monorepo項目多項目一次性啟動工具對比與實踐

Monorepo項目多項目一次性啟動工具對比與實踐 在現代軟件開發中&#xff0c;Monorepo&#xff08;單一倉庫&#xff09;模式越來越受到開發者的青睞。Monorepo將多個相關的項目或包集中在一個倉庫中進行管理&#xff0c;方便依賴共享、代碼復用和統一發布。在Monorepo項目開發…

筆記整理六----OSPF協議

OSPF 動態路由的分類&#xff1a; 1.基于網絡范圍進行劃分--將網絡本身劃分為一個個AS&#xff08;自治系統---方便管理和維護&#xff09; 內部網關協議---負責AS內部用戶之間互相訪問使用的協議 IGP--RIP EIGRP ISIS OSPF 外部網關協議--負責AS之間&#xff08;整個互聯網&…

網絡編程,使用select()進行簡單服務端與客戶端通信

這里在Ubuntu環境下演示 一般流程 服務端常用函數&#xff1a; socket()&#xff1a;創建一個新的套接字。bind()&#xff1a;將套接字與特定的IP地址和端口綁定。listen()&#xff1a;使套接字開始監聽傳入的連接請求。accept()&#xff1a;接受一個傳入的連接請求&#xff…