从单片机基础到程序框架(全集 2019pdf版).pdf - 第583页
移动 2 秒 ,移动 2 秒后 开始原 路返 回, “ 机械 手”向 上移动 ,碰 到“ 上感 应器” 后, 滑块 开始 往左 边移动 , 移动 3 秒后默认已 经回到原位 最左边 ,此时“计数 器”累加 1 ,完成一次 过程,如果 再按下启动 按键,继 续 重复这个过 程。 这个设备用 了 2 个气缸。1 个“水平气缸” 驱动滑块水 平方向的左 右移动,当 控制“水平 气缸” 的输出 信号为 0 时往左边跑 , 当控制 “水平 气缸”…

第一百一十一节: 工业自动化设备的开关信号的运动控制。
【111.1 开关信号的运动控制。】
上图 111.1.1 独立按键
上图 111.1.2 LED 电路
上图 111.1.3 有源蜂鸣器的电路
本节涉及的知识点有,switch 的过程控制,时间延时,开关感应器的软件滤波,工件计数器,以及整体
的软件框架。
现在有一台设备,水平方向有一个滑块,能左右移动,滑块上安装了一个能垂直伸缩的“机械手”。按
下启动按键后,滑块先从左边往右边移动,移到最右边碰到“右感应器”后,滑块上的“机械手”开始往下

移动 2 秒,移动 2 秒后开始原路返回,“机械手”向上移动,碰到“上感应器”后,滑块开始往左边移动,
移动 3 秒后默认已经回到原位最左边,此时“计数器”累加 1,完成一次过程,如果再按下启动按键,继续
重复这个过程。
这个设备用了 2 个气缸。1 个“水平气缸”驱动滑块水平方向的左右移动,当控制“水平气缸”的输出
信号为 0 时往左边跑,当控制“水平气缸”的输出信号为 1 时往右边跑。另 1 个“垂直气缸”驱动“机械手”
的上下移动,当控制“垂直气缸”的输出信号为 0 时往上边跑,当控制“垂直气缸”的输出信号为 1 时往下
边跑。
这个设备用了 2 个开关感应器。分别是“右感应器”和“上感应器”。当感应器没有被碰到的时候信号
为 1,当感应器被碰到的时候信号为 0。
这个设备用了 1 个独立按键。控制运动的启动。
2 个气缸是输出信号,用 P1.4 和 P1.5 所控制的两个 LED 模拟。2 个开关感应器是输入信号,用 K2 和 K3
这两个独立按键模拟。1 个独立按键用 K1 按键。如上图。
#include "REG52.H"
#define KEY_VOICE_TIME 50
#define KEY_FILTER_TIME 25
#define SENSOR_TIME 20 //开关感应器的“滤波”时间
void T0_time();
void SystemInitial(void) ;
void Delay(unsigned long u32DelayTime) ;
void PeripheralInitial(void) ;
void BeepOpen(void);
void BeepClose(void);
void GoLeft(void) ; //“水平气缸”往左跑
void GoRight(void); //“水平气缸”往右跑
void GoUp(void); //“垂直气缸”往上跑
void GoDown(void); //“垂直气缸”往下跑
void VoiceScan(void);
void SensorScan(void); //开关感应器的消抖,在定时中断里调用处理
void KeyScan(void);
void KeyTask(void);
void RunTask(void); //运动控制的任务函数
sbit P1_4=P1^4; //水平气缸的输出
sbit P1_5=P1^5; //垂直气缸的输出
sbit P3_4=P3^4; //蜂鸣器的输出口

sbit KEY_INPUT1=P2^2; //【启动】按键 K1 的输入口。
sbit SensorRight_sr=P2^1; //右感应器的输入口
sbit SensorUp_sr=P2^0; //上感应器的输入口
volatile unsigned char vGu8SensorRight=0; //右感应器经过滤波后的当前电平状态。
volatile unsigned char vGu8SensorUp=0; //上感应器经过滤波后的当前电平状态。
volatile unsigned char vGu8BeepTimerFlag=0;
volatile unsigned int vGu16BeepTimerCnt=0;
volatile unsigned char vGu8KeySec=0;
unsigned char Gu8RunStart=0; //启动的总开关
unsigned char Gu8RunStatus=0; //运动的状态,0 为停止,1 为运行
unsigned int Gu16RunCnt=0; //计数器
unsigned int Gu16ReturnLeftTime=3000; //水平往左跑的延时变量,默认为 3 秒
unsigned int Gu16GoDownTime=2000; //垂直往下跑的延时变量,默认为 2 秒
volatile unsigned char vGu8RunTimerFlag=0; //用于控制运动过程中的延时的定时器
volatile unsigned int vGu16RunTimerCnt=0;
void main()
{
SystemInitial();
Delay(10000);
PeripheralInitial();
while(1)
{
KeyTask(); //按键的任务函数
RunTask(); //运动控制的任务函数
}
}
/* 注释一:
* 两个“计时器”相互“清零”相互“抗衡”,从而实现了开关感应器的“消抖”处理,
* 专业术语也叫“软件滤波”。这种滤波方式,不管是从“高转成低”,还是“低转成高”,
* 如果在某个瞬间出现干扰抖动,某个计数器都会及时被“清零”,从而起到非常高效的消抖滤波作用。
*/
void SensorScan(void) //此函数放在定时中断里每 1ms 扫描一次,用来识别和滤波开关感应器
{
static unsigned int Su16SensorRight_H_Cnt=0; //判断高电平的计时器