第二十五节.docx

上传人:b****6 文档编号:8038767 上传时间:2023-01-28 格式:DOCX 页数:14 大小:20.28KB
下载 相关 举报
第二十五节.docx_第1页
第1页 / 共14页
第二十五节.docx_第2页
第2页 / 共14页
第二十五节.docx_第3页
第3页 / 共14页
第二十五节.docx_第4页
第4页 / 共14页
第二十五节.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

第二十五节.docx

《第二十五节.docx》由会员分享,可在线阅读,更多相关《第二十五节.docx(14页珍藏版)》请在冰豆网上搜索。

第二十五节.docx

第二十五节

第二十五节:

用LED灯和按键来模拟工业自动化设备的运动控制。

开场白:

前面三节讲了独立按键控制跑马灯的各种状态,这一节我们要做一个机械手控制程序,这个机械手可以左右移动,最左边有一个开关感应器,最右边也有一个开关感应器。

它也可以上下移动,最下面有一个开关感应器。

左右移动是通过一个气缸控制,上下移动也是通过一个气缸控制。

而单片机控制气缸,本质上是通过三极管把信号放大,然后控制气缸上的电磁阀。

这个系统机械手驱动部分的输出和输入信号如下:

  2个输出IO口,分别控制2个气缸。

对于左右移动的气缸,当IO口为0时往左边跑,当IO口为1时往右边跑。

对于上下移动的气缸,当IO口为0时往上边跑,当IO口为1时往下边跑。

    3个输入IO口,分别检测3个开关感应器。

感应器没有被触发时,IO口检测为高电平1。

被触发时,IO口检测为低电平0。

这一节继续要教会大家两个知识点:

第一点:

如何用软件进行开关感应器的抗干扰处理。

第二点:

如何用Switch语句搭建工业自动控制的程序框架。

还是那句话,我们只要以Switch语句为支点,再复杂再繁琐的程序都可以轻松地编写出来。

具体内容,请看源代码讲解。

(1)硬件平台:

基于朱兆祺51单片机学习板。

用矩阵键盘中的S1键作为启动独立按键,用S5按键模拟左边的开关感应器,用S9按键模拟右边的开关感应器,用S13按键模拟下边的开关感应器。

记得把输出线P0.4一直输出低电平,模拟独立按键的触发地GND。

(2)实现功能:

    开机默认机械手在左上方的原点位置。

按下启动按键后,机械手从左边开始往右边移动,当机械手移动到最右边时,机械手马上开始往下移动,最后机械手移动到最右下角的位置时,延时1秒,然后原路返回,一直返回到左上角的原点位置。

注意:

启动按键必须等机械手处于左上角原点位置时,启动按键的触发才有效。

(3)源代码讲解如下:

#include"REG52.H"

#defineconst_voice_short  40  //蜂鸣器短叫的持续时间

#defineconst_key_time1  20  //按键去抖动延时的时间

#defineconst_sensor  20  //开关感应器去抖动延时的时间

#defineconst_1s  500  //1秒钟大概的定时中断次数

voidinitial_myself();   

voidinitial_peripheral();

voiddelay_short(unsignedintuiDelayShort); 

voiddelay_long(unsignedintuiDelaylong);

voidleft_to_right();  //从左边移动到右边

voidright_to_left();//从右边返回到左边

voidup_to_dowm();  //从上边移动到下边

voiddown_to_up();  //从下边返回到上边

voidrun();//设备自动控制程序

voidhc595_drive(unsignedcharucLedStatusTemp16_09,unsignedcharucLedStatusTemp08_01);

voidled_update();  //LED更新函数

voidT0_time();  //定时中断函数

voidkey_service();//按键服务的应用程序

voidkey_scan();//按键扫描函数放在定时中断里

voidsensor_scan();//开关感应器软件抗干扰处理函数,放在定时中断里。

sbithc595_sh_dr=P2^3;   

sbithc595_st_dr=P2^4;  

sbithc595_ds_dr=P2^5;  

sbitbeep_dr=P2^7;//蜂鸣器的驱动IO口

sbitkey_sr1=P0^0;//对应朱兆祺学习板的S1键

sbitleft_sr=P0^1;//左边的开关感应器  对应朱兆祺学习板的S5键   

sbitright_sr=P0^2;//右边的开关感应器  有对应朱兆祺学习板的S9键

sbitdown_sr=P0^3;//下边的开关感应器  对应朱兆祺学习板的S13键

sbitkey_gnd_dr=P0^4;//模拟独立按键的地GND,因此必须一直输出低电平

unsignedcharucKeySec=0;  //被触发的按键编号

unsignedint  uiKeyTimeCnt1=0;//按键去抖动延时计数器

unsignedcharucKeyLock1=0;//按键触发后自锁的变量标志

unsignedcharucLeftSr=0;  //左边感应器经过软件抗干扰处理后的状态标志

unsignedcharucRightSr=0;  //右边感应器经过软件抗干扰处理后的状态标志

unsignedcharucDownSr=0;  //下边感应器经过软件抗干扰处理后的状态标志

unsignedint  uiLeftCnt1=0;  //左边感应器软件抗干扰所需的计数器变量

