本设计实现了通过ARM对步进电机(Motor)的控制。控制方式有两种,一种是通过外部中断,另外一种是通过串口发送命令进行控制。

  本设计可实现步进电机的速度和方向控制。通过串口方式控制电机时,只要在仿真过程中在虚拟终端(Virtual Terminal)输入相应的命令即可控制电机的运转。

  

vesc电机串口配置_vesc电机串口配置

                                           虚拟终端

 

  串口控制命令(双引号内字符,可自己定义)如下:

  "<": 使电机逆时针方向转动;

  ">": 使电机顺时针方向转动;

  "+": 加速;

  "-" : 减速。

  

  如果读者在仿真过程中不小心关闭了虚拟终端(Virtual Terminal),可以在调试(Debug)菜单下找到它。

  

  整体电路连接如下图所示:

vesc电机串口配置_服务程序_02

 

  如果读者在实践过程中出现电机运转不稳定的情况可尝试把电机的Maximum RPM设置为一个较大的数值,此处笔者设置为7200,如下图所示:

vesc电机串口配置_服务程序_03

 

 

  附上本设计源代码:

1 #include "config.h"
  2 
  3  int DelayTime=60;    //延时参数
  4  
  5 typedef struct UartMode
  6 {
  7     uint8 datab;        //字长度,5/6/7/8可选
  8      uint8 stopb;        //停止位,1/2可选
  9      uint8 parity;        //奇偶校验位,0:无校验;1:奇检验;2:偶检验
 10  }UARTMODE;
 11 
 12 uint8 rcv_buf;            //UART0数据接收缓冲区
 13  uint8 rcv_new;            //接收数据标志
 14 
 15  //延时函数原型声明
 16  void delay(int dly);
 17 
 18  //工作模式设置函数原型声明
 19  void SetWorkMode(char WorkMode);
 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 //中断初始化函数
 28 void Int_Init(void);
 29 
 30 //串口0接收中断服务程序
 31 void __irq IRQ_UART0(void);
 32 
 33 //串口0数据发送函数
 34 void UART0_SendByte(uint8 dat);
 35 
 36 //串口0初始化函数
 37 uint8 UART0_Init(uint32 baud, UARTMODE set);
 38 
 39 
 40 //********************************************************************************************************
 41 //主函数
 42 int main (void)
 43 {
 44 
 45     UARTMODE set;
 46     
 47     set.datab=8;    //设置字长度为8位
 48     set.stopb=1;    //设置停止位为1位
 49     set.parity=0;    //设置检验方式为无校验
 50     
 51     rcv_new=0;        //接收数据标志初始化
 52 
 53     //配置引脚功能
 54     PINSEL0=0x0005c0c5; 
 55     PINSEL1=0x00000301;        
 56     
 57     IO0DIR=0x03<<21;            //设P0.21-P0.22为输出
 58     
 59     UART0_Init(9600, set);        //串口初始化
 60     U0FCR=0x01;                    //使能FIFO,并设置触发点为1字节
 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);        //根据输入的控制信号改变步进电机的工作模式
 71             UART0_SendByte(rcv_buf);    //把键盘输入发回虚拟终端回显
 72         }
 73         //模拟脉冲信号驱动步进电机转动
 74         IO0SET=0x01<<22;                
 75         delay(DelayTime);
 76         IO0CLR=0x01<<22;
 77         delay(DelayTime);
 78     }
 79     return 0;
 80 }
 81 
 82 //********************************************************************************************************
 83 //延时函数
 84 void delay(int dly)
 85 {
 86     int i,j;
 87     for(i=0; i<dly; i++)
 88         for(j=0; j<1200; j++);
 89         
 90 }
 91 
 92 //********************************************************************************************************
 93 //工作模式设置函数
 94 void SetWorkMode(char WorkMode)
 95 {
 96     //WorkMode:控制信号     
 97     //    '+':加速    '-':减速    '<':逆时针    '>':顺时针
 98     switch(WorkMode)
 99     {
100         case '+':
101                 if(DelayTime>20)
102                 DelayTime=DelayTime-20;        //减少延时,即加速
103                 break;
104         case '-':
105                 if(DelayTime<100)
106                 DelayTime=DelayTime+20;        //增加延时,即减速
107                 break;
108         case '<':
109                 IO0CLR=0x01<<21;            //设置的步进电机的运转方向为逆时针
110                 break;
111         case '>':
112                 IO0SET=0x01<<21;            //设置的步进电机的运转方向为顺时针
113                 break;
114         default :break;
115     }
116 }
117 
118 //********************************************************************************************************
119 //外部中断0服务程序
120 void __irq IRQ_Eint0(void)
121 {
122     IO0CLR=0x01<<21;        //设置的步进电机的运转方向为逆时针
123     
124     while((EXTINT&0x01)!=0)
125     {
126         EXTINT=0x01;        //清除中断标志
127     }
128     VICVectAddr=0;
129 }
130 
131 //********************************************************************************************************
132 //外部中断1服务程序
133 void __irq IRQ_Eint1(void)
134 {
135     IO0SET=0x01<<21;        //设置的步进电机的运转方向为顺时针
136 
137     while((EXTINT&0x02)!=0)
138     {
139         EXTINT=0x02;        //清除中断标志
140     }
141     VICVectAddr=0;
142 }
143 
144 //********************************************************************************************************
145 //外部中断2服务程序
146 void __irq IRQ_Eint2(void)
147 {
148     if(DelayTime>20)
149     DelayTime=DelayTime-5;        //减少延时,即加速
150     
151     while((EXTINT&0x04)!=0)
152     {
153         EXTINT=0x04;            //清除中断标志
154     }
155     VICVectAddr=0;
156 }
157 
158 //********************************************************************************************************
159 //外部中断3服务程序
160 void __irq IRQ_Eint3(void)
161 {
162     if(DelayTime<100)
163     DelayTime=DelayTime+5;        //增加延时,即减速
164     while((EXTINT&0x08)!=0)
165     {
166         EXTINT=0x08;            //清除中断标志
167     }
168     VICVectAddr=0;
169 }
170 
171 //********************************************************************************************************
172 //中断初始化函数
173 void Int_Init(void)
174 {
175     EXTMODE=0x00;        //设置外部中断为电平触发
176     
177     IRQEnable();        //使能IRQ中断
178     
179     VICIntSelect=0x00000000;    //设置所有分配为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     //设置中断服务程序地址
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;    //清除所有外部中断标志
196     
197     VICIntEnable=(1<<0x0e)|(1<<0x0f)|(1<<0x10)|(1<<0x11)|(1<<0x06);    //使能所用到的中断
198 }
199 
200 //********************************************************************************************************
201 //串口0接收中断服务程序
202 void __irq IRQ_UART0(void)
203 {
204     if((U0IIR&0x0f)==0x04)
205         rcv_new=1;                //设置接收到新的数据标志
206     
207     rcv_buf=U0RBR;                //读取FIFO的数据,并清除中断
208     
209     VICVectAddr=0;
210 }
211 
212 //********************************************************************************************************
213 //串口0数据发送函数
214 void UART0_SendByte(uint8 dat)
215 {
216     U0THR=dat;
217     while((U0LSR&0x20)==0);        //等待数据发送完毕
218 }
219 
220 //********************************************************************************************************
221 //串口0初始化函数
222 uint8 UART0_Init(uint32 baud, UARTMODE set)
223 {
224     uint32 bak;
225     
226     //参数过滤
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     //设置串口的波特率
233     U0LCR=0x80;                        //DLAB=1
234     bak=(Fpclk>>4)/baud;
235     U0DLM=bak>>8;
236     U0DLL=bak&0xff;
237     
238     //设置串口模式
239     bak=set.datab-5;                //设置字长
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;                //设置奇偶校验
248     
249     U0LCR=bak;
250     
251     return(1);
252 }
253 
254 /*********************************************************************************************************
255 **                            End Of File
256 ********************************************************************************************************/

 

  本设计源程序、电路图及HEX文件

  Motor.7z