二自由度自动进样检测器控制(Version 1.1)

较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:针臂下限位信号

*/

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
关于Frmresize1.1的说明: FRMRESIZE VERSION 1.1 (CLASS) ---------------------- 作者: SUNVFP Mail: SUNVFP@EYOU.COM 开发日期:2002.10.27 改进日期:2002.10.29 简介: ------------ 有许多狐友关心不同分辨率下表单的显示问题和改变表单大小时表单内各控件的相应改变问题, 也有相当多的狐友写过这方面的类。 我所见过的resize类在使用中都有大大小小的不如人意之处: 如:vfp自己的resize类示例,不支持嵌套等;老外resize类,需要fll动态链接库支持,并且当 控件数量超过256时就会出错等。还有算法不严密,造成控件失位,Frmresize1.0就有这方面的BUG。 我决定重新写一个,代码很简单。大家不妨试用一下,并请不吝提出要求,以方便改进,使之成 为通用类,使后来者少走弯路。 1)Frmresize可以改变字体的相应大小; 2)Frmresize没有嵌套层数的限制,没有控件数量的限制; 3)Frmresize可以有选择的控制各控件是否改变,及如何改变; 4)Frmresize可以自适应不同分辨率。 改进: —————————— 1)增加NoHeightClassList 、NoHeightObjectList 两个属性,可以控制控件的高度是否变化; 2)改进算法,彻底消除失位现象。不论如何调整表单大小,控件的相对位置都不会失位!; 3)因算法的变化,去掉两个不再需要的自定义属性。 用法: ----- 要使用 Frmresize 1.1 必须按以下两步: 添加该类到你的表单, 并设置它的属性. 1) 将 Frmresize 类拖放到你的表单 2) 设置它的属性: 设置类的 FontResize 属性 (在属性窗口的末端) (.T.(默认值)-字体随着作相应大小的改变,.F.-字体大小不变) 设置类的 NoPosClassList 属性 (在属性窗口的末端) (不作位置变化的基类列表,例如commandbutton text等,timer custom hyperlink已排除) 设置类的 NoSizeClassList 属性 (不作大小变化的基类列表,例如commandbutton text等,timer custom hyperlink已排除) 设置类的 NoPosObjectList 属性 (不作位置变化的控件名称列表,例如txt1 COMMAND1 CMDOK等) 设置类的 NoSizeObjectList 属性 (不作大小变化的控件名称列表,例如txt1 COMMAND1 CMDOK等) 设置类的 NoHeightClassList 属性 (不作高度变化的基类列表,例如commandbutton text等,timer custom hyperlink已排除) 设置类的 NoHeightObjectList 属性 (不作高度变化的控件名称列表,例如txt1 COMMAND1 CMDOK等) 注:1。当NoPosClassList和NoSizeClassList 或 NoPosObjectList和NoSizeObjectList中同时包含时,则相关控件及其下层控件不变化。 2。NoSizeClassList或NoSizeObjectList中的相应控件的字体大小不变。 3) 在表单resize事件中写:this.frmresize1.frmresize() 注: 不带任何参数。 4) 在表单init事件中写:this.frmresize1.frmresize(800,600) 注: 参数800,600是指你开发时的屏幕分辨率。 许可: 该类可以没有问题地添加到你的项目. 我要求的唯一东西是如果你改进了程序请让我知道. 发送 Bug 和建议到: sunvfp@eyou.com 或到天堂论坛进行讨论 www.myf1.net
### 回答1: CoaXPress标准版本1.1是一种高速串口技术标准,用于在计算机和图像传感之间传输图像和数据。这个标准是由一个由多家公司组成的联盟共同开发的,为了解决高速数据传输过程中的问题。 此标准的主要特点是: 1. 高速传输:采用同轴电缆传输,可达到每秒6.25 Gbps的传输速度。 2. 双向通信:支持同时进行传输和控制,能够实现图像采集设备的双向通信。 3. 长距离传输:传输距离可达到超过100米。 4. 多路复用:支持多个接收设备与一个主设备相连,实现多路复用。 CoaXPress标准版本1.1的应用范围非常广泛,包括机视觉、医疗成像、航空航天、工程测试等领域。此标准可以保证高速、准确、稳定的数据传输,为图像采集和处理提供了更大的空间和灵活性。 ### 回答2: CoaXPress标准版本1.1是一种高速数字视频传输协议,它基于同名标准的最新版本,并且在原来的协议基础上进行了一些改进和升级。该协议可以使用同一条协议电缆传输多个高速视频流,实现高速、稳定、可靠的视频数据传输。 该标准版本1.1的最重要的改进是增加了新的特性,如基于多通道的同步触发和多流同步,这些特性可以更好地支持多摄像机的同步工作。此外,该协议还提供了更大的灵活性,可支持更高的带宽速率,同时增强了对断电和短路等故障的检测和防护机制,提高了系统的稳定性和可靠性。 总的来说,CoaXPress标准版本1.1是一个完备、可靠和先进的数字视频传输协议,可以广泛应用于工业自动化、机视觉、医疗和安防等领域,为用户带来更好的视频传输体验和更好的系统性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好梦成真Kevin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值