博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言中关联计数器的协同管理
阅读量:5227 次
发布时间:2019-06-14

本文共 2446 字,大约阅读时间需要 8 分钟。

1 起因

在嵌入式应用中,对于很多控制器管脚传过来的信号要做软件防抖。如下面的图1:

在状态S1时,若C1的信号过来了,定时器T1开始计时;当T1的值达到V1时,就认为C1的信号是有效的。同理,S2与S3是一样的情况。

                  图1 关联定时器

计数器T1、T2和T3是互相关联的。它们之中最多有一个不为0。每当一个计数器在计数前,都要复位其它计数器。

例如:

假如T1正在计数,v1的值为500。当T1计数到200时,A1条件不符合,进入了A2条件,就要先复位T1定时器,然后再对T2进行计数。这样保证了当A1条件符合时,T1可以从0开始计数,达到了设计目的;否则T1就是从200开始计数了。

图1中只有3个计数器,当计数器很多时,甚至在Condition=c1处再加入几个判断,不同定时器的操作就会很复杂,而且维护起来很困难。所以有必要把几个计数器集中起来进行管理。

2 分析

 在图1中,先提出基本的实现:

实现a1:当State转移之后,首先要复位与此State下不相关的计数器(例子中只有一个T1;若不止一个的话,是不一样的);

实现a2:然后根据Condition的情况,相关计数器复位(C1)或是继续计算(T1++);

当计数器很多时,若每一个计数器分配一块内存,消耗很大;同时在需求中,最多只有一个计数器在工作,所以就定义一个计数器,通过其它名称来判断是为个条件计数。

实现a1就可以变成将计数器复位。考虑到这是一个循环执行的函数,就要保证不能每一次循环都要复位,这样就使用下面的算法完全没有作用了;

实现a2的计数器复位和实现a1一样,继续计算就是自增1;

现在就变成了两种情况:计数器复位和计数器数值自增1。而它们的前提是要分辨出前后操作的计数器是否一致。

那么计数器的名称在哪一步确定呢?

在图1中,因为条件C1并不是一定不会成立,这样当前计数器的计数和其它计数器的复位完全没有关系了,对于编程来说,不好操作,所以要更改程序流程,如图2:

                  图2 关联定时器

进而,实现就变成了如下的样子

实现b1:在不符合当前计数器计数条件下,将计数器复位,同时将计数器的名称复位;

实现b2:在符合当前计数器计数的条件下,当前要使用的计数器名称与上一次的名称不同,更新计数器名称;

实现b3:在符合当前计数器计数的条件下,当前计数器名称和上一次计数器的名称是相同的,计数器中的数值自增1。

根据实现b1,要为图2中的每个计数器分配一个名称。

通过对比C1~C4四种情况的计数器操作,可以看出根据这一次和上一次操作计数器名称的不同,每次操作最多修改两个计数器的值。

假设0为复位全部的计数器(如图2中的C3情况),1~4对应着T1~T4,LasterOrder表示上一次操作的计数器,Order表示本次操作的计数器,则对计数器的处理如表1所示:

表1 不同情况对计数器的处理

LastOrder Order 实际操作
0 0 什么也不做
0 >0 计数器等于1
>0 0 计数器复位
>0 =LastOrder 计数器加1,不能让计数器溢出
>0 !=LastOrder 计数器等于1

 

 

 

 

 

 

现在已经很明确了,可以开始写代码了。

3 编码

如下:

 

#define TIMER_NUM       4       //计数器个数#define RESET_ALL       0       //复位名称#define T1              1#define T2              2#define T3              3#define T4              4ubyte CounterManage(ubyte Order){    static ubyte LastOrder;    static uword CoupleCounter;        if (Order > 255 || Order >= TIMER_NUM)      //要修改的计数器不在正确范围内    {        return 1;    }    else     {        if (LastOrder == 0)        {            if (Order > 0)            {                CoupleCounter = 1;            }        }        else        {            if (Order = 0)            {                CoupleCounter = 0;            }            else if (Order = LastOrder)            {                CoupleCounter++;            }            else            {                CoupleCounter = 1;            }        }        LastOrder = Order;        return 0;    }}

上面的代码对于计数器溢出的处理并没有做相应的设计。

同时,对于几种条件的判断也可以分成下面三种情况
Order=0、Order=LastOrder和Order!=LastOrder

我不是很喜欢这种写法,虽然代码少了,但是给理解增添了一些难度。我的标准就是一看就能明白什么意思,越简单越好。

另,流程很重要。像图一的流程,对于图二中多个Condition的情况,很难实现上面的方法。

转载于:https://www.cnblogs.com/fallcolor/p/4422339.html

你可能感兴趣的文章
训练记录
查看>>
IList和DataSet性能差别 转自 http://blog.csdn.net/ilovemsdn/article/details/2954335
查看>>
Hive教程(1)
查看>>
第16周总结
查看>>
C#编程时应注意的性能处理
查看>>
Fragment
查看>>
比较安全的获取站点更目录
查看>>
苹果开发者账号那些事儿(二)
查看>>
使用C#交互快速生成代码!
查看>>
UVA11374 Airport Express
查看>>
P1373 小a和uim之大逃离 四维dp,维护差值
查看>>
NOIP2015 运输计划 树上差分+树剖
查看>>
P3950 部落冲突 树链剖分
查看>>
读书_2019年
查看>>
读书汇总贴
查看>>
微信小程序 movable-view组件应用:可拖动悬浮框_返回首页
查看>>
MPT树详解
查看>>
空间分析开源库GEOS
查看>>
RQNOJ八月赛
查看>>
前端各种mate积累
查看>>