微机原理实验报告
实验名称: 步进电机控制
院 系: 物理与机电工程学院
专业班级: 0 8电子信息工程
学 号: 2008041521
学生姓名: 刘新勇
指导教师:
完成时间: 2011年5月5日
报告成绩:
评阅意见:
评阅教师 日期
一、 实验目的
1、 掌握四相五线步进电机的工作原理
2、 以单四拍的方式用LPC2138与L297、L298控制步进电机
二、 实验原理
1、用软件的方式通过对P1_21与P1_22的控制,并通过L297、L298驱动5V直流步进电机,原理图如下:
2、同时用按键产生外部中断控制电机的转速与转向。转速的控制主要是脉冲的频率,为了控制的简单,可以直接利用软件延时的方法实现。
3、程序再增加上位机控制步进电机指令
4、程序流程图
三、 实验设备
微机、EasyARM2131-LYXY V1.14学习开发板
四、实验效果
上电时步进电机按初始化的速度转动,按下4个按键分别执行增、减速;正、反转,同时上位机显示控制指令。
五、实验总结
1、 此次实验由于不是精细控制步进电机的步进量,所以只用简单的延时程序就可以控制速度,但要注意延时变量的取值避免步进电机出现失步现象。
2、 写中断服务程序时记得清除相应的中断标志,且一定不要忘了VICVectAddr = 0x00;即通知VIC中断处理结束。一开始实验时由于少了此句,程序一直不正常。
七、程序清单
#include "config.h"
int DelayTime=60; //延时参数
typedef struct UartMode
{
uint8 datab; //字长度,5/6/7/8可选
uint8 stopb; //停止位,1/2可选
uint8 parity; //奇偶校验位,0:无校验;1:奇检验;2:偶检验
}UARTMODE;
uint8 rcv_buf; //UART0数据接收缓冲区
uint8 rcv_new; //接收数据标志
void delay(int dly)
{
int i,j;
for(i=0; i
115200))return(0);
if((set.datab<5)||(set.datab>8))return(0);
if((set.stopb==0)||(set.stopb>2))return(0);
if(set.parity>4)return(0);
//设置串口的波特率
U0LCR=0x80; //DLAB=1
bak=(Fpclk>>4)/baud;
U0DLM=bak>>8;
U0DLL=bak&0xff;
//设置串口模式
bak=set.datab-5; //设置字长
if(set.stopb==2)bak|=0x04; //判断是否为2位停止位
if(set.parity!=0)
{
set.parity=set.parity-1;
bak|=0x08;
}
bak|=set.parity<<4; //设置奇偶校验
U0LCR=bak;
return(1);
}
//中断初始化函数
void Int_Init(void)
{
EXTMODE=0x00; //设置外部中断为电平触发
IRQEnable(); //使能IRQ中断
VICIntSelect=0x00000000; //设置所有分配为IRQ中断
VICVectCntl4=0x20|0x0e; //分配外部中断4到向量中断0
VICVectCntl1=0x20|0x0f; //分配外部中断1到向量中断0
VICVectCntl2=0x20|0x10; //分配外部中断2到向量中断0
VICVectCntl3=0x20|0x11; //分配外部中断3到向量中断0
VICVectCntl0=0x20|0x06; //分配Uart0中断到向量中断0
//设置中断服务程序地址
VICVectAddr4=(uint32)IRQ_Eint0;
VICVectAddr1=(uint32)IRQ_Eint1;
VICVectAddr2=(uint32)IRQ_Eint2;
VICVectAddr3=(uint32)IRQ_Eint3;
VICVectAddr0=(uint32)IRQ_UART0;
EXTINT=0x0f; //清除所有外部中断标志
VICIntEnable=(1<<0x0e)|(1<<0x0f)|(1<<0x10)|(1<<0x11)|(1<<0x06);//使能所用到的中断
}
//工作模式设置函数
void SetWorkMode(char WorkMode)
{
//WorkMode:控制信号
// '+':加速 '-':减速 '<':逆时针 '>':顺时针
switch(WorkMode)
{
case '+':
if(DelayTime>20)
DelayTime=DelayTime-20; //减少延时,即加速
break;
case '-':
if(DelayTime<100)
DelayTime=DelayTime+20; //增加延时,即减速
break;
case '<':
IO0CLR=0x01<<21; //设置的步进电机的运转方向为逆时针
break;
case '>':
IO0SET=0x01<<21; //设置的步进电机的运转方向为顺时针
break;
default :break;
}
}
//外部中断0服务程序
void __irq IRQ_Eint0(void)
{
IO0CLR=0x01<<21; //设置的步进电机的运转方向为逆时针
while((EXTINT&0x01)!=0)
{
EXTINT=0x01; //清除中断标志
}
VICVectAddr=0;
}
//外部中断2服务程序
void __irq IRQ_Eint2(void)
{
if(DelayTime>20)
DelayTime=DelayTime-5; //减少延时,即加速
while((EXTINT&0x04)!=0)
{
EXTINT=0x04; //清除中断标志
}
VICVectAddr=0;
}
//外部中断1服务程序
void __irq IRQ_Eint1(void)
{
IO0SET=0x01<<21; //设置的步进电机的运转方向为顺时针
while((EXTINT&0x02)!=0)
{
EXTINT=0x02; //清除中断标志
}
VICVectAddr=0;
}
//外部中断3服务程序
void __irq IRQ_Eint3(void)
{
if(DelayTime<100)
DelayTime=DelayTime+5; //增加延时,即减速
while((EXTINT&0x08)!=0)
{
EXTINT=0x08; //清除中断标志
}
VICVectAddr=0;
}
//串口0接收中断服务程序
void __irq IRQ_UART0(void)
{
if((U0IIR&0x0f)==0x04)
rcv_new=1; //设置接收到新的数据标志
rcv_buf=U0RBR; //读取FIFO的数据,并清除中断
VICVectAddr=0;
}
int main (void)
{
UARTMODE set;
set.datab=8; //设置字长度为8位
set.stopb=1; //设置停止位为1位
set.parity=0; //设置检验方式为无校验
rcv_new=0; //接收数据标志初始化
PINSEL0=0x0005c0c5;
PINSEL1=0x00000301;
IO0DIR=0x03<<21; //设P0.21-P0.22为输出
UART0_Init(9600, set); //串口初始化
U0FCR=0x01; //使能FIFO,并设置触发点为1字节
U0IER=0x01; //允许RBR中断,即接收中断
Int_Init(); //中断初始化(外部中断、串口中断)
while(1)
{
if(rcv_new==1)
{
rcv_new=0;
SetWorkMode(rcv_buf);//根据输入控制信号改变步进电机的工作模式
UART0_SendByte(rcv_buf); //把键盘输入发回虚拟终端回显
}
IO0SET=0x01<<22;
delay(DelayTime);//DelayTime初始值设定为60
IO0CLR=0x01<<22;
delay(DelayTime);
}
return 0;
}