單片機(jī)與控制實(shí)驗(yàn)(4)——步進(jìn)電機(jī)原理及應(yīng)用
掃描二維碼
隨時(shí)隨地手機(jī)看文章
一、實(shí)驗(yàn)?zāi)康暮鸵?br/>
了解步進(jìn)電機(jī)的工作原理,學(xué)習(xí)用單片機(jī)的步進(jìn)電機(jī)控制系統(tǒng)的硬件設(shè)計(jì)方法,掌握定時(shí)器和中斷系統(tǒng)的應(yīng)用,熟悉單片機(jī)應(yīng)用系統(tǒng)的設(shè)計(jì)與調(diào)試方法。
二、實(shí)驗(yàn)設(shè)備
單片機(jī)測(cè)控實(shí)驗(yàn)系統(tǒng)
步進(jìn)電機(jī)控制實(shí)驗(yàn)?zāi)K
Keil開發(fā)環(huán)境
STC-ISP程序下載工具
三、實(shí)驗(yàn)內(nèi)容
編制MCS-51程序使步進(jìn)電機(jī)按照規(guī)定的轉(zhuǎn)速和方向進(jìn)行旋轉(zhuǎn),并將已轉(zhuǎn)動(dòng)的步數(shù)顯示在數(shù)碼管上。
步進(jìn)電機(jī)的轉(zhuǎn)速分為兩檔,當(dāng)按下S1開關(guān)時(shí),加速旋轉(zhuǎn),速度從10轉(zhuǎn)/分加速到60轉(zhuǎn)/分。當(dāng)松開開關(guān)時(shí),減速旋轉(zhuǎn),速度恢復(fù)為10轉(zhuǎn)/分。當(dāng)按下S2開關(guān)時(shí),按照逆時(shí)針旋轉(zhuǎn);當(dāng)松開時(shí),按照順時(shí)針旋轉(zhuǎn)。
本程序要求使用定時(shí)器中斷來實(shí)現(xiàn),不準(zhǔn)使用程序延時(shí)的方式。
四、實(shí)驗(yàn)步驟
1、 預(yù)習(xí)
參考輔助材料,學(xué)習(xí)C51編程語言使用和步進(jìn)電機(jī)原理。
2、 簡(jiǎn)單程序錄入和調(diào)試
(1)關(guān)于C51的中斷
本程序需要使用定時(shí)器定時(shí),并使用中斷來同步。中斷程序的典型例子如下:
格式:void 函數(shù)名()interrupt 中斷號(hào) using 工作組
{
中斷服務(wù)程序內(nèi)容
}
注意:中斷不能返回任何值,所以前面是 void 后面是函數(shù)名,名字可以自己起,但不要與c語言的關(guān)鍵字相同;中斷函數(shù)不帶任何參數(shù),所以 函數(shù)名后面的()內(nèi)是 空的,中斷號(hào)是指單片機(jī)的幾個(gè)中斷源的序號(hào)。這個(gè)序號(hào)是單片機(jī)識(shí)別不同中斷的唯一標(biāo)志。所以一定要寫正確。
后面的using 工作組 是指這個(gè)這個(gè)中斷使用單片機(jī)內(nèi)存中 4 個(gè)工作寄存器的哪一組,c51 編譯后會(huì)自動(dòng)分配工作組,因此最后這句話我們通常省略不寫。
c51 中斷寫法實(shí)例:
void T1-time() interrupt 3
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
}
上面的意思是定時(shí)器 1 的中斷服務(wù)程序,定時(shí)器 1 的中斷服務(wù)序號(hào)是 3 ,因此我們要寫成 interrupt 3 ,服務(wù)程序的內(nèi)容是給 兩個(gè)初值寄存器裝入新值。。
寫中斷前的準(zhǔn)備:
A、TMOD 賦值 確定工作方式。T0 還是T1 的工作方式。
B、計(jì)算初值 裝入 TH0 TL0 或者 TH1 TL1
C、中斷方式時(shí) ,對(duì) IE 賦值,開放中斷。
D、使 TR0 和 TR1 置位,啟動(dòng)定時(shí)器/計(jì)數(shù)器 定時(shí)/計(jì)數(shù)。
(2)關(guān)于定時(shí)器中斷的賦值
使用定時(shí)器時(shí),首先應(yīng)由外部條件得到要定時(shí)的時(shí)間長(zhǎng)度t,如本實(shí)驗(yàn)中,就是根據(jù)要求的速度計(jì)算出的每一步之間的間隔。然后選擇適當(dāng)?shù)亩〞r(shí)器工作方式,去計(jì)算想要設(shè)定的計(jì)數(shù)器初值s,使用如下方程:
?。?定時(shí)器最大位數(shù) - s)× 定時(shí)周期 =t 【定時(shí)周期 = 12/CPU晶振頻率】
得到的s需要分成高8位和低8位,分別放入計(jì)數(shù)器THx和TLx中(x為0或1)。如果s為負(fù)數(shù),說明需要的定時(shí)時(shí)間太長(zhǎng),即使定時(shí)器的最大時(shí)間也無法滿足要求。這種情況下,需要加入軟件循環(huán)才能實(shí)現(xiàn)。我們可以將需要的定時(shí)時(shí)間分成n份,利用定時(shí)器達(dá)到t/n的時(shí)間長(zhǎng)度,然后在定時(shí)器處理程序中,累計(jì)某一變量,如果到達(dá)n,說明總的時(shí)間t已經(jīng)達(dá)到。
要想使用定時(shí)器中斷,除了上面的定時(shí)器初值設(shè)定外,還需要將其他相關(guān)的特殊功能寄存器也都設(shè)置好。如果使用方式0和方式1,不要忘記在計(jì)數(shù)結(jié)束后重新恢復(fù)計(jì)數(shù)器初值。
3、 程序調(diào)試
用單步、斷點(diǎn)、連續(xù)方式調(diào)試程序,觀察狀態(tài)指示燈及電機(jī)狀態(tài),檢查運(yùn)行結(jié)果。如果需要,可以將四個(gè)輸出信號(hào)的狀態(tài)同時(shí)輸出到P0口的某些位上,便于觀察。
4、 編寫程序,完成功能
五、實(shí)驗(yàn)原理
1、我們使用的單片機(jī)系統(tǒng)的頻率是12M;步進(jìn)電機(jī)轉(zhuǎn)動(dòng)一周需要24步。
2、本步進(jìn)電機(jī)實(shí)驗(yàn)板,使用FAN8200作為驅(qū)動(dòng)芯片。CPU通過如下4個(gè)引腳與FAN8200相連,即:
3、本實(shí)驗(yàn)使用簡(jiǎn)單的雙四拍工作模式即可,這也是FAN8200比較方便的工作方式。只要將CE1和CE2分別置為高,然后IN1和IN2按照預(yù)定的脈沖輸出,即01->11->10->00->01這個(gè)循環(huán)構(gòu)成一個(gè)方向旋轉(zhuǎn)的輸出脈沖,將此序列翻轉(zhuǎn),就是相反方向的輸出脈沖。
六、實(shí)驗(yàn)代碼
1 #include
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; //用于計(jì)已轉(zhuǎn)動(dòng)的步數(shù)
16 int flag=0; //用于給IN1、IN2傳值
17 //二極管顯示碼,存放在code區(qū)
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){ //顯示一個(gè)數(shù)字
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); //個(gè)位
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