|  
 
 
 最近刚把 DYS388 项目了结,期间写了不少程序,写着写着想到了一下东西,于是总结了一下,在这骚一把,高手勿喷啊。 
一、什么是占用式程序     一个进程在一个时刻只能处理一个任务。     每个任务是为了完成一个功能,如果这个功能的实现过程是一直占用进程处理资源的话,就称这个任务函数是占用式程序结构。     最常见的占用式程序结构就是延时函数了,比如我最常用的5ms延时函数     void delay5(unsigned char n)     {          unsigned int i;          for(;n>0;n--)              for(i=4700;i>0;i--);   //12MHz,1T     }     在完成5ms功能过程中是一直占用调用它的进程处理资源的,在此期间不能进行其它任务。     还有一个很常见的占用式程序——数码管扫描,不过在这里我不举数码管扫描的例子,而举这次在DYS388中使用的8*8彩色点阵屏的扫描程序:     void refresh7()     {          unsigned char r;          for(r=0;r<8;r++)          {              //扫描红色              DPw = ~(0x01<<r);  //修改完了再导通指定行              DPr = ~vm7r[r];//送入R灯IO接口显示              DELAY7 (light7);//显示时间长度              DPw=0xff;              DPr=0xff;              DPg=0xff;              DPb=0xff;              DELAY7 (32-light7);//灭灯时间长度              //为了简洁,这里把绿色和蓝色的扫描程序省略,它们的结构和红色扫描是一样的          }     }     这个函数是7色模式下的屏幕扫描程序,调用一次此函数会把整个屏幕扫描一遍。     r代表行数,r循环8次代表屏幕的8个行;在每次循环里,先导通对应的行和需点亮的灯,然后延时light7个单位,再关闭所有显示,再延时32-light7个单位。   二、占用式程序的缺点     占用式程序最大的缺点就是执行时间太长,耽误对其它任务的响应。另外就是资源浪费,很多时间浪费在执行中的延时上。     当然,可以在这些占用式程序中嵌入其它代码以及时处理其它任务,但是这样会造成程序结构混乱,嵌入的其它代码还会影响本程序的执行。如果嵌入的代码功能简单还好,如果功能复杂,尤其是当嵌入的代码也是占用式的,就会严重影响程序执行速度。     三、对占用式程序的改造     在此以DYS388的扫描程序为例,对其进行改造。     首先,每次调用就扫描8行,耗时太长,现将其改成每次扫描一行:     void refresh7()     {          static unsigned char r=0;          //扫描红色          DPw = ~(0x01<<r);  //修改完了再导通指定行          DPr = ~vm7r[r];//送入R灯IO接口显示          DELAY7 (light7);//显示时间长度          DPw=0xff;          DPr=0xff;          DPg=0xff;          DPb=0xff;          DELAY7 (32-light7);//灭灯时间长度          //为了简洁,这里把绿色和蓝色的扫描程序省略,它们的结构和红色扫描是一样的                r++;          if(r==8)              r=0;     }     用一个静态变量r来记忆行数,这样每次调用此函数只需扫描一行,执行速度是原来的8倍,可以比较快地响应其它任务了。     但是这样还不够,每次扫描都会扫描三种颜色,时间还是有点长,下面再次改造,改为每次只扫描一种颜色:     void refresh7()     {          static unsigned char r=0;          static unsigned char flagrgb=0;  //当前需要点亮的颜色,0-R,1-G,2-B          flagrgb++;          if(flagrgb==3)     //说明三种颜色都扫描完了          {              flagrgb=0;    //从红色开始扫描              r++;     //开始扫描下一行              if(r==8) //如果发现行都扫描结束则从第行开始扫描                   r=0;          }                switch(flagrgb)          {          case 0:  //扫描红色              DPw = ~(0x01<<r);  //修改完了再导通指定行              DPr = ~vm7r[r];//送入R灯IO接口显示              DELAY7 (light7);//显示时间长度              DPw=0xff;              DPr=0xff;              DPg=0xff;              DPb=0xff;              DELAY7 (32-light7);//灭灯时间长度              break;          case 1:  //扫描绿色                //省略代码              break;          case 2:  //扫描蓝色             //省略代码              break;          }     }     改造完成之后,执行时间再次缩短,变成了刚才的1/3。     这下还没完,我们发现每次扫描中都有延时,延时过程中什么也不做,这是极大的浪费,我们需要再此改造,把延时去掉:     void refresh7()     {          static unsigned char r=0;          static unsigned char flagrgb=0;  //当前需要点亮的颜色,0-R,1-G,2-B          static unsigned char num=0;          num++;          if(num==32)          {              num=0;              flagrgb++;              if(flagrgb==3)     //说明三种颜色都扫描完了              {                   flagrgb=0;    //从红色开始扫描                   r++;     //开始扫描下一行                   if(r==8) //如果发现行都扫描结束则从第行开始扫描                        r=0;              }          }                if(num<light7)     //说明需要点亮          {              switch(flagrgb)              {              case 0:  //扫描红色                   DPw = ~(0x01<<r);                   DPr = ~vm7r[r];//送入R灯IO接口显示                   break;              case 1:  //扫描绿色                      DPw = ~(0x01<<r);                   DPg = ~vm7g[r];                   break;              case 2:  //扫描蓝色                   DPw = ~(0x01<<r);                   DPb = ~vm7b[r];                   break;              }          }          else //说明不需要点亮          {              DPw=0xff;              DPr=0xff;              DPg=0xff;              DPb=0xff;          }     }     现在,这个函数中没有任何延时和循环,执行所消耗的时间是非常少的,可以很快地响应响应其它任务。   四、改造的本质     上面我们对DYS388的扫描程序进行了“三大改造”,分别是:1、各个行扫描的分离;2、各个颜色扫描的分离;3、延时函数的消除。     这些改造的本质都是对原程序的分割,把一大坨程序分成多个步骤分别执行,以减小耗时,提高对外部的响应速度。     但就整个进程的执行来看,有效代码的比例是降低的,包括上面“三大改造”的第三点 延时函数的消除,看上去是消除了延时函数,提高了执行效率,但从“扫描一次整屏”这个任务来看,其执行的代码量反而是增加的。(但并不是所有的改造都一定会使效率降低,有些改造确实可以达到“消除延时函数”的目的)     那为什么还要对其进行改造呢,见下节分析。   五、非占用式程序结构的优势     1、非占用式程序相比于占用式程序,增加了一定的代码,虽然会使整体效率降低,但是提高了各个任务之间的切换速度,可以对各个任务都能很快地响应。这点类似于操作系统,虽然降低了效率,但是各个任务间的快速切换可以达到各个任务“并行处理”的效果,光是这点的好处就已经很大了。     2、非占用式程序结构可以放进定时器 之前写过一片《单片机用定时器分配任务程序结构总结》已经发现用定时器分配任务的好处,有些简短的代码可以直接放进定时器里。 [1] [2] 下一页  
 |