单片机编程多动作(操作、事件)的设计方法心得(一)

来源:互联网 发布:adblock plus mac 编辑:程序博客网 时间:2024/06/07 20:47
    在写单片机程序的时候,一个程序有几个动作(操作,事件…),几个动作还有某种关系,或互斥,或按时间顺序等等。    本文应该算作程序设计一类,还是比较简单的,权当为梳理记录,不图讲到什么高深道理。   言归正传,设计程序的时候,一定要有分块的概念,大块包含小块,正如人类逻辑上的包含关系。比如一套广播体操分,几套动作,每一套动作分几Part简单的重复动作。那么我们应该认识到,这些简单的重复动作是不可再分割的,所以原则上,我们可以先把这些简单动作写成一个一个函数,至于后面的设计,可能需要合并这些函数,但是思维上把这些动作分割开是首要的。

【互斥动作】

比如机器的某个关节的几个动作是互斥的,下面以头部关节的转动为例,对互斥的动作进行设计:

#include <stdio.h>#include <xxx.h>bool HR_IF//头部转动动作执行或者不执行的开关标记char HR_FLGS //bit7、6:表示头部转动的模式,参见Mode_HR成员;bit5~0表示头部转动次数enum Mode_HR{    VERTI,    HORI,    ALLDIRE,};HR_VERTI(){}//头部水平转动函数HR_HORI(){}//头部竖直转动函数HR_ALLDIRE(){}//头部全方向转动函数void HeadRotate(bool HR_if, Mode_HR mod , int times )//参数:开关,方式、次数(0为无限次){    HR_IF = HR_if;    HR_FLGS| = mod << 6;//Mode_HR有效位只有两位,把它左移到HR_FLGS的高2位    HR_FLGS| = times & 0x3f;//HR_FLGSd bit5~0表示头部转动次数}int main(){    machine_init();    while(1)    {        if(HR_if)        {            if(HR_FLGS&0xc0 == 0)//HR_FLGS的bit7、6:表示头部转动的模式,                HR_VERTI();            else if(HR_FLGS&0xc0 == 1)                HR_HORI();            else if(HR_FLGS&0xc0 == 1)                HR_ALLDIRE();            if(HR_FLGS&0x3f == 1)                HR_if = 0;//计数次数完结,不再执行动作            else(HR_FLGS&0x3f != 0)                HR_FLGS--;        }    }    return 0;}void interrupt()//按键中断函数{    HeadRotate(1,VERTI,9); //一旦按下按键,则让机器头部按水平方向转动。}
>   可以看出,一个关节的动作其实是由几个小的动作组成的,几个小的动作是相互排斥的,这里用了几个if-else结果来表示这个互斥作用。
HR_VERTI(){}//头部水平转动函数HR_HORI(){}//头部竖直转动函数HR_ALLDIRE(){}//头部全方向转动函数

【独立动作】

那么两个独立的动作又怎么处理呢?独立的动作之间本身是没有关联性的,承接上例来说,头部关节的动作和躯干关节的动作本身是没有联系的,是独立的。

我依照上面的例子进行一些修改,加入一个机器的身体(BODY)动作:
#include <stdio.h>#include <stdlib.h>char ACTION//!!!此处本来是头部动作开关的标记,现在改为几个动作的开关标记组char HR_FLGS //bit7、6:表示头部转动的模式,参见Mode_HR成员;bit5~0表示头部转动次数enum Mode_HR{    VERTI,    HORI,    ALLDIRE,};HR_VERTI(){}//头部水平转动函数HR_HORI(){}//头部竖直转动函数HR_ALLDIRE(){}//头部全方向转动函数void HeadRotate(bool HR_if, Mode_HR mod , int times )//参数:开关,方式、次数(0为无限次){    ACTION| = HR_if;//!ACTION的bit0表示头部动作    HR_FLGS| = mod << 6;//Mode_HR有效位只有两位,把它左移到HR_FLGS的高2位    HR_FLGS| = times & 0x3f;//HR_FLGSd bit5~0表示头部转动次数}//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\//        新增body动作部分//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\char BD_FLGS //bit7、6:表示头部转动的模式,参见Mode_HR成员;bit5~0表示头部转动次数enum Mode_BD{    BD_MODE0,    BD_MODE1,    BD_MODE2};BD_0(){}//头部水平转动函数BD_1(){}//头部竖直转动函数BD_2(){}//头部全方向转动函数void HeadRotate(bool BD_if, Mode_HR mod , int times )//参数:开关,方式、次数(0为无限次){    ACTION| = BD_if<<1;//!ACTION的bit1表示身体动作    HR_FLGS| = mod << 6;    HR_FLGS| = times & 0x3f;}//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\int main(){    machine_init();    while(1)    {        if(ACTION&0x01 == 1)//!如果头部动作可以执行        {            if(HR_FLGS&0xc0 == 0)//HR_FLGS的bit7、6:表示头部转动的模式,                HR_VERTI();            else if(HR_FLGS&0xc0 == 1)                HR_HORI();            else if(HR_FLGS&0xc0 == 1)                HR_ALLDIRE();            if(HR_FLGS&0x3f == 1)                ACTION& = 0xfe;//计数次数完结,不再执行动作,清除bit0            else(HR_FLGS&0x3f != 0)                HR_FLGS--;        }        if(ACTION&0x02 == 1)//!如果身体动作可以执行        {            if(HR_FLGS&0xc0 == 0)                HR_VERTI();            else if(HR_FLGS&0xc0 == 1)                HR_HORI();            else if(HR_FLGS&0xc0 == 1)                HR_ALLDIRE();            if(HR_FLGS&0x3f == 1)                ACTION& = 0xfd;//清除bit1            else(HR_FLGS&0x3f != 0)                HR_FLGS--;        }    }    return 0;}void interrupt()//按键中断函数{    HeadRotate(1,VERTI,9); //一旦按下按键,则让机器头部按水平方向转动。}
    > 由上面代码看出,BODY和HEAD的动作是分成两个独立部分的,它们在程序上有相似的结构(这不必须,不过作为程序的编写者,有必要让程序具有普适性),它们之间唯一的交集就是ACTION。虽然说两套动作的开关都在ACTION的某一bit里,但是本质上,这两个bit位的操作也是独立开来的,那为啥还要做在一个char里呢,这是为了方便综合控制,这个后面再说。


    >可以看出,上述两段代码都有一个基本的理念,就是把控制和实现分成两大部分。控制,利用标记和标记组,加上if或者switch判断来选择需要执行的具体函数这一过程,而具体实现则是几个细小得不可分割的函数。当然,像上面的代码,我们可以把mian函数里的if判断放在一个新的函数里以简化mian函数,形如:
void HEAD_ACTION(Mode_HR mod){    if(mod == 0)//HR_FLGS的bit7、6:表示头部转动的模式,        HR_VERTI();    else if(mod  == 1)        HR_HORI();    else if(mod == 1)        HR_ALLDIRE();}
    几个关节的动作的开关合并作一个标记组ACTION,可以用于综合控制。围绕这个部分,还可以写一篇文章,关于复杂动作之间的关系,如何利用这个标记组表示和设计,所以此文就暂时到此为止。