2019-12-12 01:05:10 weixin_44613063 阅读数 237
  • 直流电机和步进电机-第1季第12部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第12个课程,主要讲解了直流电机和步进电机,其中步进电机是关键,通过学习让大家初步掌握步进电机相关的概念和时序,能够将时序转化为驱动程序以驱动步进电机。

    2670 人正在学习 去看看 朱有鹏

步进电机是一种将电脉冲转化为角位移的执行机构。当步进电机的驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(即步长)。通过控制脉冲个数来控制角位移量,达到准确定位的目的;通过控制脉冲频率来控制电机转动的速度和加速度,达到调速的目的。

下面是连接图,右上角是 Arduino 与驱动器的连线,VCC、脉冲、方向、使能是单片机提供的 4 个引脚,字面意思是对于驱动器而言,与 Arduino 无关,选择 4 个输出引脚就行。VCC 与三个 +端 相连。

在这里插入图片描述


控制程序

这里使用 2、3、4、5 四个引脚与驱动器连接,只需要控制脉冲的次数和频率就能够控制电机转动的角度和速度。本来 Arduino 有专门的 Stepper 库来驱动步进电机,但功能比较简单,就自己写了,还有一个 tone() 频率函数,如果只控制速度可以使用一下。

代码如下:

#define VCC 2
#define PLS 3
#define DIR 4
#define ENA 5

void setup() {
	pinMode(VCC, OUTPUT);
	pinMode(PLS, OUTPUT);
	pinMode(DIR, OUTPUT);
	pinMode(ENA, OUTPUT);
}

void loop() {
	digitalWrite(VCC, HIGH);
	digitalWrite(ENA, HIGH);
	digitalWrite(DIR, HIGH);	//正转
	//正转一圈,用时1s
	//此处驱动器定义1600步为1圈
	//本来1600X625微秒=1秒,因为时间间隔太短,程序运行也需要时间,间隔时间/2之后总时间差不多1秒
    for(int x=0; x<1600; x++){
	    digitalWrite(PLS, HIGH);
	    delayMicroseconds(625/2);
	    digitalWrite(PLS, LOW);
	    delayMicroseconds(625/2);
    }
	delay(1000);	//停1s
	
	digitalWrite(DIR, LOW);    //反转
	//反转一圈,用时1s
    for(int x=0; x<1600; x++){
	    digitalWrite(PLS, HIGH);
	    delayMicroseconds(625/2);
	    digitalWrite(PLS, LOW);
	    delayMicroseconds(625/2);
    }
	delay(1000);	//停1s
}

上面的代码是让步进电机正转 1 圈后停 1 秒,再反转 1 圈后停 1 秒,转 1 圈的时间也是 1 秒,如此循环,可根据需要自己更改。

程序说明:VCC 给驱动器提供电源引脚,PLS 给步进电机提供脉冲引脚,DIR 决定电机是正转还是反转,ENA 是步进电机驱动器的开关,如果控制电路给 ENA 引脚高电压那么就相当于让驱动器接受控制信号,如果 ENA 提供低电压,无论怎么给脉冲信号电机都不会动。在 PLS 引脚产生一定频率的脉冲,并控制脉冲时间,就可控制步进电机。

2018-06-07 17:42:57 ca1m0921 阅读数 3416
  • 直流电机和步进电机-第1季第12部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第12个课程,主要讲解了直流电机和步进电机,其中步进电机是关键,通过学习让大家初步掌握步进电机相关的概念和时序,能够将时序转化为驱动程序以驱动步进电机。

    2670 人正在学习 去看看 朱有鹏

1. 要完成的工作内容:

  1.  组装小车,完成线路规划。=======>> 完成任务,完成了小车的连线

  2.  定义接线引脚,考虑 多方面 因素。=====>> 定义了单片机引脚 与 各个模块的连接

  3.  进行 模块测试,分析遇到的问题。====>> 完成了 模块的测试,以及完成了 蓝牙控制小车前进

  1. .....

 

 

 2. 整个小车系统的架构:

 

 

3. 过程中遇到的问题:

 

3.1  测试 :  测试 电压不够 是因为 直接连接了  电机驱动 还是  南孚 就是不能用。      

