基于ARM的步进电机控制课程设计Word文档下载推荐.docx
《基于ARM的步进电机控制课程设计Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《基于ARM的步进电机控制课程设计Word文档下载推荐.docx(18页珍藏版)》请在冰豆网上搜索。
第二种方案中采用定时器定时中断的方式,只需要几条简单的指令就可以产生具有一定
频率和数目的脉冲信号,而且在整个脉冲产生过程中,CPU可用来处理其他工作,大大
提高了系统的实时处理能力。
考虑到系统的实时性及程序的繁简程度我选择了第二种方案。
3、硬件电路
3.1硬件结构
(1)EasyARM2138开发板是广州周立功公司设计的EasyARM系列开发套件之一,采用了PHILIPS公司基于ARM7TDMI-S核、单电源供电、LQFP64封装的LPC2138,具有JTAG
仿真调试、ISP编程等功能。
开发板上提供了一些键盘、LED、蜂鸣器等常用功能部件,还具有RS232接口电路、I2C
存储器电路。
另外,用户也可以更换兼容的CPU进行仿真调试,如LPC2132、LPC2138、
LPC2142等。
灵活的跳线组合(开发板内使用的所有I/O均可断开连接),还有用户I/O接
口,极大地方便了用户进行32位ARM嵌入式系统的开发实验。
(2)定时器
(3)中断
LPC2138通过向量中断控制器(VIC)管理中断。
外设中断信号需要经过2个开关才能
到达ARM内核,真正产生异常,逻辑示意图如下图所示。
如果在VIC中使能了相应外
设的中断,外设中断才能到达VIC并向内核发送中断请求;
只有使能了内核中断IRQ或者
FIQ,内核才能真正产生异常。
硬件图如下
中断的过程示意图如下:
(4)按键的连接图
不按下时为高电平,按下时变为低电平。
(5)UART0
特性:
管脚描述:
(6)步进电机接口
由于LPC2138的GPIO驱动能力有限,必须通过ULN2003达林顿集成驱动芯片驱动步进电机,在步进电机和驱动电路间连接了电阻,防止控制紊乱而造成的电机损坏。
3.2器件连接说明
(1)在EasyARM2138开发板上,当跳线JP6分别选择TXD0和RXD0端时方可进行UART0通信实验。
(2)KEY1连接P0.16;
KEY2连接P0.17;
KEY3连接P0.18,KEY4连接P0.19,KEY5连接P0.20,KEY6连接P0.21。
(3)步进电机的四个输入端口分别接EasyARM2138开发板上P2.2~P2.5四个端口。
4、软件设计
系统软件采用C语言编程,程序详情请参见附录。
程序的流程图如下:
否
是
是
否
4、调试
按照器件连接说明连接好EasyARM2131开发板上的跳线,然后将步进电机与EasyARM2131开发板连接上。
运行程序,开始调试。
在一开始的时候,由于用定时器设置的中断时间太长导致看不见电机有明显的转动。
通过修改定时时间,渐渐地电机转动变得明显了。
然后测试按键功能时发现,案件的检测不够灵敏,有时候需要按几下才能检测到,后来经过修改延时消抖的时间,将其变短且在每次按下按键时不急于松开而保持一会儿,这样按键检测变得较为灵敏了。
在调试中发现:
单双八拍和双四拍要比单四拍的转动更加有效。
单四拍模式的时候电机只是震动并没有转动,用肉眼观察不到转速的快慢,故最后舍弃了这种模式。
调试的最终结果是:
程序开始时电机进入模式0,如果没有按键按下则一直保持模式0。
当有按键按下时,且按键为KEY1~KEY4则电机根据不同按键的按下进入不同的转动模式(KEY1对应模式0:
八拍正转,KEY2对应模式1:
八拍反转,KEY3对应模式2:
双四拍正转,KEY4对应模式3:
双四拍反转)。
当按键KEY5按下时,电机转速变慢,且随着KEY5按下次数的增多电机逐渐变慢直至停止;
当按键KEY6按下时,电机转速变快,且随着KEY5按下次数的增多电机逐渐变快。
同时在上位机上可以看见当前的转速。
5、课程设计体会
一方面,通过这一周的课程设计,我对课本上关于LPC2138的硬件结构的知识有了更加深刻的理解,而且对其用法掌握得更加熟练。
在课程设计过程中,能够不断地发现问题,并想办法解决,如此提高了我自己解决问题的能力。
在编写程序方面,我对ARM7编程结构和技巧也有了深刻的理解和领会。
此次课程设计还让我知道什么是实时系统以及如何构建一个简单的实时系统。
现在我已经基本掌握了构建实时系统的方法。
还有我明白了流程图的重要性,以前在编程的时候,我从不写流程图,直接开始写程序,这样出现了不该出现的问题。
但这次课程设计时,我试着先写出流程图然后按照流程图编写程序,结果错误少了很多,即使有错误只要根据流程图一查就知道错在哪里,这让我节省了大量的时间和精力。
所以我认识到,以后要编写程序时,先写流程图是很有必要的。
另一方面,我感觉这一周的课程设计我自己的效率太低。
有时候被一些问题困惑了很久,但经过老师的指点,我才恍然大悟,原来只要换个方式思考问题就能想到很好的方法。
6、参考文献
[1]周立功.《深入浅出ARM7——LPC213X/214X(上册)》[M].北京:
北京航空航天大学出版社,2008:
146-175,226-240,275-286.
[2]周立功.《ARM嵌入式系统实验教程(三)》[M].北京:
北京航空航天大学出版社,
2005:
134-140.
[3]冷洪滨,邬义杰.基于计数器/定时器的步进电机可编程控制接口电路设计[J]北京:
组合机床与自动化加工技术,2004.
[4]周明德.微型计算机硬件软件及其应用.北京:
清华大学出版社,1993.
附录:
实训程序
#include"
config.h"
#defineHC595_CS(1<
<
29)//P0.29口为74HC595的片选
#defineLED11<
18//P1.18
#defineLED21<
19//P1.19
#defineLED31<
20//P1.20
#defineLED41<
21//P1.21
#definebj_qd0x0f<
22//步进电机驱动脚p1.22~p1.25
uint32bj[8]={1<
22,3<
22,1<
23,3<
23,1<
24,3<
24,1<
25,9<
22};
//0A,1AB2B3BC4C5CD6D7DA
constuint32KEY1=1<
16;
//P0.16连接KEY1
constuint32KEY2=1<
17;
//P0.17连接KEY1
constuint32KEY3=1<
18;
//P0.18连接KEY1
constuint32KEY4=1<
19;
//P0.19连接KEY1
constuint32KEY5=1<
20;
//P0.20连接KEY1
constuint32KEY6=1<
21;
//P0.21连接KEY1
uint8i,n=0,t=0,m=20,cnt=0;
uint8bj_mod=0;
//0-八拍zh正转,1-八拍反转,2-双四拍正转,3-双四拍反转/********************************************************************
**函数名称:
DelayNS()
**函数功能:
长软件延时
**入口参数:
dly延时参数,值越大,延时越久
**出口参数:
无
********************************************************************/
voidDelayNS(uint32dly)
{
uint32i;
for(;
dly>
0;
dly--)
for(i=0;
i<
50000;
i++);
}
#defineUART_BPS115200//通讯波特率115200
/********************************************************************
**函数名称:
UART0_Init()
**函数功能:
初始化串口0:
波特率115200,8位数据位,1位停止位,无奇偶校验。
**入口参数:
**出口参数:
*******************************************************************/
voidUART0_Init(void)
{
uint16Fdiv;
U0LCR=0x83;
//DLAB=1
Fdiv=(Fpclk/16)/UART_BPS;
U0DLM=Fdiv/256;
U0DLL=Fdiv%256;
U0LCR=0x03;
UART0_SendByte()
向串口发送字节数据,并等待数据发送完毕。
data要发送的数据
voidUART0_SendByte(uint8data)
U0THR=data;
while((U0LSR&
0x40)==0);
//等待数据发送完毕
PC_DispChar()
向PC机发送显示字符。
x显示字符的横坐标
**y显示字符的纵坐标
**chr显示的字符,不能为ff
**color显示的状态,包括前景色、背景色、闪烁位。
与DOS字符显示一样:
0~3,前景色,4~6,背景色,7,闪烁位。
无
voidPC_DispChar(uint8x,uint8y,uint8chr,uint8color)
UART0_SendByte(0xff);
//起始字符
UART0_SendByte(x);
UART0_SendByte(y);
UART0_SendByte(chr);
UART0_SendByte(color);
ISendStr()
向上位机发送字符串。
**与DOS字符显示一样:
**str要发送的字符串,以'
\0'
结束
voidISendStr(uint8x,uint8y,uint8color,char*str)
while
(1)
{
if(*str=='
)break;
//结束字符
PC_DispChar(x++,y,*str++,color);
if(x>
=80)
{
x=0;
y++;
}
}
/**********************************************************************函数名称:
MSPI_Init()
初始化SPI接口,设置为主机。
voidMSPI_Init(void)
PINSEL0=(PINSEL0&
(~(0xFF<
8)))|(0x55<
8);
SPCCR=0x52;
//设置SPI时钟分频
SPCR=(0<
3)|//CPHA=0,数据在SCK的第一个时钟沿采样
(1<
4)|//CPOL=1,SCK为低有效
5)|//MSTR=1,SPI处于主模式
(0<
6)|//LSBF=0,SPI数据传输MSB(位7)在先
7);
//SPIE=0,SPI中断被禁止
/*******************************************************************
MSPI_SendData()
向SPI总线发送数据
data待发送的数据
返回值为读取的数据
uint8MSPI_SendData(uint8data)
IOCLR=HC595_CS;
//片选74HC595
SPI_SPDR=data;
while(0==(SPI_SPSR&
0x80));
//等待SPIF置位,即等待数据发送完毕
IOSET=HC595_CS;
return(SPI_SPDR);
/*此表为LED0~F以及L、P的字模*/
uint8constDISP_TAB[10]={
//0123456789
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
qudong()
驱动步进电机转动
voidqudong()
IO1SET=0x0f<
22;
//不输出
switch(bj_mod)
case0:
//八拍正转
IO1CLR=bj[cnt%8];
break;
case1:
//八拍反转
IO1CLR=bj[7-(cnt%8)];
case2:
//双四拍正转
IO1CLR=bj[(cnt%4)*2+1];
case3:
//双四拍反转
IO1CLR=bj[7-(cnt%4)*2];
default:
break;
T0IR=0x01;
/*清除中断标志*/
VICVectAddr=0x00;
/*通知VIC中断处理结束*/
IRQ_Timer0()
定时器0中断服务程序,定时调用qudong()程序,使步进电机按节拍转动。
void__irqIRQ_Timer0(void)
t++;
cnt++;
qudong();
MSPI_SendData(DISP_TAB[i]);
//发送显示
main()
程序初始化,AD采样和按键调节电机转速,通过串口向上位机发送显示数据。
**调试说明:
需要将跳线JP6分别选择TXD0和RXD0端
**KEY1~KEY6连接P0.16~P0.21,步进电机四个输入端分别接P1.22~P1.25。
uint8rcv_data;
intmain(void)
uint32ADC_Data,temp,zhuansu=100,zhuansu1=100,zhuansu2=200;
uint32bapaizhengzhuan,bapaifanzhuan,shsipaizhengzhuan,shsipaifanzhuan;
charstr[20];
PINSEL0=0x00005505;
//设置SPI管脚连接
PINSEL1=0x10000000;
//PINSEL1=1<
28;
//P0.30连接到AD0.3
IODIR=HC595_CS;
PINSEL2=PINSEL2&
(~0x08);
//P1[25:
16]连接GPIO
IO1DIR=bj_qd;
//设置bjdj_qd控制口为输出
UART0_Init();
MSPI_Init();
//初始化SPI
IRQEnable();
/*IRQ中断使能*/
/*定时器0初始化*/
T0TC=0;
/*定时器设置为0*/
T0PR=0;
/*时钟不分频*/
T0MCR=0x03;
/*设置T0MR0匹配后复位T0TC,并产生中断标志*/
T0MR0=Fpclk/zhuansu;
/*0.5秒钟定时*/
T0TCR=0x01;
/*启动定时器*/
/*设置定时器0中断IRQ*/
VICIntSelect=0x00;
/*所有中断通道设置为IRQ中断*/
VICVectCntl0=0x20|0x04;
/*设置定时器0中断通道分配最高优先级*/
VICVectAddr0=(uint32)IRQ_Timer0;
/*设置中断服务程序地址*/
VICIntEnable=1<
0x04;
/*使能定时器0中断*/
{
if((IO0PIN&
KEY1)==0)//KEY1MIDE0
{
DelayNS(10);
if((IO0PIN&
KEY1)==0)
bj_mod=0;
i=0;
MSPI_SendData(DISP_TAB[0]);
//发送到数码管显示
bapaizhengzhuan=3*zhuansu/20;
sprintf(str,"
bapaizhengzhuan:
%4d"
bapaizhengzhuan);
//发送到上位机显示
ISendStr(0,4,0x30,str);
while((IO0PIN&
KEY1)==0);
KEY