步進電機由于具有角位移和輸入脈沖數成正比并且沒有累積誤差的特點,而被廣泛的用作汽車儀表的顯示部件,其中具有代表性的是偉力驅動技術(深圳)有限公司的VID29系列步進電機。在多數情況下,人們會使用專用的驅動芯片來驅動步進電機,主控制器只需要給出方向控制信號和控制轉動步數的脈沖就行了。另外,也有集成了步進電機驅動電路的MCU,如Freescale的MC9S12HY系列,其使用方法也比較簡單。然而,在很多較低端的汽車儀表,如微型車、農用車、三輪貨車和摩托車的儀表上,人們為了降低成本,希望能夠不用專用驅動芯片或相對較貴的帶驅動電路的MCU,而是用普通的MCU直接去驅動步進電機。本應用筆記介紹了在Freescale的HCS08系列MCU上,如何用軟件來實現對VID29系列步進電機的直接驅動。本文所附帶的程序,已經在Freescale的LG32 Cluster ReferenceDesign演示板上運行驗證過。 VID29系列步進電機的工作原理 VID29系列步進電機是兩相步進電機經三級齒輪減速傳動輸出的。該步進電機的工作原理可以用下面的簡化的結構圖(圖1~4)進行說明。在象VID29系列這樣的兩相步進電機中,轉子是一個永磁體,定子上安裝了兩組線圈。當給定子線圈通上電流的時候,就在轉子周圍的氣隙中產生了一個磁場,轉子就會在磁力的作用下轉動到使它自身的磁場方向和線圈電流產生的氣隙磁場方向平行的位置(下文中把它叫做平衡位置)。要讓步進電機連續地旋轉,可以按如下步驟進行: 1. 如圖1所示,在線圈A中通上電流,轉子就會轉過90度到圖2所示的位置; 2. 如圖2所示,斷開線圈A中的電流,給線圈B通上電流,轉子又會繼續旋轉90度到圖3 所示的位置; 3. 如圖3所示,斷開線圈B中的電流,給線圈A通上跟步驟1中方向相反的電流,轉子繼續旋轉90度到圖4所示的位置; 4. 如圖4所示,斷開線圈A中的電流,給線圈B通上跟步驟2中方向相反的電流,轉子繼續旋轉90度回到圖1所示的位置; 5. 重復步驟1~4,步進電機就會連續地旋轉起來了。 如果將步驟1~4的順序顛倒過來,那么步進電機就會以相反的方向旋轉。另外,如果將A和B兩個線圈同時通以大小相同的電流,那么產生的合成磁場的方向就和一個線圈單獨通電時的磁場方向成45度夾角,這樣轉子就將旋轉45度,而不是90度。 實際的步進電機由于轉子的形狀和定子線圈的安裝方位跟上述的簡化結構不同,所以工作時驅動電流的時序和轉子每一步旋轉的角度也不完全一樣。對于VID29系列步進電機來說,它的驅動脈沖序列和轉子相應的旋轉角度如圖5所示。 分步驅動和微步驅動 步進電機的驅動通常有分步方式和微步方式兩種,圖5中的脈沖序列是分步方式下的驅動信號。分步方式的優點是驅動信號的幅度只有0和電源電壓(5V)兩種,與數字信號的低電平和高電平完全一一對應,因此只要使用MCU的普通數字I/O口(GPIO)就可以產生驅動信號,驅動程序也比較簡單。但是由于分步方式下,定子線圈產生的氣隙磁場的方向在每走一步的過程中都發生一個較大的跳變——對于VID29系列步進電機而言是60度的跳變,定子磁場從原來的方向跳變到下一個平衡位置的方向,轉子則在磁力的作用下加速向下一個平衡位置轉動,當它到達平衡位置的那個瞬間,速度達到最大值,而磁場力則變為零(只考慮切向力,不考慮徑向力,因為徑向力與轉動無關。下同);然后,如果驅動信號沒有變化的話,轉子就會在慣性的作用下繼續往前轉動偏離平衡位置,這時磁場力將會增大,而其方向卻變成跟剛才相反,于是就使轉子減速,當轉子與平衡位置的偏離達到最大時,其速度減為零,然后在磁場力作用下往回加速轉動;當轉子轉回平衡位置時,磁場力又變為零,而速度不為零,于是在慣性的作用下繼續轉動偏離平衡位置……如此反復,只要驅動信號還沒有再次改變,轉子就會象蕩秋千一樣在平衡位置附近來回振蕩,并在摩擦力的作用下幅度逐漸減小。這種振蕩還會產生一定的噪聲,所以用分步方式驅動時,步進電機的噪聲和抖動會比較大。 為了減小步進電機運行時的噪聲和抖動,人們設法讓定子線圈的磁場方向的跳變幅度變小,把一個分步一次的大跳變分成若干次較小的跳變來完成,于是就有了微步驅動方式,也叫細分驅動方式。 根據矢量合成的原理,當步進電機中的兩個線圈各自產生的磁場的強度按照正/余弦規律變化的時候,它們的合成磁場的方向就會勻速旋轉,而合成磁場的強度保持不變,如圖6所示。線圈產生的磁場強度與通過它的電流大小成正比,因此微步驅動方式就是讓通過線圈的驅動電流不是象分步方式那樣在0和最大值之間跳變,而是按照正/余弦規律分成幾個階梯逐步變化,如圖7所示。 那么如何來產生階梯變化的驅動電流呢?通常的做法是將一個PWM波形電壓信號施加到線圈上;同時串聯一個阻值較小的電阻作為電流傳感器,將電流信號轉換成電壓信號反饋回PWM控制器中;PWM控制器根據反饋信號調整輸出脈沖的占空比,從而使線圈上的平均電流等于所需的階梯電流。目前,常見的步進電機專用驅動芯片就是依據這個原理來工作的。在使用MCU直接驅動步進電機的時候,因為MCU內部也集成了PWM模塊,所以我們也可以采用這個方法。但是,這種方法還需要使用ADC來測量反饋信號的大小,并且要實時地計算出所需的PWM脈沖的占空比,因此將會占用太多的MCU的資源,使MCU幾乎無法再處理其他的事情。 為了減少對MCU資源的占用,我們可以將其中的反饋環節刪掉,從閉環控制變為開環控制。對每個階梯電流,我們事先計算出所需的PWM脈沖的占空比,并做成查找表存放在FLASH中。在驅動步進電機轉動的時候,每走一個微步就從表中取出相應的占空比來對PWM模塊進行設置,然后在當前的這一步結束之前不再改變PWM脈沖的占空比。這樣一來就極大的減少了計算量,使MCU有足夠的資源去處理其他的事情。然而,由于定子線圈具有一定的電感,所以通過線圈的平均電流和PWM脈沖的占空比并不是線性關系,要想精確的計算出每個階梯電流對應的占空比是相當困難的;另外,當轉子旋轉的時候,還會在定子線圈中產生感生電動勢,這個感生電動勢會使通過線圈的電流發生改變,而它的大小又與轉子永磁體的磁場強度和旋轉速度相關。因此,事實上在開環控制中不管你使用多么復雜的數學公式來計算占空比,都無法使通過線圈的平均電流總是等于預期的階梯電流。不過,所幸的是:在低端的汽車儀表中,并不要求對步進電機的轉動控制到那么精確的程度,我們可以姑且認為通過線圈的平均電流是和PWM脈沖的占空比成正比的,反正只要減小了每一步跳變的角度(相對于分步方式而言),就可以讓步進電機轉動得更平穩一些了,噪聲也能減小一些。 電機轉動的加減速 步進電機在轉動時,因為轉子、傳動齒輪和負載的轉動慣量,使它從一個位置轉動到下一個位置(一個分步或微步)需要一定的時間。如果在轉子轉動到下一個位置之前,驅動信號就又往前走了一步的話,那么轉子的磁場方向和定子線圈產生的氣隙磁場方向的夾角就會超過一個分步或微步所對應的角度。只要轉子的旋轉速度跟不上驅動信號的變化速度,這個夾角就會越來越大,當夾角超過180度的時候,磁場對轉子的作用力的方向就會變得跟原來的方向相反,如圖8所示。這時,轉子的旋轉速度就會減慢,直到變成以相反的方向旋轉。最終的結果就是轉子所轉過的角度和氣隙磁場所轉過的角度不相等了,也就是轉子所轉過的步數和驅動信號走過的步數不相等了,人們常把這種現象叫做“失步”。同樣的,當要使步進電機從高速的旋轉中停下來的時候,如果驅動信號的變化過快,轉子就有可能在慣性的作用下繼續旋轉超過180度,從而也產生失步。另外,由于轉子軸承、傳動齒輪和負載上都有一定的摩擦阻力,因此電機在連續轉動時的速度也是有限的,如果驅動信號的變化速度超過了電機能達到的最大轉速的話,電機也會失步。 那么,如果讓驅動信號一直保持較慢的變化速度,是不是就沒有問題了呢?答案當然是否定的。這是因為步進電機作為儀表的顯示部件,我們要求它能夠將被測信號的變化實時地顯示出來;而電機轉動如果比較慢,那么儀表的顯示就無法跟上被測信號的變化。 為了讓步進電機既不會失步,又能轉得盡可能的快,那么就要讓驅動信號的變化速度和轉子轉動的速度保持基本一致。當電機啟動的時候,轉子做加速轉動,這時第一步的持續時間要比較長,然后每一步的持續時間逐漸變短,對應的轉動速度變化如圖9所示。電機停止的過程則與之相反。在VID29系列步進電機的數據手冊上給出了電機啟動/停止時允許的驅動信號的變化速度(啟動頻率,Start-stop Frequency)和電機連續轉動時允許的驅動信號的變化速度(最大驅動頻率,Max Driving Frequency),我們可以根據它們計算出第一步的持續時間和加速過程結束后的每一步的持續時間。 步進電機和MCU的硬件連接 在LG32 Cluster Reference Design中,MCU和步進電機之間的連接如圖10所示。其中使用了一片74ACT125作為電流放大驅動,這是因為MC9S08LG32的I/O口輸出的電流最大只10mA,而VID29步進電機需要的驅動電流最大可達20mA。使用TPM模塊的兩個PWM輸出通道驅動步進電機兩個線圈的正極,兩個普通I/O口驅動兩個線圈的負極。TPM模塊的兩個通道也可以設置成普通I/O口,這樣就可以根據需要使用微步方式驅動或者分步方式驅動。 在MC9S08LG32中集成了兩個TPM模塊,其中TPM1有2個通道,TPM2有6個通道。在這里選擇TPM1來驅動步進電機,是因為當把一個TPM模塊的某一個通道設置為PWM輸出時,此TPM模塊公用的模數(MOD)寄存器將被設成一個比較特殊的值,這樣就會給它的其它通道的功能使用造成很多限制。所以為了更加充分地利用MCU的資源,這里選擇了通道較少的TPM1,而把通道較多的TPM2留作他用。 步進電機驅動程序 本驅動程序為應用程序提供的接口函數有三個: 1. InitStepper:初始化函數,對驅動所用到的I/O口和定時器進行設置,并讓步進電機轉到初始位置——使儀表的指針指到零點的位置。 函數原型:void InitStepper(void); 參數:無 返回值:無 2. SetStepperTarget:設定步進電機的目標位置,也就是要讓儀表的指針轉到哪個位置(以相對于零點的角度來表示),整個轉動的過程(如需要轉多少步,往哪個方向轉等)應用程序無需知道,而且應用程序可以指定任意目標位置。 函數原型:void SetStepperTarget(word wTargetDegree); 參數:word wTargetDegree,目標位置相對于零點的角度,其值是以(1/12)度(等 于微步方式下的步距)為單位的; 返回值:無 3. GetStepperCurrent:得到步進電機的當前位置。 函數原型:word GetStepperCurrent(void); 參數:無 返回值:返回儀表的指針當前所指的位置(以相對于零點的角度來表示),其值也以(1/12)度(等于微步方式下的步距)為單位。 另外,在頭文件Stepper.h中定義了選擇驅動方式的宏,使用者修改宏定義就可以選擇分步驅動方式或微步驅動方式,如下: #define STEPPER_PARTIAL_MODE 0 #define STEPPER_MICRO_MODE !STEPPER_PARTIAL_MODE 如前所述,驅動信號的變化速度不能太快,每次變化后都必須保持一段時間不變,為了讓驅動程序占用的CPU的處理時間更少,就需要用到一個定時器。除了上面的三個接口函數外,驅動程序的其余部分都在定時器的中斷服務程序中運行。 在驅動程序中,用兩個靜態變量來保存步進電機的目標位置和當前位置,其值是到零點的步數。定時器中斷由SetStepperTarget函數使能,在中斷服務程序中根據目標位置和當前位置的差值來決定步進電機轉動的方向和步數,然后根據選擇的驅動方式執行相應的轉動程序。 分步方式程序 從前面的圖5中,可以看到分步方式下的驅動信號是周期性變化的,每個周期對應轉子旋轉一圈(輸出軸旋轉2度),其中包含6個分步,分別對應轉子的6個平衡位置,我們也可以把它們叫做6個相位。因此,分步驅動方式下MCU的4個I/O口輸出的電平也有6種組合,分別對應這6個相位。 在程序中,使用一個靜態局部變量bPhase來保存步進電機當前所處的相位,步進電機每走一個分步,相位就加1(逆時針轉)或者減1(順時針轉),然后在一個switch…case結構中按新的相位設置I/O口的輸出狀態,如下: switch(bPhase) { case 0: STEPPER_LP = 1; STEPPER_LN = 0; STEPPER_RP = 1; STEPPER_RN = 0; break; case 1: STEPPER_LP = 0; STEPPER_LN = 0; STEPPER_RP = 1; STEPPER_RN = 0; break; case 2: STEPPER_LP = 0; STEPPER_LN = 1; STEPPER_RP = 0; STEPPER_RN = 0; break; case 3: STEPPER_LP = 0; STEPPER_LN = 1; STEPPER_RP = 0; STEPPER_RN = 1; break; case 4: STEPPER_LP = 0; STEPPER_LN = 0; STEPPER_RP = 0; STEPPER_RN = 1; break; case 5: STEPPER_LP = 1; STEPPER_LN = 0; STEPPER_RP = 0; STEPPER_RN = 0; break; default: ; } 微步方式程序 從前面的圖7中,可以看到微步方式下的驅動信號是近似于正弦波的階梯電流信號,每個周期對應轉子旋轉一圈(輸出軸旋轉2度),當把每個分步細分成4個微步的時候,一個正弦波周期里就有24個階梯。本文利用PWM來產生這些階梯電流,并且近似地認為PWM的占空比與平均電流大小成正比。 首先,把TPM1的通道0和1初始化成邊沿對齊的PWM工作模式,設置TPM1的工作時鐘為總線時鐘,預分頻系數為1,設置TPM1MOD的值為255,這樣當總線時鐘頻率為16MHz時,所產生的PWM信號的頻率是64KHz。在對TPM進行設置的時候需要考慮兩個方面: 其一,因為PWM的占空比與平均電流大小成正比,所以要使產生的平均電流盡量接近理想的正弦波分成24個階梯時的值,就要求PWM占空比的精度比較高。TPM1MOD的值決定了每個PWM周期里有多少個時鐘周期,脈沖寬度則由各個通道的Value寄存器的值決定,最小為0(對應占空比為0),最大為(TPM1MOD+1)(對應占空比為100%),設置Value寄存器的值大于(TPM1MOD+1)的效果和設為等于(TPM1MOD+1)是一樣的。PWM的占空比其實就是Value寄存器的值(TPM1MOD+1)的比值,由于寄存器里的值只能是整數,所以占空比的精度只能達到1/(TPM1MOD+1)。因此,要使占空比的精度較高,就要給TPM1MOD設置比較大的值。 其二,因為電機的線圈是個感性負載,所以用PWM驅動的時候,線圈上的電流是波浪式變化的,如圖11所示。電流的變化導致磁場強度的變化,兩個線圈各自產生的磁場強度變化則導致合成磁場的強度和方向都發生變化,這種波浪式的變化將使電機產生振動和噪聲。顯然,電流波紋的幅度是PWM信號的周期的單調增函數,即PWM的周期越長則電流波紋的幅度越大。因此,PWM的周期應當盡量短,而PWM的周期等于(TPM1MOD+1)乘以TPM1的工作時鐘的周期,所以應當使TPM1的工作時鐘的頻率盡量高,而且TPM1MOD的值不宜設得太大。 設置完PWM的工作時鐘頻率和模值(TPM1MOD)后,還要計算出各個階梯電流所對應的占空比,即Value寄存器的值,計算公式如下: 把算出的數值做成查找表放在FLASH存儲器中。兩個線圈的電流相位相差60度 ,而 ,因此把由上式計算得到的一組數字的順序循環移動4個位置就得到另一個線圈的電流對應的查找表。由于PWM的占空比只能控制平均電流的大小,而電流的方向由其他設置決定,所以程序中這兩個表的數字都取絕對值,它們的定義如下: static const word waCosineTable[] = { 256, 246, 221, 180, 127, 65, 0, 65, 127, 180, 221, 246, 256, 246, 221, 180, 127, 65, 0, 65, 127, 180, 221, 246 }; static const word waShiftCosTable[] = { 127, 180, 221, 246, 256, 246, 221, 180, 127, 65, 0, 65, 127, 180, 221, 246, 256, 246, 221, 180, 127, 65, 0, 65 }; 與分步方式程序相似地,本文把這24個階梯叫做24個相位,用一個靜態局部變量bPhase來保存步進電機當前所處的相位,步進電機每走一個微步,相位就加1(逆時針轉)或者減1(順時針轉),然后在兩個查找表中取出相應的數值寫到TPM1的兩個通道的Value寄存器中。為了實現電流的方向變化,需要在電流過零對應的相位時改變PWM輸出的極性和連接線圈另一極的GPIO口輸出的電平,在程序中用switch…case結構來完成這個任務,代碼如下: void MoveStepper1Micro(void) { static byte bPhase; if(bDirection == 1) { if(bPhase == 0) bPhase = 23; else bPhase--; switch(bPhase) { case 17: V I t STEPPER_LN = 1; //設置左線圈負極GPIO口輸出高電平,并 TPM1C0SC = 0x24; //設置PWM極性為低有效,使電流方向為負 break; case 21: STEPPER_RN = 1; //設置右線圈負極GPIO口輸出高電平,并 TPM1C1SC = 0x24; //設置PWM極性為低有效,使電流方向為負 break; case 5: STEPPER_LN = 0; //設置左線圈負極GPIO口輸出低電平,并 TPM1C0SC = 0x28; //設置PWM極性為高有效,使電流方向為正 break; case 9: STEPPER_RN = 0; //設置右線圈負極GPIO口輸出低電平,并 TPM1C1SC = 0x28; //設置PWM極性為高有效,使電流方向為正 break; default: ; } wCurrentPosition++; } else if(bDirection == 0xFF) { if(bPhase == 23) bPhase = 0; else bPhase++; switch(bPhase) { case 6: STEPPER_LN = 1; //設置左線圈負極GPIO口輸出高電平,并 TPM1C0SC = 0x24; //設置PWM極性為低有效,使電流方向為負 break; case 10: STEPPER_RN = 1; //設置右線圈負極GPIO口輸出高電平,并 TPM1C1SC = 0x24; //設置PWM極性為低有效,使電流方向為負 break; case 18: STEPPER_LN = 0; //設置左線圈負極GPIO口輸出低電平,并 TPM1C0SC = 0x28; //設置PWM極性為高有效,使電流方向為正 break; case 22: STEPPER_RN = 0; //設置右線圈負極GPIO口輸出低電平,并 TPM1C1SC = 0x28; //設置PWM極性為高有效,使電流方向為正 break; default: ; } wCurrentPosition--; } TPM1C0V = waCosineTable[bPhase]; TPM1C1V = waShiftCosTable[bPhase]; } 轉動速度控制 由于被測量的輸入信號的變化是隨機的,有時快有時慢,為了讓儀表實時、直觀地顯示出輸入信號的變化,驅動程序就必須對步進電機的轉動速度進行適當的控制。可以說,一個汽車儀表做得好不好,很大程度上就看它對步進電機的轉動控制得好不好。 通常,儀表對輸入信號進行周期性的定時測量,因此對步進電機目標位置(指針位置)的設定也是每隔一段時間進行一次的。在程序中給這個間隔時間定義了一個宏,放在Stepper.h頭文件中,以便根據應用程序的需要作修改,宏定義如下: #define STEPPER_UPDATE_INTERVAL 256 //單位:毫秒,必須在(8,512)內 這里把指針位置的更新間隔時間限定在8到512毫秒之間是因為: 1. 儀表是用來給人看的,而人眼并不能看清變化非常快的東西,所以對指針位置更新得太快就沒有實際意義,徒然增加CPU的處理負擔而已。 2. 如下文將要提到的,本程序使用的定時器所能達到的最大中斷間隔時間為512毫秒,為了簡化定時器的中斷服務程序,減小CPU的負荷,所以限定指針位置的更新間隔時間不要超過512毫秒。 為了讓儀表的指針擺動得更加平穩、自然,最好能讓電機在下一次設定目標位置前的那一刻剛好轉動到本次設定的目標位置。為此就要計算出電機在這一段時間里的平均旋轉速度,也就是每個分步或微步的平均間隔時間。當所需的平均速度較大時,如前所述,還需要對電機進行加減速的控制。 為了實現步進電機的轉動速度控制,在定時器的每次中斷里只讓電機轉動一個分步/微步,然后用一定的算法計算出這一步到下一步之間應當間隔的時間,以重新設置定時器的溢出時間。在本驅動程序中,定時器選用的是TPM2模塊的通道0,對其相關的寄存器的設置說明如下: 初始化: SCGC1_TPM2 = 1; //使能TPM2模塊的時鐘 TPM2MOD = 0; //設置TPM2的計數器為自由運行模式 TPM2SC = 0x0F; //選擇總線時鐘為時鐘源,預分頻系數為128 把預分頻系數設置為128是為了讓定時器的溢出時間能夠盡可能大,減少中斷對CPU造 成的負擔。當總線時鐘頻率為16MHz時,此定時器能達到的最大中斷間隔時間是512毫秒。 啟動定時器: TPM2C0V = TPM2CNT + 2; TPM2C0SC = 0x50; 設置通道0為輸出比較模式,比較一致時產生中斷,但比較結果不輸出到管腳上(相關管腳仍然由GPIO控制)。因為啟動定時器時步進電機還沒有開始轉動,所以給比較值寄存器(TPM2C0V)設置的值是計數器(TPM2CNT)當前的值加2,即讓它盡快地產生一次中斷。然后在每次中斷產生后,在中斷服務程序里讓步進電機轉動一步,并給TPM2C0V設置一個新的值,即根據所需的間隔時間給TPM2C0V增加一定的數值。 為了對步進電機進行加減速控制,我們需要知道它啟動時第一步所需的間隔時間和最大轉速時每一步所需的間隔時間。步進電機啟動時第一步所需的間隔時間的最小值(Tss)可以由下面的公式計算得到: 式中,d是步距,即每走一步輸出軸轉過的角度;fss是啟動頻率,即啟動時允許的輸出軸的最大轉速,單位是(度/秒)。 從VID29系列步進電機的數據手冊上可以查到,fss等于125(度/秒),在分步方式下d等于(1/3)度。代入上式,可以算出Tss等于(1/375)秒,約等于2667微秒。 在程序中定義MAX_PARTIAL_STEP_TIME為400,當在中斷服務程序里把TPM2C0V的值增加400后,下一次比較中斷產生的時間和本次中斷之間的間隔就為3200微秒,大于Tss且還有一定的裕量。 步進電機達到最大轉速時每一步所需的間隔時間(Tmm),計算公式如下: 式中,d仍是步距,fmm是最大驅動頻率,即連續旋轉時輸出軸的最大轉速,單位是(度/秒)。 從VID29系列步進電機的數據手冊上查到fmm等于600(度/秒),算出Tmm約等于556微秒。在程序中定義MIN_PARTIAL_STEP_TIME為80,對應的間隔時間為640微秒,同樣是大于Tmm且有一定的裕量。 對于微步方式,由于我們把每個分步細分成4個微步,所以相應的Tss和Tmm都是分步方式時的四分之一。 在程序中,設定步進電機的目標位置SetStepperTarget函數里根據目標位置與當前位置的差(wDiff) 計算出需要的平均轉速, 也就是每一步的平均間隔時間(wAverageStepTime),根據平均間隔時間設置TPM2C0V的增量(wTimerIncrement),并啟動定時器。在定時器的中斷服務程序中驅動電機一步一步地向目標位置轉動,當步進電機轉動到目標位置后,讓定時器停止工作。 另外,考慮到輸入信號變化很快時,電機的轉動速度可能跟不上信號的變化,從而在下一次測量完輸入信號,對步進電機的目標位置再次進行設定時,電機還正在轉動之中。這時,電機的轉動速度有可能很快,在這種情況下如果重新啟動定時器則有可能造成失步,因此SetStepperTarget程序根據電機當前的狀態進行了分別的處理,其流程如圖12所示。 在定時器的中斷服務程序中,首先判斷bBrakeFlag標志,如果不是0,則表示當前轉動方向跟目標位置不一致,需要先減速到停止,然后再反向轉動。當bBrakeFlag為0時,根據平均間隔時間決定何時讓電機轉動一個分步/微步,以及是否需要進行加減速。當平均間隔時間大于Tss時,電機每隔一個平均間隔時間轉動一步,作勻速轉動。而當平均間隔時間小于Tss時,則讓電機第一步的間隔時間為Tss,然后逐漸減小,即做加速轉動,直到達到需要的平均轉速或電機允許的最高轉速;到接近目標位置時,則讓每一步的間隔時間逐漸加長,電機減速轉動,并且使最后一步的間隔時間不小于Tss,以保證不會失步。 定時器中斷服務程序的流程如圖13所示。 總結 使用本文給出的驅動程序,用戶的應用程序和驅動程序之間的接口非常簡單,所有的控制步進電機的邏輯都封裝在驅動程序中,而且驅動程序占用CPU的處理時間非常少。另外,本程序根據汽車儀表應用的特點對步進電機的轉動速度進行了相應的控制,所以不管輸入信號變化快慢,電機輸出帶動的指針都能快速、平穩地轉動,以讓人感覺很自然的方式將輸入的物理量顯示出來。 |