單片機與控制實驗(4)——步進電機原理及應用


本文為大大維原創,最早於博客園發表,轉載請注明出處!!! 

一、實驗目的和要求

  了解步進電機的工作原理,學習用單片機的步進電機控制系統的硬件設計方法,掌握定時器和中斷系統的應用,熟悉單片機應用系統的設計與調試方法。 

二、實驗設備

  單片機測控實驗系統
  步進電機控制實驗模塊
  Keil開發環境
  STC-ISP程序下載工具

三、實驗內容

  編制MCS-51程序使步進電機按照規定的轉速和方向進行旋轉,並將已轉動的步數顯示在數碼管上。

  步進電機的轉速分為兩檔,當按下S1開關時,加速旋轉,速度從10轉/分加速到60轉/分。當松開開關時,減速旋轉,速度恢復為10轉/分。當按下S2開關時,按照逆時針旋轉;當松開時,按照順時針旋轉。

  本程序要求使用定時器中斷來實現,不准使用程序延時的方式。

 

四、實驗步驟

 

1、 預習

  參考輔助材料,學習C51編程語言使用和步進電機原理。

2、 簡單程序錄入和調試

(1)關於C51的中斷

  本程序需要使用定時器定時,並使用中斷來同步。中斷程序的典型例子如下:
  格式:void 函數名()interrupt 中斷號 using 工作組
  {
  中斷服務程序內容
  }
  注意:中斷不能返回任何值,所以前面是 void 后面是函數名,名字可以自己起,但不要與c語言的關鍵字相同;中斷函數不帶任何參數,所以 函數名后面的()內是 空的,中斷號是指單片機的幾個中斷源的序號。這個序號是單片機識別不同中斷的唯一標志。所以一定要寫正確。
  后面的using 工作組 是指這個這個中斷使用單片機內存中 4 個工作寄存器的哪一組,c51 編譯后會自動分配工作組,因此最后這句話我們通常省略不寫。

c51 中斷寫法實例:
  void T1-time() interrupt 3
  {
  TH1=(65536-50000)/256;
  TL1=(65536-50000)%256;
  }
  上面的意思是定時器 1 的中斷服務程序,定時器 1 的中斷服務序號是 3 ,因此我們要寫成 interrupt 3 ,服務程序的內容是給 兩個初值寄存器裝入新值。。
  寫中斷前的准備:

  A、TMOD 賦值 確定工作方式。T0 還是T1 的工作方式。
  B、計算初值 裝入 TH0 TL0 或者 TH1 TL1
  C、中斷方式時 ,對 IE 賦值,開放中斷。
  D、使 TR0 和 TR1 置位,啟動定時器/計數器 定時/計數。

 

(2)關於定時器中斷的賦值

  使用定時器時,首先應由外部條件得到要定時的時間長度t,如本實驗中,就是根據要求的速度計算出的每一步之間的間隔。然后選擇適當的定時器工作方式,去計算想要設定的計數器初值s,使用如下方程:

  (2定時器最大位數 - s)× 定時周期 =t   【定時周期 = 12/CPU晶振頻率】

  得到的s需要分成高8位和低8位,分別放入計數器THx和TLx中(x為0或1)。如果s為負數,說明需要的定時時間太長,即使定時器的最大時間也無法滿足要求。這種情況下,需要加入軟件循環才能實現。我們可以將需要的定時時間分成n份,利用定時器達到t/n的時間長度,然后在定時器處理程序中,累計某一變量,如果到達n,說明總的時間t已經達到。

  要想使用定時器中斷,除了上面的定時器初值設定外,還需要將其他相關的特殊功能寄存器也都設置好。如果使用方式0和方式1,不要忘記在計數結束后重新恢復計數器初值。

3、 程序調試

  用單步、斷點、連續方式調試程序,觀察狀態指示燈及電機狀態,檢查運行結果。如果需要,可以將四個輸出信號的狀態同時輸出到P0口的某些位上,便於觀察。

4、 編寫程序,完成功能

 

五、實驗原理

 

1、 我們使用的單片機系統的頻率是12M;步進電機轉動一周需要24步。

2、 本步進電機實驗板,使用FAN8200作為驅動芯片。CPU通過如下4個引腳與FAN8200相連,即:

FAN8200引腳與CPU接口
CPU FAN8200
P1.1 CE1
P1.4 CE2
P3.2 IN1
P1.0 IN2

 

 

 

3、 本實驗使用簡單的雙四拍工作模式即可,這也是FAN8200比較方便的工作方式。只要將CE1和CE2分別置為高,然后IN1和IN2按照預定的脈沖輸出,即01->11->10->00->01這個循環構成一個方向旋轉的輸出脈沖,將此序列翻轉,就是相反方向的輸出脈沖。

 

