微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 第25节:用LED灯和按键来模拟工业自动化设备的运动控制

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

时间:11-22 来源:互联网 点击:
LED灯的状态都要更新一次。

unsigned char ucLedStatus16_09=0; //代表底层74HC595输出状态的中间变量
unsigned char ucLedStatus08_01=0; //代表底层74HC595输出状态的中间变量

unsigned intuiRunTimeCnt=0;//运动中的时间延时计数器变量
unsigned char ucRunStep=0;//运动控制的步骤变量

void main()
{
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也难。这里所说的"难"是指要经过去抖处理。
*/

void sensor_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; //说明感应器确实被接触到了
}
}
}

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

if(key_sr1==1)//IO是高电平,说明按键没有被按下,这时要及时清零一些标志位
{
ucKeyLock1=0; //按键自锁标志清零
uiKeyTimeCnt1=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。
}
else if(ucKeyLock1==0)//有按键按下,且是第一次被按下
{
uiKeyTimeCnt1++; //累加定时中断次数
if(uiKeyTimeCnt1>const_key_time1)
{
uiKeyTimeCnt1=0;
ucKeyLock1=1;//自锁按键置位,避免一直触发
ucKeySec=1; //触发1号键
}
}

}

void key_service() //按键服务的应用程序
{
switch(ucKeySec) //按键服务状态切换
{
case 1:// 启动按键 对应朱兆祺学习板的S1键
if(ucLeftSr==0)//处于左上角原点位置
{
ucRunStep=1; //启动
uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。
}

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

}
}

void led_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(ucLedStatus16_09,ucLedStatus08_01);//74HC595底层驱动函数

}
}

void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)
{
unsigned char i;
unsigned char ucTempData;
hc595_sh_dr=0;
hc595_st_dr=0;

ucTempData=ucLedStatusTemp16_09;//先送高8位
for(i=0;i<8;i++)
{
if(ucTempData>=0x80)hc595_ds_dr=1;
else hc595_ds_dr=0;

hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
delay_short(15);
hc595_sh_dr=1;
delay_short(15);

ucTempData=ucTempData<1;
}

ucTempData=ucLedStatusTemp08_01;//再先送低8位
for(i=0;i<8;i++)
{
if(ucTempData>=0x80)hc595_ds_dr=1;
else hc595_ds_dr=0;

hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
delay_short(15);
hc595_sh_dr=1;
delay_short(15);

ucTempData=ucTempData<1;
}

hc595_st_dr=0;//ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来
delay_short(15);
hc595_st_dr=1;
delay_short(15);

hc595_sh_dr=0; //拉低,抗干扰就增强
hc595_st_dr=0;
hc595_ds_dr=0;

}

void left_to_right()//从左边移动到右边
{
ucLed_dr1=1; // 1代表左右气缸从左边移动到右边

ucLed_update=1;//刷新变量。每次更改LED灯的状态都要更新一次。
}
void right_to_left() //从右边返回到左边
{
ucLed_dr1=0; // 0代表左右气缸从右边返回到左边

ucLed_update=1;//刷新变量。每次更改LED灯的状态都要更新一次。
}
void up_to_down() //从上边移动到下边
{
ucLed_dr2=1; // 1代表上下气缸从上边移动到下边

ucLed_update=1;//刷新变量。每次更改LED灯的状态都要更新一次。
}
void down_to_up() //从下边返回到上边
{
ucLed_dr2=0; // 0代表上下气缸从下边返回到上边

ucLed_update=1;//刷新变量。每次更改LED灯的状态都要更新一次。
}

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

switch(ucRunStep)
{
case 0: //机械手处于左上角原点的位置,待命状态。此时触发启动按键ucRunStep=1,就触发后续一些列的连续动作。

break;

case 1: //机械手从左边往右边移动
left_to_right();
ucRunStep=2;//这就是鸿哥传说中的怎样灵活控制步骤变量
break;

case 2: //等待机械手移动到最右边,直到触发了最右边的开关感应器。
if(ucRightSr==0)//右边感应器被触发
{
ucRunStep=3;//这就是鸿哥传说中的怎样灵活控制步骤变量
}
break;

case 3: //机械手从右上边往右下边移动,从上往下。
up_to_down();
ucRunStep=4;//这就是鸿哥传说中的怎样灵活控制步骤变量
break;

case 4: //等待机械手从右上边移动到右下边,直到触发了右下边的开关感应器。
if(ucDownSr==0)//右下边感应器被触发
{
uiRunTimeCnt=0;//时间计数器清零,为接下来延时1秒钟做准备
ucRunStep=5;//这就是鸿哥传说中的怎样灵活控制步骤变量
}
break;

case 5: //机械手在右下边延时1秒
if(uiRunTimeCnt>const_1s)//延时1秒
{
ucRunStep=6;//这就是鸿哥传说中的怎样灵活控制步骤变量
}
break;
case 6: //原路返回,机械手从右下边往右上边移动。
down_to_up();
ucRunStep=7;//这就是鸿哥传说中的怎样灵活控制步骤变量
break;

case 7: //原路返回,等待机械手移动到最右边的感应开关
if(ucRightSr==0)
{
ucRunStep=8;//这就是鸿哥传说中的怎样灵活控制步骤变量
}
break;

case 8: //原路返回,等待机械手从右边往左边移动
right_to_left();
ucRunStep=9;//这就是鸿哥传说中的怎样灵活控制步骤变量

break;

case 9: //原路返回,等待机械手移动到最左边的感应开关,表示返回到了原点
if(ucLeftSr==0) //返回到左上角的原点位置
{
ucRunStep=0;//这就是鸿哥传说中的怎样灵活控制步骤变量
}
break;
}
}

void T0_time()

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top