unsignedint  uiLeftCnt2=0;

unsignedint  uiRightCnt1=0;  //右边感应器软件抗干扰所需的计数器变量

unsignedint  uiRightCnt2=0;

unsignedint  uiDownCnt1=0;  //下边软件抗干扰所需的计数器变量

unsignedint  uiDownCnt2=0;

unsignedint  uiVoiceCnt=0;  //蜂鸣器鸣叫的持续时间计数器

unsignedcharucLed_dr1=0;  //代表16个灯的亮灭状态,0代表灭,1代表亮

unsignedcharucLed_dr2=0;

unsignedcharucLed_dr3=0;

unsignedcharucLed_dr4=0;

unsignedcharucLed_dr5=0;

unsignedcharucLed_dr6=0;

unsignedcharucLed_dr7=0;

unsignedcharucLed_dr8=0;

unsignedcharucLed_dr9=0;

unsignedcharucLed_dr10=0;

unsignedcharucLed_dr11=0;

unsignedcharucLed_dr12=0;

unsignedcharucLed_dr13=0;

unsignedcharucLed_dr14=0;

unsignedcharucLed_dr15=0;

unsignedcharucLed_dr16=0;

unsignedcharucLed_update=1;  //刷新变量。

每次更改LED灯的状态都要更新一次。

unsignedcharucLedStatus16_09=0;  //代表底层74HC595输出状态的中间变量

unsignedcharucLedStatus08_01=0;  //代表底层74HC595输出状态的中间变量

unsignedint  uiRunTimeCnt=0;  //运动中的时间延时计数器变量

unsignedcharucRunStep=0;  //运动控制的步骤变量

voidmain() 

  {

  initial_myself();  

  delay_long(100);  

  initial_peripheral(); 

  while

(1)  

  {

    run();//设备自动控制程序

    led_update();  //LED更新函数

    key_service();//按键服务的应用程序

  }

}

/*注释一:

*开关感应器的抗干扰处理,本质上类似按键的去抖动处理。

唯一的区别是:

*按键去抖动关注的是IO口的一种状态,而开关感应器关注的是IO口的两种状态。

*当开关感应器从原来的1状态切换到0状态之前,要进行软件滤波处理过程,一旦成功地

*切换到0状态了,再想从0状态切换到1状态的时候,又要经过软件滤波处理过程,符合

*条件后才能切换到1的状态。

通俗的话来说,按键的去抖动从1变成0难,从0变成1容易。

*开关感应器从1变成0难,从0变成1也难。

这里所说的"难"是指要经过去抖处理。

*/

voidsensor_scan()//开关感应器软件抗干扰处理函数,放在定时中断里。

{

  if(left_sr==1)  //左边感应器是高电平,说明有可能没有被接触  对应朱兆祺学习板的S5键  

  {

    uiLeftCnt1=0;//在软件滤波中,非常关键的语句!

类似按键去抖动程序的及时清零

    uiLeftCnt2++;//类似独立按键去抖动的软件抗干扰处理

      if(uiLeftCnt2>const_sensor)

      {

        uiLeftCnt2=0;

          ucLeftSr=1;  //说明感应器确实没有被接触

      }

  }

  else  //左边感应器是低电平,说明有可能被接触到了

  {

    uiLeftCnt2=0;//在软件滤波中,非常关键的语句!

类似按键去抖动程序的及时清零

    uiLeftCnt1++; 

      if(uiLeftCnt1>const_sensor)

      {

        uiLeftCnt1=0;

          ucLeftSr=0;  //说明感应器确实被接触到了

      }

  }

  if(right_sr==1)  //右边感应器是高电平,说明有可能没有被接触  对应朱兆祺学习板的S9键  

  {

    uiRightCnt1=0;//在软件滤波中,非常关键的语句!

类似按键去抖动程序的及时清零

    uiRightCnt2++;//类似独立按键去抖动的软件抗干扰处理

      if(uiRightCnt2>const_sensor)

      {

        uiRightCnt2=0;

          ucRightSr=1;  //说明感应器确实没有被接触

      }

  }

  else  //右边感应器是低电平,说明有可能被接触到了  

  {

    uiRightCnt2=0;//在软件滤波中,非常关键的语句!

类似按键去抖动程序的及时清零

    uiRightCnt1++; 

      if(uiRightCnt1>const_sensor)

      {

        uiRightCnt1=0;

          ucRightSr=0;  //说明感应器确实被接触到了

      }

  }

  if(down_sr==1)  //下边感应器是高电平,说明有可能没有被接触  对应朱兆祺学习板的S13键  

  {

    uiDownCnt1=0;//在软件滤波中,非常关键的语句!

类似按键去抖动程序的及时清零

    uiDownCnt2++;//类似独立按键去抖动的软件抗干扰处理

      if(uiDownCnt2>const_sensor)

      {

        uiDownCnt2=0;

          ucDownSr=1;  //说明感应器确实没有被接触

      }

  }

  else  //下边感应器是低电平,说明有可能被接触到了

  {

    uiDownCnt2=0;//在软件滤波中,非常关键的语句!

类似按键去抖动程序的及时清零

    uiDownCnt1++; 

      if(uiDownCnt1>const_sensor)

      {

        uiDownCnt1=0;

          ucDownSr=0;  //说明感应器确实被接触到了

      }

  }

}

