下面介绍足疗机的软件设计。按照前面的需求分析,总结功能如下:
● 红外接收与解码;
● 键盘处理和LED的显示;
● 电动机两种工作模式;
● 电动机三挡速度的设置;
● 电热丝高低温度的控制;
● 定位程序。
表2-5和表2-6分别是程序用到的变量名和函数名。
表2-5 程序用到的变量名
续表
表2-6 程序用到的函数名
首先谈谈单片机的资源分配问题。对时间要求高的是红外和PWM,其余的直接在主程序中处理。红外接收用外中断0来实现,由于采用的单片机没有PWM功能,为了能够控制电动机和电热丝的电压,用定时器模拟PWM的产生。红外通信用最高级的中断,而两个PWM分别控制电动机和电热丝,在处理红外通信时PWM会产生非常短暂的停顿,由于红外通信的时间是在200ms内,如此短的时间对电动机输出不会产生明显的影响,因此也就是不影响用户的使用体验。
以下为红外通信中断程序,其输出是按键号,就是对应停止、模式、速度、高低温中的一个。从 图2-10 主控板原理图可以看出,红外接收电路VS1838B的输出连接到STC11F02的外部中断0,当没有红外信号进来时,引脚为高电平,只要有红外信号,便成为低电平,从而引起外中断程序执行。
图2-53是遥控器发出后接收端经过VS1838B检波输出的波形。注意,这和VS1838B发出的原始波形是不同的,原始波形是38kHz的经过调制后的载波,而VS1838B内部已经对载波进行处理,输出的是调制波。如果不用VS1838B而用分立元件自己做,需要注意这个问题。
图2-53 红外遥控波形
从波形上可以看到,开始9ms为低,之后4.5ms为高,表示这是红外数据的开始,然后便是数据通信。由于要计算红外高低电平长短,因此还需要定时器0的配合。
以下是相应的红外接收程序。
红外数据的格式分为4字节,第一字节定义为0,第二字节定义为0xff,第三字节定义为数据A,第4字节为数据A的反码。
定义键1为0,键2为4,键3为8,键4为0x0c。
以下分析代码。首先,这个中断是低电平引起后才进入的。
定义中断0,告诉编译器使用寄存器组1。
定义循环变量。
清零定时器0。注意,主程序在初始化时就让定时器0一直运行着。
等待低电平结束,因为显示程序是主程序中循环调用的,并未用中断实现,因此这里如果一直等待显示会停下来,表现的结果是LED灯在这段时间一直亮。为了避免这种情况出现,需要调用显示程序。
如果TH0>12,说明低电平持续时间至少为9ms,否则是干扰信号,忽略并退出。如果是正常,就清零定时器0。
这一段和上一段意思一样,不同的是持续时间为TH>6,也就是4.5ms高电平时间。
接收4字节,因此循环4次。
以下介绍对单独1字节的接收。
首先是对当前接收的字节清零,以消除上次接收的数据。
然后对每一比特进行处理,也就是高低电平的处理,1字节共8比特,如图2-54所示。
图2-54 红外遥控中0和1的波形
对比特进行分析可以看出,1和0的不同在于高电平持续的时间不同,而在低电平时间上是一样的。
以下开始进行比特的接收。
等待高电平的到来,在等待的同时调用LED显示程序,避免LED停止扫描显示。
高电平已经来了,立刻清零定时器0。
等待高电平结束,在等待的同时调用LED显示程序,避免LED停止扫描显示。
如果TH0>1,则一定是持续时间满足了1的高电平时间,因此字节的对应位置位;否则就是0的高电平时间,对应位不用做任何动作,因为前面字节初始化时就是0了。
由于遥控器的红外发射通信定义了前面2字节固定是0和0xff,因此如果接收到的不是这个,则肯定是出问题了,要么用的遥控器有问题,要么受到干扰。此时应该忽略本次接收,退出中断。
以上4句代码的含义相同,以第一句为例,如果第三字节是0并且第四字节是0的反码0xff,则对应的红外按键是1,也就是和控制面板上按S1按键的效果相同。在4字节全部接收完毕后,中断程序结束。输出结果是virtual_key。
下面介绍PWM模拟产生程序,该程序采用定时器1中断模拟产生。
在程序的定义部分有:
表示将电动机PWM输出MOTO定义为P1.5,将加热PWM输出HEAT定义为P1.6。
首先定义电动机控制PWM时间变量 m_tmp和电热丝PWM时间变量btm_tmp为静态变量,也就是每次重新载入时能保持上次的数据。
图2-55 PWM周期
上面代码中MAX_VAL是PWM的周期,speed是当前电动机速度的PWM占空时间,从足疗机电源板原理图可以看到,PWM到电动机的实际驱动是反相的,也就是当MOTO为高电平时电动机不转,为低电平时才转动。由图2-55可以看出,白色部分是控制电动机开通的时间,右边灰色部分是控制电动机断电的时间。从代码可以知道,当目前时间进入右边区域时,控制电动机断电。
上述两句代码的意思和电动机控制的含义相同,是用来控制电热丝的。
如果PWM时间变量 btm_tmp达到周期时间,则清零该变量。
如果PWM时间变量 m_tmp达到周期时间,则清零该变量。
LED的扫描显示和普通静态显示相比的优点是可以节约I/O的数量,也就是简化硬件,当然缺点是软件编写麻烦。对于家用电器这类对成本比较敏感的产品,可以采用这种方法。为方便学习,以下将显示的原理图用图2-10重新绘出,如图2-56所示。原理很简单,就是LED灯分时显示,依靠视觉暂留现象,使LED看上去的效果和单独的I/O点亮一样。下面结合显示子程序软件进行说明。
图2-56 LED 和按键
以上灯和功能的对应为:
● DL1——启/停;
● DL2——低温;
● DL3——高温;
● DL4——模式1;
● DL5——模式2;
● DL6——低速;
● DL7——中速;
● DL8——高速。
键盘和功能的对应为:
● S1——停止;
● S2——加热;
● S3——模式;
● S4——速度。
变量cnt表示虚拟计数器。
如果cnt到了显示的循环周期,则清零。
按照cnt目前的数值进行切换显示。
如果目前cnt到10了,则关闭所有的LED灯。
选通图2-56最下面三个LED的阴极。
根据目前的速度挡次变量来决定对应的LED是否点亮。例如,第一句表示,如果FAST_SLOW_III变量为真,则选1即P1_2为高,反之为低。
如果目前cnt到20了,则关闭所有的LED灯。
选通图2-56中间三个LED的阴极。
根据目前的模式选择变量来决定对应的LED是否点亮。例如,第一句表示,如果PGM_II变量为真,则选1即P1_2为高,反之为低。
根据目前的高温选择变量HOT_Hi来决定对应的LED是否点亮。如果HOT_Hi变量为真,则选1即P1_4为高,反之为低。
如果目前cnt到30了,则关闭所有的LED灯。
选通图2-56最上方两个LED的阴极。
根据目前的低温选择变量HOT_Lo来决定对应的LED是否点亮。
上面代码的第一句表示如果机器运行标志置位,则对应的运行灯点亮。
下面几句的意思是,当机器没有启动时,灯表现为一闪一闪,如果机器正在定位,对应的灯也为闪烁。当然这需要结合整体的程序才能完全理解。一般而言,开发产品做程序时先编写主要功能,并进行调试,一些次要功能可最后添加。
下面的程序是以查询方式执行的,可以发现里面用了巧妙的方法避免查询引起的延迟。
定义循环变量i。
如果红外遥控没有按键按下,就进入面板上键盘按下与否的判断程序。
通过判断K1、K2、K3、K4是否都是高电平来了解是否有按键按下。如果是,则进一步判断keytag标志是否为1,这是为了防止持续按一个按键重复执行动作。Keytag表示当一个按键按下后置位,松开后清零。如果是持续按的,就退出,不再执行下面的程序。
如果按键都是松开的,则清零keytag标志,并返回。
延迟时间20ms,应对键盘的弹簧片抖动。
延迟大约20ms后,如果发现键都松开了,说明是干扰导致的,不是真正地按下键。这种情况在键盘线比较长或者干扰大的场合经常发生,为了产品的稳定性,在软件上需要进行抗干扰设计。
如果确实是按下键,置键盘按下标志。
如果目前面板上的键或者遥控器上的键有按下,继续执行。
如果按下了S1按键,或者在遥控器上按了停止按钮,执行以下程序。
pgm_style= =0表示停止,pgm_style= =1表示模式1,pgm_style= =1表示模式2,如果目前不是停止状态,则一定是运行状态。从运行状态进入到停止状态需要让电动机运转到定位处,这样才可以把脚从按摩器中取出。
运行标志run_tag清零,pgm_style清零,加热变量heat_var清零,此为停止的状态。
如果按了S2按键,或者遥控器上的加热键按下过,则加热变量增加1,0表示不加热,1表示低温,2表示高温。
如果按了S3按键,或者遥控器上的模式按钮按下过,则模式加1,0表示停止,1表示模式1,2表示模式2。
如果刚刚开机,则进行定位。
如果按了S4按键,或者遥控器上的速度按键按下过,则速度变量加1,0表示慢速,1表示中速,2表示快速。
蜂鸣器叫一下,提示用户。
清零遥控按键标志。
注意,以下程序为了理解方便,对原始程序进行了适当的删减,主要是涉及延迟的事项。程序的按钮为查询方式,所以如果执行以下程序时按下按钮,将无法响应,因此在原始程序的延迟中添加了对按钮的查询,并且一旦发现按钮按下,则立刻退出并执行按钮程序。由于查询按钮用时很短,因此不会对延迟产生大的影响。
定义循环变量。
速度有两个变量,speed表示当前设置的速度,speed_bak是对原来的速度进行备份。
以下节拍循环运行10次。
内循环对应断续模式节拍表(见表2-1)的第3列。
对应断续模式节拍表的1~11项的(1,2)、(3,4)、(5,6)、(7,8)、(9,10)、(11,12),每一对的执行都相同,因此循环6次重复执行。
speed恢复初始设置,也就是正常运行的速度。
按照表2-1中序号1的要求延迟。
按照表2-1中序号1的要求,速度设置为0。
按照表2-1中序号1的要求延迟。
按照表2-1中序号2的要求循环13次。
速度恢复为初始值。
按照表2-1中序号2的要求,速度设置为0。
按照表2-1中序号2的要求延迟。
执行表2-1中序号3~11。
延迟需要查表,因为延迟节拍的要求都放在延迟表格中,在程序的开头有相关全局定义如下:
恢复速度为初始值。
延迟,按照索引查表。
整个模式运行完毕。
关闭加热,停止电动机运转。
定位程序如下:
定位程序的作用是模拟计数变量,实现长时间的计数。
速度下降为最低挡。
清零定时器0。
如果槽形光耦没有被遮光板挡住。
每当定时器0的TH0达到120的时候,清零自己,并且cnt增加,用此方法实现cnt的增加。
如果cnt超过150,则退出。这用于万一槽形光耦的遮光板出现故障(经常发生折断),可自动停止。
当遮光板进入的时候,延迟,防止干扰。
清零TH0。
重置cnt为1。
只要遮光板在槽形光耦中就运行以下程序。
每当定时器0的TH0达到120的时候,清零自己,并且cnt增加,用此方法实现cnt的增加。
如果cnt超过150,则退出。这用于万一槽形光耦的遮光板出现故障(螺钉滑落,遮光板一直在槽形光耦中),可自动停止。
本程序首先是键盘处理,读取按了哪个键,然后对显示面板上的LED进行点灯,接着按照加热选择设置电热丝的PWM数值,最后按照电动机运转选择模式设置电动机运转的PWM数据。
扫描键盘。
如果目前是停止标志,
则加热清零。
速度清零。
根据加热变量处理。
如果不用加热。
则电热丝的PWM参数hot设置为0。
高温对应的发光指示灯亮。
低温对应的发光指示灯亮。
如果运行的电动机工作模式为0,则停止标志清零,表示停止。
电热丝的PWM参数hot设置为MID_HOT。
高温对应的发光指示灯灭。
低温对应的发光指示灯亮。
运行标志置位。
电热丝的PWM参数hot设置为HIGH _HOT。
高温对应的发光指示灯亮。
低温对应的发光指示灯灭。
运行标志置位。
根据运行电动机模式选择。
电动机停止模式。
间断模式指示灯灭。
持续模式指示灯灭。
低速指示灯灭。
中速指示灯灭。
高速指示灯灭。
如果加热变量为0,则停止标志清零。这种情况是电动机可以不转,仅电热丝加热,但当电热丝停止加热时,运行进入停止状态。
间断模式。
间断模式指示灯亮。
持续模式指示灯灭。
运行标志置位。
电动机持续运转模式。
间断模式指示灯灭。
持续模式指示灯亮。
运行标志置位。
如果电动机运转模式不是停止,
则根据转速变量选择。
低速。
低速指示灯亮。
中速指示灯灭。
高速度指示灯灭。
电动机速度PWM设置数值为SLOW。
中速情况。
低速指示灯灭。
中速指示灯亮。
高速指示灯灭。
速度PWM设置数值为MID。
高速情况。
低速指示灯灭。
中速指示灯灭。
高速度指示灯亮。
速度PWM设置数值为FAST。
主函数main如下:
定义长整型i。
初始化P1口配置寄存器,对输入/输出进行设置。
初始化P3口配置寄存器。
设置I/O的初始状态。
蜂鸣器响一下。
电动机速度为0。
初始化定时器配置。
定时器1初始化。
定时器0中断允许。
外中断允许。
开中断。
调主控制函数。
如果用户设置为停止,
则电动机和加热停止。
定位标志清零。
根据电动机模式选择。
不运转情况。
间断模式。
调间断模式子程序。
持续模式。
延迟。
软件计数器i增加。
当i达到97的时候,
清零i。
清零加热变量。
电动机停止,面板显示停止LED。
至此,足疗机的设计介绍完毕。
从第3章开始,将在本章的基础上更加深入一步,介绍乒乓自动发球机的设计。乒乓自动发球机也叫乒乓陪练机,可以在一个人的情况下和机器打乒乓球。