假设 :  南孚电池组 可以 直接给 单片机 供电, 经过测试,使用四节南孚电池  直接给51最小系统供6V电,51最小系统工作正常,再通过51最小系统给电机驱动模块供电。

 

(测试中遇到两个问题 : 

       1. 上电之后,最小系统的单片机发烫,原因是 单片机的安置方面 摆反了。因为卡座上没有标识,一直以来关于怎么放,都是蒙,昨天认真研究了一下。我使用的 是 STC89C52 的40引脚 长方形 芯片。摆放在卡座上的方向  : 缺角标识的右上角 应该是最小系统的 VCC引脚。

       2. 当使用USB-TTL下载线连接最小系统时,在最小系统电源开关关闭状态下,最小系统的指示灯没有亮(在最小系统开关关闭的情况下,指示灯也应该亮,只是光不强而已)。原因是 卡座没有卡住 芯片。

 

 

 

3.2   因为 程序总是进入左转 或者 右转 中,没有办法 跳出来,所以 测试是否是 延迟 程序 的问题,

    经过测试,发现如果存在延迟程序,蓝牙控制小车 就不会生效。所以要改变  小车转弯的实现方式。考虑使用 PWM控制。

 

 

@其他:

 

采购:   USB 延长线、  电池盒、 

 

 

@闲时测试:

 

测试 : 单片机的 P0口 经过上拉电阻 之后 可以通过置位  给 低电平?

 

 

测试:  速度调节,控制直行


 

测试:  蓝牙莫名断开===>>考虑可能是 单片机的断电

 

 

 

 

 

 

今天的 任务 是 :通过技术方式,实现 小车的直行  和  90度转弯。

 

 

 

 

 

 

 

 

 

 

 

2018-05-07 16:58:30 qq_40977332 阅读数 2793
  • 直流电机和步进电机-第1季第12部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第12个课程,主要讲解了直流电机和步进电机,其中步进电机是关键,通过学习让大家初步掌握步进电机相关的概念和时序,能够将时序转化为驱动程序以驱动步进电机。

    2670 人正在学习 去看看 朱有鹏

前段时间,学完51单片机,出于兴趣,做了一个蓝牙遥控小车,能实现现小车的前进、停止、后退、左转、右转、变速等基本控制。

​ 小车主要由STC12C5620AD为主要控制模块,蓝牙模块使用的是hc-05,使用一个L298N驱动两个电机,通过电机之间的交叉连线,使同一方向的电机实现同方向转动,利用PWM的原理控制电机,程序如下:

硬件链接:

左电机控制端口:P0.0、P0.1
右电机控制端口:P0.2、P0.3         

***************************/

include

define uchar unsigned char//宏定义

define uint unsigned int//宏定义

define aa 50//左轮速度调节值

define bb 50//右轮速度调节值

define PWM1 7//小车前进速度,1-9可调(若转弯容易冲出,调慢即可)

define PWM2 8//小车转向速度,1-9可调

sbit zb=P1^2;//左边 光电管的信号端
sbit qb=P1^1;//前边 光电管的信号端
sbit yb=P1^0;//右边 光电管的信号端
sbit you1=P0^1;//右轮正转信号端
sbit you2=P0^0;//右轮倒转信号端
sbit zuo1=P0^3;//左轮正转信号端
sbit zuo2=P0^2;//左轮倒转信号端

uchar a=0;//定义一个变量a,用来读取串口的数据
uchar flag = 0;
void delayms(uint z)//一个带参数的延时程序
{

int i,j;//定义两个变量
for(i=z;i>0;i--)
for(j=110;j>0;j--);//将参数z赋值给j

}
void qian()//前进
{

you1=0;
you2=1;
zuo1=0;
zuo2=1;
delayms(PWM1);//pwm调速,若PWM1=7表示速度为全速的35%
you1=0;
you2=0;
zuo1=0;
zuo2=0;
delayms(20-PWM1);   

}
void you()//右转
{

you1=1;
you2=1;
zuo1=0;
zuo2=1;
delayms(PWM2);//pwm调速,若PWM1=9表示速度为全速的90%
you1=0;
you2=0;
zuo1=0;
zuo2=0;
delayms(20-PWM2);

}
void zuo()//左转
{

you1=0;
you2=1;
zuo1=1;
zuo2=1;
delayms(PWM2);//pwm调速,若PWM1=9表示速度为全速的90%
you1=0;
you2=0;
zuo1=0;
zuo2=0;
delayms(20-PWM2);

}
void init()//初始化子程序
{

TMOD=0x20;//设置定时器T1为工作方式2
TH1=0xfd;
TL1=0xfd;//T1定时器装初值
TR1=1;//启动定时器T1
REN=1;//允许串口接收
SM0=0;
SM1=1;//设置串口工作方式1
EA=1;//开总中断
ES=1;//开串口中断

}
void go1()//前进子程序
{

zuo1=1;
zuo2=0;//左边轮子正转
delayms(aa);//pwm有用值,越大左边方向的轮子越快
zuo2=1;//关闭左边轮子

you1=1;
you2=0; //右边轮子正转
delayms(bb);//pwm有用值,越大右边的轮子越快
you2=1;//关闭右边轮子

delayms(100);//pwm无用值,越大,小车跑的越慢

}

void go2()//前进子程序
{

zuo1=1;
zuo2=0;//左边轮子正转
delayms(aa);//pwm有用值,越大左边方向的轮子越快
zuo2=1;//关闭左边轮子

you1=1;
you2=0; //右边轮子正转
delayms(bb);//pwm有用值,越大右边的轮子越快
you2=1;//关闭右边轮子

delayms(80);//pwm无用值,越大,小车跑的越慢

}

void go3()//前进子程序
{

zuo1=1;
zuo2=0;//左边轮子正转
delayms(aa);//pwm有用值,越大左边方向的轮子越快
zuo2=1;//关闭左边轮子

you1=1;
you2=0; //右边轮子正转
delayms(bb);//pwm有用值,越大右边的轮子越快
you2=1;//关闭右边轮子

delayms(60);//pwm无用值,越大,小车跑的越慢

}

void go4()//前进子程序
{

zuo1=1;
zuo2=0;//左边轮子正转
delayms(aa);//pwm有用值,越大左边方向的轮子越快
zuo2=1;//关闭左边轮子

you1=1;
you2=0; //右边轮子正转
delayms(bb);//pwm有用值,越大右边的轮子越快
you2=1;//关闭右边轮子

delayms(40);//pwm无用值,越大,小车跑的越慢

}

void go5()//前进子程序
{

zuo1=1;
zuo2=0;//左边轮子正转
delayms(aa);//pwm有用值,越大左边方向的轮子越快
zuo2=1;//关闭左边轮子

you1=1;
you2=0; //右边轮子正转
delayms(bb);//pwm有用值,越大右边的轮子越快
you2=1;//关闭右边轮子

delayms(20);//pwm无用值,越大,小车跑的越慢

}

void go6()//前进子程序
{

zuo1=1;
zuo2=0;//左边轮子正转
delayms(aa);//pwm有用值,越大左边方向的轮子越快
zuo2=1;//关闭左边轮子

you1=1;
you2=0; //右边轮子正转
delayms(bb);//pwm有用值,越大右边的轮子越快
you2=1;//关闭右边轮子

}

void hui1()//小车后退的子程序
{

zuo1=0;
zuo2=1;//左边轮子倒转
delayms(aa);//pwm有用值,越大左边方向的轮子越快
zuo1=1;//关闭左边轮子

you1=0;
you2=1; //右边轮子倒转
delayms(bb);//pwm有用值,越大右边的轮子越快
you1=1;//关闭右边轮子

delayms(100);//pwm无用值,越大,小车跑的越慢

}

void hui2()//小车后退的子程序
{

zuo1=0;
zuo2=1;//左边轮子倒转
delayms(aa);//pwm有用值,越大左边方向的轮子越快
zuo1=1;//关闭左边轮子

you1=0;
you2=1; //右边轮子倒转
delayms(bb);//pwm有用值,越大右边的轮子越快
you1=1;//关闭右边轮子

delayms(80);//pwm无用值,越大,小车跑的越慢

}

void hui3()//小车后退的子程序
{

zuo1=0;
zuo2=1;//左边轮子倒转
delayms(aa);//pwm有用值,越大左边方向的轮子越快
zuo1=1;//关闭左边轮子

you1=0;
you2=1; //右边轮子倒转
delayms(bb);//pwm有用值,越大右边的轮子越快
you1=1;//关闭右边轮子

delayms(60);//pwm无用值,越大,小车跑的越慢

}

void hui4()//小车后退的子程序
{

zuo1=0;
zuo2=1;//左边轮子倒转
delayms(aa);//pwm有用值,越大左边方向的轮子越快
zuo1=1;//关闭左边轮子

you1=0;
you2=1; //右边轮子倒转
delayms(bb);//pwm有用值,越大右边的轮子越快
you1=1;//关闭右边轮子

delayms(40);//pwm无用值,越大,小车跑的越慢

}
void hui5()//小车后退的子程序
{

zuo1=0;
zuo2=1;//左边轮子倒转
delayms(aa);//pwm有用值,越大左边方向的轮子越快
zuo1=1;//关闭左边轮子

you1=0;
you2=1; //右边轮子倒转
delayms(bb);//pwm有用值,越大右边的轮子越快
you1=1;//关闭右边轮子

delayms(20);//pwm无用值,越大,小车跑的越慢

}
void hui6()//小车后退的子程序
{

zuo1=0;
zuo2=1;//左边轮子倒转
delayms(aa);//pwm有用值,越大左边方向的轮子越快
zuo1=1;//关闭左边轮子

you1=0;
you2=1; //右边轮子倒转
delayms(bb);//pwm有用值,越大右边的轮子越快
you1=1;//关闭右边轮子

}

void turnleft()//小车左转弯子程序
{

zuo1=0;
zuo2=1;//左边轮子停止转动
you1=1;
you2=0; //右边轮子正转
delayms(1);//pwm有用值,越大右边的轮子越快
you2=1;//右边轮子停止
zuo1=1;

}

void turnright()//小车右转弯子程序
{

zuo1=1;
zuo2=0;//左边轮子正转
you1=0;
you2=1; //右边轮子停止
delayms(1);//pwm有用值,越大左边方向的轮子越快
zuo2=1;//左边轮子停止
you1=1; 

}
void down()//停止子程序
{

zuo1=1;
zuo2=1;
you1=1;
you2=1; //左右轮全部停止

}
void APP()
{

if(a==0x14||a==0x15||a==0x54||a==0x55||a==0x64||a==0x65)//如果是就前进
        go1();
        if(a==0x16||a==0x17||a==0x56||a==0x57||a==0x66||a==0x67)//如果是就前进
        go2();
        if(a==0x18||a==0x19||a==0x58||a==0x59||a==0x68||a==0x69)//如果是就前进
        go3();
        if(a==0x1a||a==0x1b||a==0x5a||a==0x5b||a==0x6a||a==0x6b)//如果是就前进
        go4();
        if(a==0x1c||a==0x1d||a==0x5c||a==0x5d||a==0x6c||a==0x6d)//如果是就前进
        go5();
        if(a==0x1e||a==0x1f||a==0x5e||a==0x5f||a==0x6e||a==0x6f)//如果是就前进
        go6();

        if(a==0x24||a==0x25||a==0x74||a==0x75||a==0x84||a==0x85)//如果是就后退
        hui1();
        if(a==0x26||a==0x27||a==0x76||a==0x77||a==0x86||a==0x87)//如果是就后退
        hui2();
        if(a==0x28||a==0x29||a==0x78||a==0x79||a==0x88||a==0x89)//如果是就后退
        hui3();
        if(a==0x2a||a==0x2b||a==0x7a||a==0x7b||a==0x8a||a==0x8b)//如果是就后退
        hui4();
        if(a==0x2c||a==0x2d||a==0x7c||a==0x7d||a==0x8c||a==0x8d)//如果是就后退
        hui5();
        if(a==0x2e||a==0x2f||a==0x7e||a==0x7d||a==0x8e||a==0x8f)//如果是就后退
        hui6();

        if(a==0x3f)//如果是0x3f就左转
        turnleft();
        if(a==0x4f)//如果是0x4f就右转
        turnright();
        if(a==0x00)//如果是0x00就停止
        down();
        else
        down();

}

void main()//主程序
{

init();//调用初始化子程序
while(1)//死循环
{
       if(flag == 1)
       {
         APP();
        flag = 0;
       }

}   

}

void chuan() interrupt 4//串口中断服务程序
{

RI=0;//软件清除串口响应
a=SBUF;//读取单片机串口接受的蓝牙模块发送的数据
flag = 1;

}

2019-11-22 13:27:38 weixin_45066914 阅读数 252
  • 直流电机和步进电机-第1季第12部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第12个课程,主要讲解了直流电机和步进电机,其中步进电机是关键,通过学习让大家初步掌握步进电机相关的概念和时序,能够将时序转化为驱动程序以驱动步进电机。

    2670 人正在学习 去看看 朱有鹏

一位萌新为参加robomaster所做的中期准备-robomaster电控部分学习(前言)


前期我们学习了stm32的相关知识,对stm32有了一定的了解,使我们能够熟练得对数据进行发送,接收,处理,能够控制单片机进行一定的操作。

中期我们需要了解robomaster比赛的相关知识,stm32只是一个载体,比赛关于电控部分涉及的知识十分宽阔,需要我们分模块,写框图(比如电机的连线、选型、控制,底盘功率限制,枪口热量限制,pid的编写与调参,操作系统,云台的控制,裁判系统的学习,发射机构相关代码,陀螺仪数据解算,麦克纳姆轮解算等等)

之前我们学习过程是:
1.学习遥控器说明书,了解相应知识,利用串口DMA接收遥控器数据,并处理遥控器数据(利用串口空闲中断接收)
2.驱动步兵车的底盘:①学习3508电机,c620电调说明书,了解相关的知识和参数,通过CAN通信将数据发送给3508电机,使电机转动②学习麦克纳姆轮相关知识,了解麦轮解算③将遥控器处理后的数据进行麦轮解算,发送给3508电机④学习如何通过CAN通信获取3508电机的数据(电机的转速,角度,温度等)⑤学习pid相关知识,将麦轮解算后的数据作为目标值,电机返回的数据作为当前值,进行pid运算,得出最终结果,发送给电机,达到驱动底盘的效果(先了解pid,比赛中一般运用的是串级pid来驱动底盘)
3.控制步兵车的云台:①学习6623电机,电调说明书,了解yaw轴和pit轴的相关知识②遥控器数据处理,获取电机返回值,利用pid运算,发送给电机,初步控制云台。③利用云台学习单级pid调参,利用虚拟示波器读取图像,通过图像调节p,i,d④学习陀螺仪(先从板子自带的mpu6500开始,通过spi通信获取数据)⑤将陀螺仪数据作为速度环的当前值,进行串级pid运算,进一步控制云台
4.学习发射机构,拨盘电机,摩擦轮电机的控制,关键在于对拨盘转速,单发连发,空弹等等算法的学习

这样学习完后就可以对步兵车进行基本的控制,能够完成步兵车基本的功能,也算进入了robomaster的大坑(嘿嘿)

2019-06-30 12:37:04 weixin_42048463 阅读数 29
  • 直流电机和步进电机-第1季第12部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第12个课程,主要讲解了直流电机和步进电机,其中步进电机是关键,通过学习让大家初步掌握步进电机相关的概念和时序,能够将时序转化为驱动程序以驱动步进电机。

    2670 人正在学习 去看看 朱有鹏

较Version 1.0, 增加了对针臂步进电机、针臂停留底部时间的控制模块, 可通过给定参数以定量方式控制针臂抬起落下的速度或控制针臂在底部停留的时间.

硬件搭建:

8051单片机(STC89C52RC) + 若干杜邦线 + 虚拟接口卡 + 虚拟接口卡专用USB线 + 8051专用USB线.

连线对接:

P1.0 -> P20

P1.1 -> P21

P1.2 -> P22

P1.3 -> P03

P0.0 -> P00

P0.1 -> P01

P0.2 -> P02

注: 左侧为虚拟接口卡接口, 右侧为STC89C52RC接口.

在此补充一下驱动系统的命令:

1. Start.E命令: 启动系统.

2. Stop.E命令: 在一个周期序列动作完成后, 停止系统.

3. Rotate 0/1.E命令: 命令主转盘以顺时针/逆时针方向转动.

4. Main motor runs X(0 ~ 9).E命令:  在一个周期序列动作完成后, 停止系统, 以给定参数决定的速度, 转动X步主转盘.(这里借用针臂步进电机的时延函数来驱动主步进电机).

5. Main motor runs XX(10 ~ 99).E命令: 和4功能一致, 在给定的步数为两位数时使用.

6. Reset.E: 命令: 系统未进入到Start命令模式下且针臂未在该模式下进入到上下移位过程中, 针臂抬至上限位, 主转盘转至0号瓶位置, 之后停止工作.

7. Arm speeds XX, XX.E命令: 命令针臂以XX XX决定的参数上下移动.

8. Arm delays XXX, XXX.E命令: 命令针臂在底部停留的时间.

#include <STC89C5xRC.h>
char tcount = 0;
char step = 0;//记录主电机走过的步数(走过的步数=step/2)
char buf[30];//存放命令
int en = 0;//en = 1 -> 系统工作, en = 0 -> 系统停止
int k = 0;
int len = 0;
int re = 0;//复位信号, 1 -> 复位, 0 -> 不复位
int direction = 0;//0 -> 顺时针, 1 -> 逆时针
int step_B = 0;//命令要求主电机转的步数
int motorRun = 0;// 1 -> 按命令转相应步数, 0 -> 无动作
int S1 = 300;//针臂在底部停留时间参数1
int S2 = 400;//针臂在底部停留时间参数2
int A1 = 40;//针臂电机参数1
int A2 = 40; //针臂电机参数2

void delay(int A1, int A2)
{
    int i,j;
    for(i = 0; i < A1; i++)
        for(j = 0; j < A2 ; j++)
        {
            ;//为针臂步进电机提供时延
        }
}
void delay2(int S1, int S2)//针臂在底部停留时延
{
    int i,j;
    for(i=0;i<S1;i++)
        for(j=0;j<S2;j++)
        {
            ;
        }
}
void motor_Control(int steps)//控制主转盘电机转动指定步数
{
    int i;
    for(i = 0; i < steps; i++)
    {
        P20 = 0;
        delay(A1, A2);
        P20 = 1;
        delay(A1, A2);
    }
}
void timer0() interrupt 1
{
    int i = 0;
    if(step == 0)
    {
        if(direction == 0)
        {
            P21 = 0;//顺时针
        }
        else if(direction == 1)
        {
            P21 = 1;//逆时针
        }
    }
    TR0 = 0;//关闭定时器0
    TH0 = 0x3c;
    TL0 = 0xB0;//50ms
    if(re == 1)//复位信号起作用
    {
        re = 0;
        //针臂移至上限位, 转盘转回0号瓶
        P03 = 0;//往上转
        while(P01 == 1)//若未到上限位置,P0.1接单片机P01
        {
            P22 = 0;
            delay(A1, A2);
            P22 = 1;    
            delay(A1, A2);
        }
        while(P00 == 1)//若未到0号瓶位置
        {
            P20 = 0;
            delay(A1, A2);
            P20 = 1;
            delay(A1, A2);
        }
        //霍尔传感器有误差, 还差2.5格左右, 再发20个脉冲
        if(P21 == 1)//转盘逆时针转过来
        {
            while(i++ < 20)
            {
                P20 = 0;
                delay(A1, A2);
                P20 = 1;
                delay(A1, A2);
            }
        }
        else if(P21 == 0)//转盘顺时针转过来
        {
            while(i++ < 22)
            {
                P20 = 0;
                delay(A1, A2);
                P20 = 1;
                delay(A1, A2);
            }    
        }
        tcount = 0;
        en = 0;
        step = 0;
        goto END;
    }
    if(motorRun == 1)//电机按要求转命令起作用
    {
        motorRun = 0;
        step = 0;
        tcount = 0;
        en  = 0;
        motor_Control(step_B);
        step_B = 0;
        goto END;
    }
    tcount++;
    if(tcount == 2)//100ms = 0.1s
    {
        P20 = ~P20;//P20翻转,相当于发送脉冲
        tcount = 0;
        step ++;
        if(step / 2 == 8)//电机走了8步(经历了8次高低电平的转换)
        {
            step = 0;//将步数归零
            //P1.3=1代表向下,P1.3=0代表向上
            P03 = 1;//往下转,P13接单片机P03
            while(P02 == 1)//若未到下限位置,P0.2接单片机P02
            {
                P22 = 0;
                   delay(A1, A2);
                P22 = 1;
                delay(A1 ,A2);
            }
            delay2(S1, S2);//针臂在底部停留片刻
            P03 = 0;//往上转
            while(P01 == 1)//若未到上限位置,P0.1接单片机P01
            {
                P22 = 0;
                delay(A1, A2);
                P22 = 1;
                delay(A1, A2);
            }
        }
    }//1000ms = 1s 发送一个完整的脉冲
END: ;
    TR0 = 1;//开启定时器0
}

void UART_INT() interrupt 4//串行通信中断处理程序
{
    int len = 0;
    int j = 0;
    if(RI == 1)//如果收到数据
    {
        if(k == 30)
        {
            k = 0;//防止越界访问
        }
        RI = 0;
        buf[k++] = SBUF;//将数据接收下来
        if(buf[k - 1] == 'E')//到达结尾
        {
            len = k - 1;//记录数据长度
            k = 0;
            if(len == 6)
            {
                if(buf[0] == 'S' && buf[1] == 't' && buf[2] == 'a' && buf[3] == 'r' && buf[4] == 't' && buf[5] == '.')
                {
                    //Start命令(开机)
                    en = 1;
                    P27 = 0;//D8亮
                    P26 = 1;
                    P25 = 1;
                    P24 = 1;
                    //再将en的值传回去
                    SBUF = en + 48;
                }
                else if(buf[0] == 'R' && buf[1] == 'e' && buf[2] == 's' && buf[3] == 'e' && buf[4] == 't' && buf[5] == '.')//主转盘回到原始位置,针臂抬到最高位置
                {
                    //Reset命令(复位命令)
                    en = 1;
                    P27 = 1;
                    P26 = 0;//D7亮
                    P25 = 1;
                    P24 = 1;
                    SBUF = en + 48;
                    re = 1;//复位信号
                }
            }
            else if(len == 5)//停机命令
            {
                if(buf[0] == 'S' && buf[1] == 't' && buf[2] == 'o' && buf[3] == 'p' && buf[4] == '.')
                {
                    //Stop命令(停机命令)
                    en = 0;
                    P27 = 1;
                    P26 = 1;
                    P25 = 0;//D6亮
                    P24 = 1;
                    SBUF = en + 48;
                }
            }
            else if(len == 19)//要求主转盘转动相应格数(>=10)
            {
                if(buf[0] == 'M' && buf[1] == 'a' && buf[2] == 'i' && buf[3] == 'n' && buf[4] == ' ' && buf[5] == 'm' && buf[6] == 'o' && buf[7] == 't' && buf[8] == 'o' && buf[9] == 'r' && buf[10] == ' ' && buf[11] == 'r' && buf[12] == 'u' && buf[13] == 'n' && buf[14] == 's' && buf[15] == ' ' && buf[18] == '.')
                {
                    //Main motor runs命令,比如Main motor runs 22.
                    if(buf[16] >= '1' && buf[16] <= '9' && buf[17] >= '1' && buf[17] <= '9')//确定发来的步数是数字
                    {
                        en = 1;
                        P27 = 1;
                        P26 = 1;
                        P25 = 1;
                        P24 = 0;//D5亮
                        SBUF = en + 48;
                        step_B = 8 * (((buf[16] - 48) * 10 + (buf[17] - 48)));
                        motorRun = 1;
                    }
                }
            }
            else if(len == 18)//要求主转盘转动相应格数(<=9) 或 设定针臂电机两速度参数
            {
                if(buf[0] == 'M' && buf[1] == 'a' && buf[2] == 'i' && buf[3] == 'n' && buf[4] == ' ' && buf[5] == 'm' && buf[6] == 'o' && buf[7] == 't' && buf[8] == 'o' && buf[9] == 'r' && buf[10] == ' ' && buf[11] == 'r' && buf[12] == 'u' && buf[13] == 'n' && buf[14] == 's' && buf[15] == ' ' && buf[17] == '.')
                {
                    //Main motor runs命令,比如Main motor runs 22.
                    if(buf[16] >= '1' && buf[16] <= '9')//确定发来的步数是数字
                    {
                        en = 1;
                        P27 = 1;
                        P26 = 1;
                        P25 = 1;
                        P24 = 0;//D5亮
                        SBUF = en + 48;
                        step_B = 8 * (buf[16] - 48);
                        motorRun = 1;
                    }
                }
                //Arm speeds 40, 40.命令
                if(buf[0] == 'A' && buf[1] == 'r' && buf[2] == 'm' && buf[3] == ' ' && buf[4] == 's' && buf[5] == 'p' && buf[6] == 'e' && buf[7] == 'e' && buf[8] == 'd' && buf[9] == 's' && buf[10] == ' ' && buf[13] == ',' && buf[17] == '.')
                {
                    if(buf[11] >= '0' && buf[11] <= '9' && buf[12] >= '0' && buf[12] <= '9' && buf[15] >= '0' && buf[15] <= '9' && buf[16] >= '0' && buf[16] <= '9')
                    {
                        //确认发来的是数字
                        A1 = (buf[11] - 48) * 10 + (buf[12] - 48);
                        A2 = (buf[15] - 48) * 10 + (buf[16] - 48);
                    }
                }
            }
            else if(len == 9)//要求主转盘转动的方向
            {
                //Rotate 0/Rotate 1命令
                if(buf[0] == 'R' && buf[1] == 'o' && buf[2] == 't' && buf[3] == 'a' && buf[4] == 't' && buf[5] == 'e' && buf[6] == ' ' && buf[8] == '.')
                {
                    if(buf[7] == '0')
                    {
                        direction = 0;//顺时针
                    }
                    else if(buf[7] == '1')
                    {
                        direction = 1;//逆时针
                    }
                }
            }
            else if(len == 20)//要求针臂在底部停留时间的两参数
            {
                //Arm delays 200, 500.命令
                if(buf[0] == 'A' && buf[1] == 'r' && buf[2] == 'm' && buf[3] == ' ' && buf[4] == 'd' && buf[5] == 'e' && buf[6] == 'l' && buf[7] == 'a' && buf[8] == 'y' && buf[9] == 's' && buf[10] == ' ' && buf[14] == ',' && buf[15] ==' ' && buf[19] == '.')
                {
                    if(buf[11] >= '0' && buf[11] <= '9' && buf[12] >= '0' && buf[12] <= '9' && buf[13] >= '0' && buf[13] <= '9' && buf[16] >= '0' && buf[16] <= '9' && buf[17] >= '0' && buf[17] <= '9' && buf[18] >= '0' && buf[18] <= '9')
                    {
                        //确认发来的是数字
                        S1 = (buf[11] - 48) * 100 + (buf[12] - 48) * 10 + (buf[13] - 48);
                        S2 = (buf[16] - 48) * 100 + (buf[17] - 48) * 10 + (buf[18] - 48);
                    }
                }
            }
        }
    }
    else if(TI == 1)//如果发送数据完毕
    {
        TI = 0;
    }
}

int main()
{
    TMOD = 0x21;
    TH0 = 0x3C;
    TL0 = 0xB0;
    IE = 0x92;
    P20 = 0;//给虚拟接口卡P1.0发脉冲,以驱动主转盘步进电机
    P22 = 0;//给虚拟接口卡P1.2发脉冲,以驱动针臂步进电机
    TR0 = 1;//启动定时器0
    //
    SCON = 0x50;
    TH1 = 0xe6;
    TL1 = 0xe6;
    TR1 = 1;//启动定时器1
    RI = 0;
    TI = 0;
    IP = 0x10;//提升串口中断的优先级
    P21 = 0;//主转盘电机方向, 默认为顺时针
    while(1)
    {
        //如果en = 1开启timer0的中断, 否则将timer0的中断关闭
        if(en == 1)
        {
            IE = 0x92;
        }
        else if(en == 0)
        {
            IE = 0x90;
        }
    }
}
/*
P1.0:转盘电机Pulse信号
P1.1:转盘电机Dir -> P21
P1.2:针臂电机Pulse
P1.3:针臂电机Dir
P0口:输出口,连接虚拟软件中的传感器信号
P0.0:霍尔传感器信号,平时为高电平,有效时为低电平 -> P00
P0.1:针臂上限位信号
P0.2:针臂下限位信号

*/

 

没有更多推荐了,返回首页