六、實驗代碼  

 

  1 #include<reg52.h>
  2 typedef unsigned int uint;
  3 sfr   P4=0xC0;
  4 sfr   P4SW=0xBB;
  5 
  6 sbit  s1=P3^6;
  7 sbit  s2=P3^7;
  8 sbit  CE1=P1^1;
  9 sbit  CE2=P1^4;
 10 sbit  IN1=P3^2;
 11 sbit  IN2=P1^0;
 12 sbit  CLK=P4^4;
 13 sbit  DAT=P4^5;
 14 
 15 uint  count=0;                    //用於計已轉動的步數
 16 int   flag=0;                     //用於給IN1、IN2傳值
 17 //二極管顯示碼,存放在code區
 18 uint code tab[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};    
 19 int main()
 20 {
 21     P4SW=0x70;
 22     TMOD=0x01;    
 23     EA=1;
 24     ET0=1;
 25     TR0=1;
 26     CE1=CE2=1;
 27     
 28     while(1);
 29 }
 30 void rotateShun(int flag)
 31 {
 32     //01 11 10 00
 33     switch(flag)
 34     {
 35         case 0:    IN1=0;
 36                 IN2=1;
 37                 break;
 38         case 1:    IN1=1;
 39                 IN2=1;
 40                 break;
 41         case 2:    IN1=1;
 42                 IN2=0;
 43                 break;
 44         case 3:    IN1=0;
 45                 IN2=0;
 46                 break;        
 47     }
 48 }
 49 /*01 11 10 00
 50 * 反方向輸出為
 51 * 00 10 11 01 
 52 * 摁下按鍵后,需向后走一位,所以為
 53 * 10 11 01 00
 54 */
 55 void rotateNi(int flag)
 56 {
 57     //10 11 01 00
 58     switch(flag)
 59     {
 60         case 0:    IN1=1;
 61                 IN2=0;
 62                 break;
 63         case 1:    IN1=1;
 64                 IN2=1;
 65                 break;
 66         case 2:    IN1=0;
 67                 IN2=1;
 68                 break;
 69         case 3:    IN1=0;
 70                 IN2=0;
 71                 break;        
 72     }
 73 }
 74 
 75 void show(uint cnt){                   //顯示一個數字
 76     uint m, c,n;
 77     m = tab[cnt];
 78     for (n = 0; n < 8; n++){
 79         CLK = 0;
 80         //按位邏輯與,和1000 0000與,最高位保留,其他位置0,此處也可以與0x80比較大小來判斷
 81         c= m & 0x80;                   //每次取一位,送往DAT
 82         if(c==0)
 83             DAT=0;
 84         else
 85             DAT=1;
 86         CLK = 1;
 87         m<<= 1;
 88     }
 89 }
 90 
 91 void display(uint cnt){                //顯示
 92     show(cnt%10);                      //個位
 93     cnt /= 10;
 94     show(cnt%10);                      //十位
 95     show(cnt/10);                      //百位
 96 }    
 97 
 98 void timeInt0() interrupt 1
 99 {
100     if(s1==1)
101     {
102         /*不按s1,10r/min=240pace/min=960次/min,
103         *即每分鍾給IN1和IN0送值960次,每次間隔60/960=0.0625s=62.5ms
104         */
105         TH0=(65536-62500)/256;
106         TL0=(65536-62500)%256;
107         if(s2==1)
108         {
109             rotateShun(flag);
110         }
111         if(s2==0)
112         {
113             rotateNi(flag);
114         }
115     }
116     if(s1==0)
117     {
118         /*按下s1,60r/min=1440pace/min=5760次/min,
119         *即每分鍾給IN1和IN0送值960次,每次間隔60/5760ms
120         */
121         TH0=(65536-(uint)(60000/5760))/256;
122         TL0=(65536-(uint)(60000/5760))%256;
123         if(s2==1)
124         {
125             rotateShun(flag);
126         }
127         if(s2==0)
128         {
129             rotateNi(flag);
130         }
131     }
132     flag++;
133     if(flag>3) 
134     {
135         flag=0;
136         count++;
137         if(count < 999)
138         {
139             display(count);
140         }
141         else{
142             count = 0;
143             display(count);
144         }
145     }
146 }

 

 

七、一點想法

  步進電機必須加驅動才可以運轉,驅動信號必須為脈沖信號,沒有脈沖的時候,步進電機靜止,如果加入適當的脈沖信號,就會以一定的角度(稱為步角)轉動,轉動的速度和脈沖的頻率成正比。改變脈沖的順序,可以方便的改變轉動的方向。

  步進電機最好不使用整步狀態,整步狀態時振動大。

八、附錄

 

 實驗電路原理圖:點擊查看


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM