Проверка цифровых входных сигналов, которые отправляются в виде целого числа, используя битовые проверки


У меня есть программа, которая работает с оборудованием через интерфейс API и ActiveX. В API есть события, которое запускается оборудование. В оборудовании есть IO карты. Есть 16 и 16 из. Изменение входного сигнала вызывает обработчик события ниже. Случае используется тип int, чтобы показать, какой сигнал включено/отключено. С помощью двоичных адресов для каждого сигнала

Signal          Mask
INPUT_0         0x01;
INPUT_1         0x02;
INPUT_2         0x04;
INPUT_3         0x08;
... 
INPUT_11        0x800

(есть некоторые сигналы, которые используются для других целей и не могут использоваться в качестве входных данных)

Сигналов может быть включено/отключено в любом порядке, но событие будет вызываться каждый раз, когда изменение произойдет! Значение, p_nBits, будет включать в себя все государственные сигналов. Это означает, что если INPUT_0 устанавливается, а затем INPUT_1 находится тогда p_nBits будет 3, т. е. оба сигнала! Но INPUT_0 уже обработана, и не надо снова обрабатывать, пока не установлено. У меня есть целое число currentBits , что текущее состояние входных сигналов.

Любая ошибка в логике? Что можно улучшить? Можно ли сделать это быстрее?

// Current state of Input signals
int currentBits = 0;

public void IoPort_sigInputChange(int p_nBits)
{
    lock (lockObj)
    {

        if ((p_nBits & INPUT_0) == INPUT_0)
        {
            if ((currentBits & INPUT_0) != INPUT_0)
            {
                currentBits |= INPUT_0;
                RaiseRunModeEvent(true);
            }
        }
        else
        {
            if ((currentBits & INPUT_0) == INPUT_0)
            {
                currentBits &= ~INPUT_0;
                RaiseRunModeEvent(false);
            }
        }

        if ((p_nBits & INPUT_1) == INPUT_1)
        {
            if ((currentBits & INPUT_1) != INPUT_1)
            {
                currentBits |= INPUT_1;
                RaiseAllPositionsSetEvent(true);
            }
        }
        else
        {
            if ((currentBits & INPUT_1) == INPUT_1)
            {
                currentBits &= ~INPUT_1;
                RaiseAllPositionsSetEvent(false);
            }
        }

        if ((p_nBits & INPUT_2) == INPUT_2)
        {
            if ((currentBits & INPUT_2) != INPUT_2)
            {
                currentBits |= INPUT_2;
                RaiseOrderEndedEvent(true);
            }
        }
        else
        {
            if ((currentBits & INPUT_2) == INPUT_2)
            {
                currentBits &= ~INPUT_2;
                RaiseOrderEndedEvent(false);
            }
        }

        // more checks may occur
    }
}


127
4
задан 30 марта 2018 в 06:03 Источник Поделиться
Комментарии
1 ответ

Во-первых, вы можете упростить внешний еще высказывания:

...
else
{
if ((currentBits & INPUT_0) == INPUT_0)
{
...
}
}
...

для

...
else if ((currentBits & INPUT_0) == INPUT_0)
{
} ...


Во-вторых, если проверка всех масок такой же схеме, как показано, вы можете создать метод проверки маски такой один (в C# 7.0):

private void HandleMask(int bitPattern, (int mask, Action<bool> action) maskItem)
{
if ((bitPattern & maskItem.mask) == maskItem.mask)
{
if ((currentBits & maskItem.mask) != maskItem.mask)
{
currentBits |= maskItem.mask;
maskItem.action(true);
}
}
else if ((currentBits & maskItem.mask) == maskItem.mask)
{
currentBits &= ~maskItem.mask;
maskItem.action(false);
}
}

public void IoPort_sigInputChange(int p_nBits)
{
lock (lockObj)
{
var maskItems = new(int mask, Action<bool> action)[]
{
(mask: INPUT_0, action: RaiseRunModeEvent),
(mask: INPUT_1, action: RaiseAllPositionsSetEvent),
(mask: INPUT_2, action: RaiseOrderEndedEvent),
};

foreach (var maskItem in maskItems)
{
HandleMask(p_nBits, maskItem);
}
}
}


Обновление

В .net 3.5 с вы должны/могли бы сделать это таким образом, как это:

private void HandleMask(int bitPattern, int mask, Action<bool> action)
{
if ((bitPattern & mask) == mask)
{
if ((currentBits & mask) != mask)
{
currentBits |= mask;
action(true);
}
}
else if ((currentBits & mask) == mask)
{
currentBits &= ~mask;
action(false);
}
}

public void IoPort_sigInputChange(int p_nBits)
{
lock (lockObj)
{
var maskItems = new[]
{
new { mask = INPUT_0, action = (Action<bool>)RaiseRunModeEvent },
new { mask = INPUT_1, action = (Action<bool>)RaiseAllPositionsSetEvent },
new { mask = INPUT_2, action = (Action<bool>)RaiseOrderEndedEvent },
};

foreach (var maskItem in maskItems)
{
HandleMask(p_nBits, maskItem.mask, maskItem.action);
}
}
}

4
ответ дан 31 марта 2018 в 02:03 Источник Поделиться