voidkey_scan()//按键扫描函数放在定时中断里

{  

  if(key_sr1==1)//IO是高电平,说明按键没有被按下,这时要及时清零一些标志位

  {

    ucKeyLock1=0;//按键自锁标志清零

    uiKeyTimeCnt1=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。

    

  }

  elseif(ucKeyLock1==0)//有按键按下,且是第一次被按下

  {

    uiKeyTimeCnt1++;//累加定时中断次数

    if(uiKeyTimeCnt1>const_key_time1)

    {

      uiKeyTimeCnt1=0; 

      ucKeyLock1=1;  //自锁按键置位,避免一直触发

      ucKeySec=1;  //触发1号键

    }

  }

}

voidkey_service()//按键服务的应用程序

{

  switch(ucKeySec)//按键服务状态切换

  {

  case1:

//启动按键  对应朱兆祺学习板的S1键 

      if(ucLeftSr==0)  //处于左上角原点位置

      {

        ucRunStep=1;//启动

        uiVoiceCnt=const_voice_short;//按键声音触发,滴一声就停。

  

      }        

   

      ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发

      break;   

    

  }           

}

voidled_update()  //LED更新函数

{

  if(ucLed_update==1)

  {

    ucLed_update=0;  //及时清零,让它产生只更新一次的效果,避免一直更新。

    if(ucLed_dr1==1)

        {

          ucLedStatus08_01=ucLedStatus08_01|0x01;

        }

        else

        {

          ucLedStatus08_01=ucLedStatus08_01&0xfe;

        }

    if(ucLed_dr2==1)

        {

          ucLedStatus08_01=ucLedStatus08_01|0x02;

        }

        else

        {

          ucLedStatus08_01=ucLedStatus08_01&0xfd;

        }

    if(ucLed_dr3==1)

        {

          ucLedStatus08_01=ucLedStatus08_01|0x04;

        }

        else

        {

          ucLedStatus08_01=ucLedStatus08_01&0xfb;

        }

    if(ucLed_dr4==1)

        {

          ucLedStatus08_01=ucLedStatus08_01|0x08;

        }

        else

        {

          ucLedStatus08_01=ucLedStatus08_01&0xf7;

        }

    if(ucLed_dr5==1)

        {

          ucLedStatus08_01=ucLedStatus08_01|0x10;

        }

        else

        {

          ucLedStatus08_01=ucLedStatus08_01&0xef;

        }

    if(ucLed_dr6==1)

        {

          ucLedStatus08_01=ucLedStatus08_01|0x20;

        }

        else

        {

          ucLedStatus08_01=ucLedStatus08_01&0xdf;

        }

    if(ucLed_dr7==1)

        {

          ucLedStatus08_01=ucLedStatus08_01|0x40;

        }

        else

        {

          ucLedStatus08_01=ucLedStatus08_01&0xbf;

        }

    if(ucLed_dr8==1)

        {

          ucLedStatus08_01=ucLedStatus08_01|0x80;

        }

        else

        {

          ucLedStatus08_01=ucLedStatus08_01&0x7f;

        }

    if(ucLed_dr9==1)

        {

          ucLedStatus16_09=ucLedStatus16_09|0x01;

        }

        else

        {

          ucLedStatus16_09=ucLedStatus16_09&0xfe;

        }

    if(ucLed_dr10==1)

        {

          ucLedStatus16_09=ucLedStatus16_09|0x02;

        }

        else

        {

          ucLedStatus16_09=ucLedStatus16_09&0xfd;

        }

    if(ucLed_dr11==1)

        {

          ucLedStatus16_09=ucLedStatus16_09|0x04;

        }

        else

        {

          ucLedStatus16_09=ucLedStatus16_09&0xfb;

        }

    if(ucLed_dr12==1)

        {

          ucLedStatus16_09=ucLedStatus16_09|0x08;

        }

        else

        {

          ucLedStatus16_09=ucLedStatus16_09&0xf7;

        }

    if(ucLed_dr13==1)

        {

          ucLedStatus16_09=ucLedStatus16_09|0x10;

        }

        else

        {

          ucLedStatus16_09=ucLedStatus16_09&0xef;

        }

    if(ucLed_dr14==1)

        {

          ucLedStatus16_09=ucLedStatus16_09|0x20;

        }

        else

        {

          ucLedStatus16_09=ucLedStatus16_09&0xdf;

        }

    if(ucLed_dr15==1)

        {

          ucLedStatus16_09=ucLedStatus16_09|0x40;

        }

        else

        {

          ucLedStatus16_09=ucLedStatus16_09&0xbf;

        }

    if(ucLed_dr16==1)

        {

          ucLedStatus16_09=ucLedStatus16_09|0x80;

        }

        else

        {

          ucLedStatus16_09=ucLedStatus16_09&0x7f;

        }

    hc595_drive(ucLed

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1