实验一 直流步进电机综合控制系统设计20页word文档.docx
《实验一 直流步进电机综合控制系统设计20页word文档.docx》由会员分享,可在线阅读,更多相关《实验一 直流步进电机综合控制系统设计20页word文档.docx(16页珍藏版)》请在冰豆网上搜索。
实验一直流步进电机综合控制系统设计20页word文档
实验一直流、步进电机综合控制系统设计
一、实验目的
通过本次实验熟悉MagicARM2410GPIO、UART、RTC,步进电机,直流电机,IIC的工作原理;并能熟悉的编程控制。
二、实验要求
以MagicARM2410为实验平台,设计一个通过串口通信交互控制的综合型控制系统。
具体来说,可在启动时,自动列出一些选项,通过键盘选择某个选项而实现其功能;考虑到实时性,再按某个控制键能立刻停止当前功能而回到初始的待选状态。
具体功能要求如下:
1、实现四个LED灯按照十六进制的规则依次亮灭;
2、在超级终端上输入两个两位数,实现两位数的加减乘除并显示运算结果;
3、显示当前的年月日、星期、时分秒;
4、实现步进电机的调速和正反转;可用旋转按钮W1或按键控制调速,在超级终端和数码管上同步显示其正反转和转速信息;
5、实现直流电机德调速和正反转;可用旋转按钮W2或按键控制调速,在超级终端和数码管上同步显示其正反转和转速信息;
6、利用IIC通信,实现EEPROM的读写;在超级终端上显示地址和数据。
三、实验原理
(一)LED灯
四个小灯分别接于GPE11、GPE12GPH4、GPH6端口;控制端口“0“和“1”分别实现亮灭(端口设为输出)如下:
voidLED_init(void)
//初始化I/O
rGPECON=(rGPECON&(~(0x0F<<22)))|(0x05<<22);//rGPECON[25:
22]=0101b,设置GPE11、GPE12为GPIO输出模式
rGPHCON=(rGPHCON&(~(0x33<<8)))|(0x11<<8);//rGPHCON[13:
8]=01xx01b,设置GPH4、GPH6为GPIO输出模式
(二)UART
UART是一种通用串行数据总线,用于异步通信。
该总线双向通信,可以实现全双工传输和接收。
在嵌入式设计中,UART用来与PC进行通信,包括与监控调试器和其它器件,如EEPROM通信。
UART首先将接收到的并行数据转换成串行数据来传输。
消息帧从一个低位起始位开始,后面是5~8个数据位,一个可用的奇偶位和一个或几个高位停止位。
接收器发现开始位时它就知道数据准备发送,并尝试与发送器时钟频率同步。
如果选择了奇偶,UART就在数据位后面加上奇偶位。
奇偶位可用来帮助错误校验。
在接收过程中,UART从消息帧中去掉起始位和结束位,对进来的字节进行奇偶校验,并将数据字节从串行转换成并行。
UART也产生额外的信号来指示发送和接收的状态。
例如,如果产生一个奇偶错误,UART就置位奇偶标志。
UART作用
1.发送/接收逻辑
2.波特率的产生
3.数据收发
4.中断控制{出现以下情况时,可使UART产生中断:
FIFO溢出错误 线中止错误(line-break,即Rx信号一直为0的状态,包括校验位和停止位在内) 奇偶校验错误 帧错误(停止位不为1) 接收超时(接收FIFO已有数据但未满,而后续数据长时间不来) 发送 接收 由于所有中断事件在发送到中断控制器之前会一起进行“或运算”操作,所以任意时刻UART只能向中断产生一个中断请求。
通过查询中断状态函数UARTIntStatus(),软件可以在同一个中断服务函数里处理多个中断事件(多个并列的if语句)。
5回环操作
6串行红外协议
UART初始化函数如下
voidUART_Init(void)
inti;
if(g_uart_sel)//判断是否为串口1
//I/O口设置(GPH5,GPH4)
rGPHUP=rGPHUP|(0x03<<4);
rGPHCON=(rGPHCON&(~0x00000F00))|(0x00000A00);
//串口模式设置
rUFCON1=0x00;//禁止FIFO功能
rUMCON1=0x00;//AFC(流控制)禁能
rULCON1=0x03;//禁止IRDA,无奇偶校验,1位停止位,8位数据位
rUCON1=0x245;//使用PCLK来生成波特率,发送中断为电平触发模式,接收中断为边沿触发模式,
//禁止接收超时中断,使能接收错误中断,正常工作模式,中断或查询方式(非DMA)
//串口波特率设置
rUBRDIV1=(int)(PCLK/16.0/UART_BPS+0.5)-1;
else
//I/O口设置(GPH3,GPH2)
rGPHUP=rGPHUP|(0x03<<2);
rGPHCON=(rGPHCON&(~0x000000F0))|(0x000000A0);
//串口模式设置
rUFCON0=0x00;//禁止FIFO功能
rUMCON0=0x00;//AFC(流控制)禁能
rULCON0=0x03;//禁止IRDA,无奇偶校验,1位停止位,8位数据位
rUCON0=0x245;//使用PCLK来生成波特率,发送中断为电平触发模式,接收中断为边沿触发模式,
//禁止接收超时中断,使能接收错误中断,正常工作模式,中断或查询方式(非DMA)
//串口波特率设置
rUBRDIV0=(int)(PCLK/16.0/UART_BPS+0.5)-1;
for(i=0;i<100;i++);
(三)RTC
A概述
实时时钟(RTC)单元在系统电源关闭的情况下可以在备用电池下工作。
RTC可以使用STRB/LDRBARM操作传输二进制码十进制数的8位数据给CPU。
数据包括秒、分钟、小时、日期、天、月、年的时间信息。
RTC单元可以在32.768KHz的外部晶振下工作,可以可以执行报警功能。
B特点
-BCD数:
秒、分钟、小时、日期、日、月、年
-闰年生成器
-报警功能:
报警中断或从掉电模式中唤醒
-已经解决2000年问题
-独立电源引脚(RTCVDD)
-支持对于实时内核时间节拍的毫秒节拍时间中断
C实时时钟操作
C.1闰年发生器
闰年发生器可以基于BCDDATE、BCDMON、BCDYEAR的数据,从28、29、30、31中确定每个月的最后一天。
该模块在确定某月最后一天的时候会考虑闰年的因素。
一个8位的计数器仅能代表两个BCD数字,所以它不能确定是否是00年(该年的最后两个数字是00)。
C.2读写寄存器
为了写RTC模块中的BCD寄存器,RTCCON寄存器的位0必须置1。
为了显示秒分小时星期日月年,CPU应该分别读取在RTC模块中的BCDSEC,BCDMIN,BCDHOUR,BCDDAY,BCDDATE,BCDMON,和BCDYEAR。
但是,因为多寄存器读取可能存在一秒的误差。
例如,当用户读BCDYEAR和BCDMON,结构假定是2059年12月31日23点59分。
当用户读BCDSEC寄存器,值的范围是从1到59(秒)就没有问题,但是如果值是0,年月日就变成了2060年1月1日0时0分因为有刚才提到的1秒误差。
在这种情况下如果BCDSEC为0,用户应该重读BCDYEAR到BCDSEC。
C.3备用电池操作
RTC逻辑可以由备用电池驱动,其通过RCTVDD引脚给RTC模块提供电源,即使系统电源关闭。
当系统关闭时,CPU和RTC模块的接口是封闭的,备用电池仅驱动振荡电路和BCD计数器以最小化电源消耗。
C.4报警功能
RTC在掉电模式或正常操作模式下的特定时间会发出报警信号。
在正常操作模式下报警中断(INT_RTC)被激活。
在掉电模式下,电源管理唤醒信号(PMWKUP)也如INT_RTC一样被激活。
RTC报警寄存器(RTCALM)决定了报警的使能状态和报警时间设定的条。
C.5节拍时间中断
RTC节拍时间是用于中断请求。
TICNT寄存器有一个中断使能位和对于中断的计数器值当节拍时间中断出现时,计数器的值为0。
中断周期如下:
Period=(n+1)/128secondn:
节拍计数器值(1~127)RTC节拍时间可以用于实时操作系统内核时间节拍。
如果时间节拍由RTC时间节拍生成,与实时操作系统功能相关的时间就会和实时同步。
D.RTC寄存器
(1)实时时钟控制寄存器(RTCCON)
(2)节拍时间计数寄存器(TICNT)
(3)RTC报警控制寄存器(RTCALM)
(4)报警秒数据寄存器(ALMSEC)
(5)报警分钟数据寄存器(ALMMIN)
(6)报警小时数据寄存器(ALMHOUR)
(7)报警日期数据寄存器(ALMDATE)
(8)报警月数据寄存器(ALMMON)
(9)报警年数据寄存器(ALMYEAR)
(10)BCD秒寄存器(BCDSEC)
(11)BCD分寄存器(BCDMIN)
(12)BCD小时寄存器(BCDHOUR)
(13)BCD日期寄存器(BCDDATE)
(14)BCD日寄存器(BCDDAY)
(15)BCD月寄存器(BCDMON)
(16)BCD年寄存器(BCDYEAR)
(四)步进机与直流电机工作原理
步进电机是一种将电脉冲转化为角位移的执行机构。
步进电机正传,双四拍程序。
时序控制为AB--BC--CD--DA--AB,共控制运转4圈(电机步距角为18度)。
每一步的延时控制。
值越大,延时越久;步进电机反转,双四拍程序时序控制为AD--DC--CB--BA--AD。
步距角为18度)。
每一步的延时控制。
值越大,延时越久。
正转模式:
dly为延时
voidMOTO_Mode1(uint32dly)
//AB相有效
GPIOSET(MOTOA);
GPIOSET(MOTOB);
Delay(dly);
GPIOCLR(MOTOA);
GPIOCLR(MOTOB);
//BC相有效
GPIOSET(MOTOB);
GPIOSET(MOTOC);
Delay(dly);
GPIOCLR(MOTOB);
GPIOCLR(MOTOC);
//CD相有效
GPIOSET(MOTOC);
GPIOSET(MOTOD);
Delay(dly);
GPIOCLR(MOTOC);
GPIOCLR(MOTOD);
//DA相有效
GPIOSET(MOTOD);
GPIOSET(MOTOA);
Delay(dly);
GPIOCLR(MOTOD);
GPIOCLR(MOTOA);
直流电机由PWM脉冲调制控制;脉冲为1是电机转动,0时停止转动。
通过PWM占空比来实现加减速。
参考程序:
voidStepMOTO_Test(void)
//uint32a=0;
//步进电机控制口设置
rGPCCON=(rGPCCON&(~0x0000FC03))|(0x00005401);//GPC0、GPC5--7口设置为输出
rGPCUP=rGPCUP|0x00E1;//禁止GPC0、GPC5--7口的上拉电阻
rGPCDAT=rGPCDAT&(~0x00E1);//设置GPC0、GPC5--7口输出低电平
while
(1)
UART_SendStr("Pleaseinput'z'OR'f'tocontrolzhengzhuanandfanzhuan\n");
UART_SendStr("Press'o'keyexittest\n");
switch(getch=UART_GetKey())
case'z':
sprintf("Press'j'tospeedup;'ESC'breakout.");
for(;;)
Change_Speed();
MOTO_Mode1(speed1);//控制步进电机正转
//在终端上显示速度
sprintf(disp_buf2,"Zhengzhuan:
StepMoto_speedis%d\n",(330-speed1));
UART_SendStr(disp_buf2);
if(UART_GetFlag()=='j')
speedup();//加速
if(UART_GetFlag()==0x1B)//按Esc键退出测试
break;
break;
case'f':
sprintf("Press'j'tospeedup;'ESC'breakout.");
for(;;)
Change_Speed();
MOTO_Mode2(speed1);//控制步进电机反转
//在终端上显示速度
sprintf(disp_buf2,"Fanzhuan:
StepMoto_speedis%d\n",-(330-speed1));
UART_SendStr(disp_buf2);
if(UART_GetFlag()=='j')
UART_SendStr("j");
speedup();//加速
if(UART_GetFlag()==0x1B)//按Esc键退出测试
break;
break;
default:
break;
if(getch=='o')//按下字母'o'键退出整个步进电机测试
break;
直流电机测试程序:
voidDCMOTO_Test(void)
uint32i=0,a=0;
uint16pwm_dac;
charget_ch=0;
//TOUT0口设置
rGPBCON=(rGPBCON&(~(0x03<<0)))|(0x02<<0);//rGPBCON[1:
0]=10b,设置TOUT0功能
rGPBUP=rGPBUP|0x0001;//禁止TOUT0口的上拉电阻
//设置GPH9为GPIO输出模式
rGPHCON=(rGPHCON&(~(0x03<<18)))|(0x01<<18);//GPH9口
rGPHDAT=rGPHDAT&(~(1<<9));//输出0电平
rGPHUP=rGPHUP|(1<<9);
//初始化PWM输出。
设PWM周期控制值为255
pwm_dac=250*255/330;//初始化占空比
PWM_Init(255,pwm_dac);
while
(1)
//按'z'键控制正传,'f'键控制反转,'s'键停止转动'Esc'退出测试
UART_SendStr("\nPressthekeytocontrolstate:
'z'--zhengzhuan'f'--fanzhuan's'--stop\n");
switch((get_ch=UART_GetKey()))
case'z':
rGPBDAT=rGPHDAT|(1<<9);
rGPHDAT=rGPHDAT&(~(1<<9));
while
(1)
Change_Speed();
rTCMPB0=(speed2*255/330);
sprintf(disp_buf3,"DCMoto_speedis%d\n",speed2);//终端显示正转速度
UART_SendStr(disp_buf3);
if(UART_GetFlag()=='s')
rGPBDAT=rGPHDAT&(~(1<<9));
rGPHDAT=rGPHDAT&(~(1<<9));
break;
break;
case'f':
rGPBDAT=rGPHDAT&(~(1<<9));
rGPHDAT=rGPHDAT|(1<<9);
while
(1)
Change_Speed();
rTCMPB0=(speed2*255/330);
sprintf(disp_buf3,"DCMoto_speedis%d\n",(-speed2));//终端显示正转速度
UART_SendStr(disp_buf3);
if(UART_GetFlag()=='s')
rGPBDAT=rGPHDAT&(~(1<<9));
rGPHDAT=rGPHDAT&(~(1<<9));
break;
break;
default:
break;
if(UART_GetFlag()==0x1B)
break;
(五)IIC通信实现EEPROM的读写
(一)I2C,一种总线结构。
I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。
所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。
实验过程中必须先初始化总线—启动总线后才能用其进行通信。
intI2C_SendByte(uint8dat)//发送一字节数据,并接收应答位
intI2C_RcvByteNA(uint8*dat)//接收I2C总线上一字节数据并发送非应答位
intI2C_RcvByteA(uint8*dat)//接上I2C总线上一字节数据,并发送应答位
voidStopI2C(uint8send)//结束总线
intISendStr(uint8sla,uint8*suba,uint8*s,uint8no)
【**Descriptions:
使用硬件I2C发送数据。
**Input:
sla从机地址
**suba器件子地址(第一字节用来表示子地址字节个数)
**s发送数据缓冲区
**no发送数据个数
**Output:
操作成功返回TRUE,仲载失败/无从机应答返回FALSE
**Note:
使用前设置好参数。
程序不会更改s、suba缓冲区的数据】
intIRcvStr(uint8sla,uint8*suba,uint8*s,uint8no)
//v使用硬件I2C读取数据。
参数和发送对应
(二)测试EEPROM程序
voidTestEEPROM(void)
uint8suba[2];
intrw_err;
inti;
rw_err=0;
//写数据测试
suba[0]=1;//1位子地址
suba[1]=0x00;//子地址
for(i=0;i<10;i++)
dat_buf[i]=i+'0';
UART_SendStr("dataofwrite:
");
for(i=0;i<5;i++)
UART_SendByte(dat_buf[i]);
UART_SendStr("\n");
i2c_opsta=ISendStr(CAT1025,suba,dat_buf,5);
for(i=0;i<10000;i++);//等待写周期
//读出校验
for(i=0;i<5;i++)dat_buf[i]=0x00;
i2c_opsta=IRcvStr(CAT1025,suba,dat_buf,5);
UART_SendStr("dataofread:
");
for(i=0;i<5;i++)
UART_SendByte(dat_buf[i]);
UART_SendStr("\n");
for(i=0;i<5;i++)
if(dat_buf[i]!
=(i+'0'))rw_err=1;
//判断操作是否出错,如果出错则蜂鸣报警
if(rw_err)ErrorShow();
【如果写入的数据和读出的相同,则测试通过】
四、实验程序
【main函数:
主要实现与终端交互的功能,通过键盘输入字符的判断来决定执行的功能】
intmain(void)
uint8g_getch;
inti=0;
UART_Select(0);//选择UART0
UART_Init();//UART0初始化
LED_init();//LED相关初始化
EINT_init();//外部中断初始化
while
(1)
fun_test();
switch(g_getch=UART_GetKey())
case'1':
UART_SendByte(g_getch);
UART_SendStr("\n");
LED_DispAllOn();//LED灯全亮
DelayNS(10);
UART_SendStr("\nTestLED_DispAllOnisOver!
\n");
break;
case'2':
UART_SendByte(g_getch);
UART_SendStr("\n");
LED_DispAllOff();//LED灯全灭
DelayNS(10);
UART_SendStr("\nTestLED_DispAllOffisOver!
\n");
break;
case'3':
UART_SendByte(g_getch);
UART_SendStr("\n");
for(;;)//死循环,当检测到按下‘Esc’键时退出
LED_onebyone();//流水灯
if(UART_GetFlag()==0x1B)//检测是否按下'Esc'键
break;
LED_DispAllOff();
UART_SendStr("\nTestLED_OnebyOneisOver!
\n");
break;
case'4':
UART_SendByte(g_getch);
UART_SendStr("\n");
Arithmitic();//加减乘除测试模块
UART_SendStr("\nTestAddsubmuldiv_TestisOver!
\n");
break;
case'5':
UART_S