基于ARM的步進(jìn)電機(jī)控制示例(串口方式+中斷方式)
本設(shè)計(jì)可實(shí)現(xiàn)步進(jìn)電機(jī)的速度和方向控制。通過串口方式控制電機(jī)時(shí),只要在仿真過程中在虛擬終端(Virtual Terminal)輸入相應(yīng)的命令即可控制電機(jī)的運(yùn)轉(zhuǎn)。
本文引用地址:http://www.ex-cimer.com/article/201611/319082.htm
串口控制命令(雙引號(hào)內(nèi)字符,可自己定義)如下:
"<": 使電機(jī)逆時(shí)針方向轉(zhuǎn)動(dòng);
">": 使電機(jī)順時(shí)針方向轉(zhuǎn)動(dòng);
"+": 加速;
"-" : 減速。
如果讀者在仿真過程中不小心關(guān)閉了虛擬終端(Virtual Terminal),可以在調(diào)試(Debug)菜單下找到它。
整體電路連接如下圖所示:
如果讀者在實(shí)踐過程中出現(xiàn)電機(jī)運(yùn)轉(zhuǎn)不穩(wěn)定的情況可嘗試把電機(jī)的Maximum RPM設(shè)置為一個(gè)較大的數(shù)值,此處筆者設(shè)置為7200,如下圖所示:
附上本設(shè)計(jì)源代碼:
1 #include "config.h"
2
3 int DelayTime=60; //延時(shí)參數(shù)
4
5 typedef struct UartMode
6 {
7 uint8 datab; //字長度,5/6/7/8可選
8 uint8 stopb; //停止位,1/2可選
9 uint8 parity; //奇偶校驗(yàn)位,0:無校驗(yàn);1:奇檢驗(yàn);2:偶檢驗(yàn)
10 }UARTMODE;
11
12 uint8 rcv_buf; //UART0數(shù)據(jù)接收緩沖區(qū)
13 uint8 rcv_new; //接收數(shù)據(jù)標(biāo)志
14
15 //延時(shí)函數(shù)原型聲明
16 void delay(int dly);
17
18 //工作模式設(shè)置函數(shù)原型聲明
19 void SetWorkMode(char WorkMode);
20
21 //中斷服務(wù)程序原型聲明
22 void __irq IRQ_Eint0(void);
23 void __irq IRQ_Eint1(void);
24 void __irq IRQ_Eint2(void);
25 void __irq IRQ_Eint3(void);
26
27 //中斷初始化函數(shù)
28 void Int_Init(void);
29
30 //串口0接收中斷服務(wù)程序
31 void __irq IRQ_UART0(void);
32
33 //串口0數(shù)據(jù)發(fā)送函數(shù)
34 void UART0_SendByte(uint8 dat);
35
36 //串口0初始化函數(shù)
37 uint8 UART0_Init(uint32 baud, UARTMODE set);
38
39
40 //********************************************************************************************************
41 //主函數(shù)
42 int main (void)
43 {
44
45 UARTMODE set;
46
47 set.datab=8; //設(shè)置字長度為8位
48 set.stopb=1; //設(shè)置停止位為1位
49 set.parity=0; //設(shè)置檢驗(yàn)方式為無校驗(yàn)
50
51 rcv_new=0; //接收數(shù)據(jù)標(biāo)志初始化
52
53 //配置引腳功能
54 PINSEL0=0x0005c0c5;
55 PINSEL1=0x00000301;
56
57 IO0DIR=0x03<<21; //設(shè)P0.21-P0.22為輸出
58
59 UART0_Init(9600, set); //串口初始化
60 U0FCR=0x01; //使能FIFO,并設(shè)置觸發(fā)點(diǎn)為1字節(jié)
61 U0IER=0x01; //允許RBR中斷,即接收中斷
62
63 Int_Init(); //中斷初始化(外部中斷、串口中斷)
64
65 while(1)
66 {
67 if(rcv_new==1)
68 {
69 rcv_new=0;
70 SetWorkMode(rcv_buf); //根據(jù)輸入的控制信號(hào)改變步進(jìn)電機(jī)的工作模式
71 UART0_SendByte(rcv_buf); //把鍵盤輸入發(fā)回虛擬終端回顯
72 }
73 //模擬脈沖信號(hào)驅(qū)動(dòng)步進(jìn)電機(jī)轉(zhuǎn)動(dòng)
74 IO0SET=0x01<<22;
75 delay(DelayTime);
76 IO0CLR=0x01<<22;
77 delay(DelayTime);
78 }
79 return 0;
80 }
81
82 //********************************************************************************************************
83 //延時(shí)函數(shù)
84 void delay(int dly)
85 {
86 int i,j;
87 for(i=0; i 88 for(j=0; j<1200; j++);
89
90 }
91
92 //********************************************************************************************************
93 //工作模式設(shè)置函數(shù)
94 void SetWorkMode(char WorkMode)
95 {
96 //WorkMode:控制信號(hào)
97 // +:加速 -:減速 <:逆時(shí)針 >:順時(shí)針
98 switch(WorkMode)
99 {
100 case +:
101 if(DelayTime>20)
102 DelayTime=DelayTime-20; //減少延時(shí),即加速
103 break;
104 case -:
105 if(DelayTime<100)
106 DelayTime=DelayTime+20; //增加延時(shí),即減速
107 break;
108 case <:
109 IO0CLR=0x01<<21; //設(shè)置的步進(jìn)電機(jī)的運(yùn)轉(zhuǎn)方向?yàn)槟鏁r(shí)針
110 break;
111 case >:
112 IO0SET=0x01<<21; //設(shè)置的步進(jìn)電機(jī)的運(yùn)轉(zhuǎn)方向?yàn)轫槙r(shí)針
113 break;
114 default :break;
115 }
116 }
117
118 //********************************************************************************************************
119 //外部中斷0服務(wù)程序
120 void __irq IRQ_Eint0(void)
121 {
122 IO0CLR=0x01<<21; //設(shè)置的步進(jìn)電機(jī)的運(yùn)轉(zhuǎn)方向?yàn)槟鏁r(shí)針
123
124 while((EXTINT&0x01)!=0)
125 {
126 EXTINT=0x01; //清除中斷標(biāo)志
127 }
128 VICVectAddr=0;
129 }
130
131 //********************************************************************************************************
132 //外部中斷1服務(wù)程序
133 void __irq IRQ_Eint1(void)
134 {
135 IO0SET=0x01<<21; //設(shè)置的步進(jìn)電機(jī)的運(yùn)轉(zhuǎn)方向?yàn)轫槙r(shí)針
136
137 while((EXTINT&0x02)!=0)
138 {
139 EXTINT=0x02; //清除中斷標(biāo)志
140 }
141 VICVectAddr=0;
142 }
143
144 //********************************************************************************************************
145 //外部中斷2服務(wù)程序
146 void __irq IRQ_Eint2(void)
147 {
148 if(DelayTime>20)
149 DelayTime=DelayTime-5; //減少延時(shí),即加速
150
151 while((EXTINT&0x04)!=0)
152 {
153 EXTINT=0x04; //清除中斷標(biāo)志
154 }
155 VICVectAddr=0;
156 }
157
158 //********************************************************************************************************
159 //外部中斷3服務(wù)程序
160 void __irq IRQ_Eint3(void)
161 {
162 if(DelayTime<100)
163 DelayTime=DelayTime+5; //增加延時(shí),即減速
164 while((EXTINT&0x08)!=0)
165 {
166 EXTINT=0x08; //清除中斷標(biāo)志
167 }
168 VICVectAddr=0;
169 }
170
171 //********************************************************************************************************
172 //中斷初始化函數(shù)
173 void Int_Init(void)
174 {
175 EXTMODE=0x00; //設(shè)置外部中斷為電平觸發(fā)
176
177 IRQEnable(); //使能IRQ中斷
178
179 VICIntSelect=0x00000000; //設(shè)置所有分配為IRQ中斷
180
181 VICVectCntl4=0x20|0x0e; //分配外部中斷4到向量中斷0
182 VICVectCntl1=0x20|0x0f; //分配外部中斷1到向量中斷0
183 VICVectCntl2=0x20|0x10; //分配外部中斷2到向量中斷0
184 VICVectCntl3=0x20|0x11; //分配外部中斷3到向量中斷0
185 VICVectCntl0=0x20|0x06; //分配Uart0中斷到向量中斷0
186
187
188 //設(shè)置中斷服務(wù)程序地址
189 VICVectAddr4=(uint32)IRQ_Eint0;
190 VICVectAddr1=(uint32)IRQ_Eint1;
191 VICVectAddr2=(uint32)IRQ_Eint2;
192 VICVectAddr3=(uint32)IRQ_Eint3;
193 VICVectAddr0=(uint32)IRQ_UART0;
194
195 EXTINT=0x0f; //清除所有外部中斷標(biāo)志
196
197 VICIntEnable=(1<<0x0e)|(1<<0x0f)|(1<<0x10)|(1<<0x11)|(1<<0x06); //使能所用到的中斷
198 }
199
200 //********************************************************************************************************
201 //串口0接收中斷服務(wù)程序
202 void __irq IRQ_UART0(void)
203 {
204 if((U0IIR&0x0f)==0x04)
205 rcv_new=1; //設(shè)置接收到新的數(shù)據(jù)標(biāo)志
206
207 rcv_buf=U0RBR; //讀取FIFO的數(shù)據(jù),并清除中斷
208
209 VICVectAddr=0;
210 }
211
212 //********************************************************************************************************
213 //串口0數(shù)據(jù)發(fā)送函數(shù)
214 void UART0_SendByte(uint8 dat)
215 {
216 U0THR=dat;
217 while((U0LSR&0x20)==0); //等待數(shù)據(jù)發(fā)送完畢
218 }
219
220 //********************************************************************************************************
221 //串口0初始化函數(shù)
222 uint8 UART0_Init(uint32 baud, UARTMODE set)
223 {
224 uint32 bak;
225
226 //參數(shù)過濾
227 if((baud==0)||(baud>115200))return(0);
228 if((set.datab<5)||(set.datab>8))return(0);
229 if((set.stopb==0)||(set.stopb>2))return(0);
230 if(set.parity>4)return(0);
231
232 //設(shè)置串口的波特率
233 U0LCR=0x80; //DLAB=1
234 bak=(Fpclk>>4)/baud;
235 U0DLM=bak>>8;
236 U0DLL=bak&0xff;
237
238 //設(shè)置串口模式
239 bak=set.datab-5; //設(shè)置字長
240 if(set.stopb==2)bak|=0x04; //判斷是否為2位停止位
241
242 if(set.parity!=0)
243 {
244 set.parity=set.parity-1;
245 bak|=0x08;
246 }
247 bak|=set.parity<<4; //設(shè)置奇偶校驗(yàn)
248
249 U0LCR=bak;
250
251 return(1);
252 }
253
254
2
3
4
5 typedef struct UartMode
6 {
7 uint8 datab; //字長度,5/6/7/8可選
8
9
10
11
12 uint8 rcv_buf; //UART0數(shù)據(jù)接收緩沖區(qū)
13
14
15
16
17
18
19
20
21
22 void __irq IRQ_Eint0(void);
23 void __irq IRQ_Eint1(void);
24 void __irq IRQ_Eint2(void);
25 void __irq IRQ_Eint3(void);
26
27 //中斷初始化函數(shù)
28 void Int_Init(void);
29
30 //串口0接收中斷服務(wù)程序
31 void __irq IRQ_UART0(void);
32
33 //串口0數(shù)據(jù)發(fā)送函數(shù)
34 void UART0_SendByte(uint8 dat);
35
36 //串口0初始化函數(shù)
37 uint8 UART0_Init(uint32 baud, UARTMODE set);
38
39
40 //********************************************************************************************************
41 //主函數(shù)
42 int main (void)
43 {
44
45 UARTMODE set;
46
47 set.datab=8; //設(shè)置字長度為8位
48 set.stopb=1; //設(shè)置停止位為1位
49 set.parity=0; //設(shè)置檢驗(yàn)方式為無校驗(yàn)
50
51 rcv_new=0; //接收數(shù)據(jù)標(biāo)志初始化
52
53 //配置引腳功能
54 PINSEL0=0x0005c0c5;
55 PINSEL1=0x00000301;
56
57 IO0DIR=0x03<<21; //設(shè)P0.21-P0.22為輸出
58
59 UART0_Init(9600, set); //串口初始化
60 U0FCR=0x01; //使能FIFO,并設(shè)置觸發(fā)點(diǎn)為1字節(jié)
61 U0IER=0x01; //允許RBR中斷,即接收中斷
62
63 Int_Init(); //中斷初始化(外部中斷、串口中斷)
64
65 while(1)
66 {
67 if(rcv_new==1)
68 {
69 rcv_new=0;
70 SetWorkMode(rcv_buf); //根據(jù)輸入的控制信號(hào)改變步進(jìn)電機(jī)的工作模式
71 UART0_SendByte(rcv_buf); //把鍵盤輸入發(fā)回虛擬終端回顯
72 }
73 //模擬脈沖信號(hào)驅(qū)動(dòng)步進(jìn)電機(jī)轉(zhuǎn)動(dòng)
74 IO0SET=0x01<<22;
75 delay(DelayTime);
76 IO0CLR=0x01<<22;
77 delay(DelayTime);
78 }
79 return 0;
80 }
81
82 //********************************************************************************************************
83 //延時(shí)函數(shù)
84 void delay(int dly)
85 {
86 int i,j;
87 for(i=0; i
89
90 }
91
92 //********************************************************************************************************
93 //工作模式設(shè)置函數(shù)
94 void SetWorkMode(char WorkMode)
95 {
96 //WorkMode:控制信號(hào)
97 // +:加速 -:減速 <:逆時(shí)針 >:順時(shí)針
98 switch(WorkMode)
99 {
100 case +:
101 if(DelayTime>20)
102 DelayTime=DelayTime-20; //減少延時(shí),即加速
103 break;
104 case -:
105 if(DelayTime<100)
106 DelayTime=DelayTime+20; //增加延時(shí),即減速
107 break;
108 case <:
109 IO0CLR=0x01<<21; //設(shè)置的步進(jìn)電機(jī)的運(yùn)轉(zhuǎn)方向?yàn)槟鏁r(shí)針
110 break;
111 case >:
112 IO0SET=0x01<<21; //設(shè)置的步進(jìn)電機(jī)的運(yùn)轉(zhuǎn)方向?yàn)轫槙r(shí)針
113 break;
114 default :break;
115 }
116 }
117
118 //********************************************************************************************************
119 //外部中斷0服務(wù)程序
120 void __irq IRQ_Eint0(void)
121 {
122 IO0CLR=0x01<<21; //設(shè)置的步進(jìn)電機(jī)的運(yùn)轉(zhuǎn)方向?yàn)槟鏁r(shí)針
123
124 while((EXTINT&0x01)!=0)
125 {
126 EXTINT=0x01; //清除中斷標(biāo)志
127 }
128 VICVectAddr=0;
129 }
130
131 //********************************************************************************************************
132 //外部中斷1服務(wù)程序
133 void __irq IRQ_Eint1(void)
134 {
135 IO0SET=0x01<<21; //設(shè)置的步進(jìn)電機(jī)的運(yùn)轉(zhuǎn)方向?yàn)轫槙r(shí)針
136
137 while((EXTINT&0x02)!=0)
138 {
139 EXTINT=0x02; //清除中斷標(biāo)志
140 }
141 VICVectAddr=0;
142 }
143
144 //********************************************************************************************************
145 //外部中斷2服務(wù)程序
146 void __irq IRQ_Eint2(void)
147 {
148 if(DelayTime>20)
149 DelayTime=DelayTime-5; //減少延時(shí),即加速
150
151 while((EXTINT&0x04)!=0)
152 {
153 EXTINT=0x04; //清除中斷標(biāo)志
154 }
155 VICVectAddr=0;
156 }
157
158 //********************************************************************************************************
159 //外部中斷3服務(wù)程序
160 void __irq IRQ_Eint3(void)
161 {
162 if(DelayTime<100)
163 DelayTime=DelayTime+5; //增加延時(shí),即減速
164 while((EXTINT&0x08)!=0)
165 {
166 EXTINT=0x08; //清除中斷標(biāo)志
167 }
168 VICVectAddr=0;
169 }
170
171 //********************************************************************************************************
172 //中斷初始化函數(shù)
173 void Int_Init(void)
174 {
175 EXTMODE=0x00; //設(shè)置外部中斷為電平觸發(fā)
176
177 IRQEnable(); //使能IRQ中斷
178
179 VICIntSelect=0x00000000; //設(shè)置所有分配為IRQ中斷
180
181 VICVectCntl4=0x20|0x0e; //分配外部中斷4到向量中斷0
182 VICVectCntl1=0x20|0x0f; //分配外部中斷1到向量中斷0
183 VICVectCntl2=0x20|0x10; //分配外部中斷2到向量中斷0
184 VICVectCntl3=0x20|0x11; //分配外部中斷3到向量中斷0
185 VICVectCntl0=0x20|0x06; //分配Uart0中斷到向量中斷0
186
187
188 //設(shè)置中斷服務(wù)程序地址
189 VICVectAddr4=(uint32)IRQ_Eint0;
190 VICVectAddr1=(uint32)IRQ_Eint1;
191 VICVectAddr2=(uint32)IRQ_Eint2;
192 VICVectAddr3=(uint32)IRQ_Eint3;
193 VICVectAddr0=(uint32)IRQ_UART0;
194
195 EXTINT=0x0f; //清除所有外部中斷標(biāo)志
196
197 VICIntEnable=(1<<0x0e)|(1<<0x0f)|(1<<0x10)|(1<<0x11)|(1<<0x06); //使能所用到的中斷
198 }
199
200 //********************************************************************************************************
201 //串口0接收中斷服務(wù)程序
202 void __irq IRQ_UART0(void)
203 {
204 if((U0IIR&0x0f)==0x04)
205 rcv_new=1; //設(shè)置接收到新的數(shù)據(jù)標(biāo)志
206
207 rcv_buf=U0RBR; //讀取FIFO的數(shù)據(jù),并清除中斷
208
209 VICVectAddr=0;
210 }
211
212 //********************************************************************************************************
213 //串口0數(shù)據(jù)發(fā)送函數(shù)
214 void UART0_SendByte(uint8 dat)
215 {
216 U0THR=dat;
217 while((U0LSR&0x20)==0); //等待數(shù)據(jù)發(fā)送完畢
218 }
219
220 //********************************************************************************************************
221 //串口0初始化函數(shù)
222 uint8 UART0_Init(uint32 baud, UARTMODE set)
223 {
224 uint32 bak;
225
226 //參數(shù)過濾
227 if((baud==0)||(baud>115200))return(0);
228 if((set.datab<5)||(set.datab>8))return(0);
229 if((set.stopb==0)||(set.stopb>2))return(0);
230 if(set.parity>4)return(0);
231
232 //設(shè)置串口的波特率
233 U0LCR=0x80; //DLAB=1
234 bak=(Fpclk>>4)/baud;
235 U0DLM=bak>>8;
236 U0DLL=bak&0xff;
237
238 //設(shè)置串口模式
239 bak=set.datab-5; //設(shè)置字長
240 if(set.stopb==2)bak|=0x04; //判斷是否為2位停止位
241
242 if(set.parity!=0)
243 {
244 set.parity=set.parity-1;
245 bak|=0x08;
246 }
247 bak|=set.parity<<4; //設(shè)置奇偶校驗(yàn)
248
249 U0LCR=bak;
250
251 return(1);
252 }
253
254
評論