2017-09-26 92 views
3

我想编写一个PLC地址生成器。但是,我需要明智的补充,以找到下一个可用的地址。如何在c#中按位添加?

含义,如果我开始与ADRESS 0.0,加入2位,则下一个空闲ADRESS是0.3。直到0.7然后下一个地址是1.0到1.7然后2.0等等。

根据我增加了一个空闲ADRESS应该算出的相加什么数据类型。

例如一个布尔是一位。 0.1 - > 0.2 - > 0.3等等 如果我添加一个字节,并且最后一个空闲地址为0.4,则下一个空闲地址应为2.0,则字节有8位。

一个字有16位,所以0.0 - > 2.0 - > 4.0等等。

双字有32位,因此0.0 - > 4.0 - > 8.0等等。

我期待在C#中的实现,我可以添加不同类型的输入,并将其添加它,并给了我相应的地址,然后保存下一个空闲地址为内部的下一步操作。

例如:

Type   Startaddress 
1 Bool   0.0   (->0.1) 
2 Bool   0.1   (->0.2) 
3 Byte   1.0   (->1.7) as 8 bits are required 
4 Bool   2.0   (->2.1) 
5 Word   3.0   (->4.7) as 16 bits are required 
6 Double Word 5.0   (->8.7) as 32 bits are required 

任何想法,我能怎么样,如果别人和循环执行,除了大量的?我正在寻找一种优雅的重载操作方法。下部的前3位,在其余位的其余部分,并从那里得到的地址 -

+1

“如果我添加一个字节和最后一个空闲地址为0.4下一个空闲的地址应为2.0”是如何计算的那? –

+0

@JakubDæbek:那个对我来说也没什么意义...... – JuanR

回答

0

唯一的“帽子戏法”,以你的问题的3.0 0.7的位地址的符号和C#的类型不匹配与您的规格中的类型完全一致。

主类我在这里展示存储为位内部偏移地址,并提供了通过fAddress()方法中的整数和小数部分。

你举的例子显示了在字节边界对齐,但不对齐字或双字 - 所以这就是我实现。评论显示如果PLC关心如何做到这一点。

您需要添加代码以存储byte.bit类型地址的值。

using System; 

namespace PLCAddress 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      PLCAddress a = new PLCAddress(); 
      float address; 
      bool boolA = true; 
      byte byteA = 7; 
      ushort wordA = 65535; 
      uint dblwordA = 4294967295; 

      address = a.Store(boolA); 
      Console.WriteLine(address.ToString()); 

      address = a.Store(boolA); 
      Console.WriteLine(address.ToString()); 

      address = a.Store(byteA); 
      Console.WriteLine(address.ToString()); 

      address = a.Store(boolA); 
      Console.WriteLine(address.ToString()); 

      address = a.Store(wordA); 
      Console.WriteLine(address.ToString()); 

      address = a.Store(dblwordA); 
      Console.WriteLine(address.ToString()); 
     } 
    } 
    public class PLCAddress 
    { 
     protected uint _address; 
     public PLCAddress() 
     { 
      _address = 0; 
     } 

     public float Store(bool b) 
     { 
      float rv = fAddress(); 
      _address += 1; 
      return rv; 
     } 
     public float Store(byte b) 
     { 
      float rv = fAddress(8); 
      _address += 8; 
      return rv; 
     } 
     public float Store(ushort b) 
     { 
      float rv = fAddress(8); // use fAddress(16) if words need to be on word boundaries 
      _address += 16; 
      return rv; 
     } 
     public float Store(uint b) 
     { 
      float rv = fAddress(8); // use fAddress(32) if double words need to be on double word boundaries 
      _address += 32; 
      return rv; 
     } 

     protected float fAddress() 
     { 
      return (float)Whole + (float)Fraction/10; 
     } 

     protected float fAddress(uint alignment) 
     { 
      uint roundup = alignment - 1; 
      uint mask = ~roundup; 
      uint AlignedAddress = _address + roundup; 
      AlignedAddress = AlignedAddress & mask; 
      _address = AlignedAddress; 
      return fAddress(); 
     } 
     protected uint Whole 
     { 
      get { return _address/8; } 
     } 
     protected uint Fraction 
     { 
      get { return _address % 8; } 
     } 
    } 
} 
0

您可以在一个int存储这些地址。这使您可以对这些地址和数字进行正常的算术运算。如果地址是在一个字符串,你可以做这样的事情:

public static int ToIntAddress(this string str) 
{ 
    var values = str.Split('.'); 
    int lower = int.Parse(values[1]); 
    int higher = int.Parse(values[0]) << 3; 
    return lower + higher; 
} 

public static string ToAddress(this int address) => $"{address >> 3}.{address & 0b0111}"; 

("3.0".ToIntAddress() + 15).ToAddress() // "4.7" 
("5.0".ToIntAddress() + 31).ToAddress() // "8.7" 
("0.4".ToIntAddress() + 7).ToAddress() // "1.3" 
0

我个人更喜欢一个面向对象的方法:

public class MemoryManager 
{ 
    private int _dataSize = 0; 

    public enum DataTypes 
    { 
     Bool = 1, 
     Byte = 8, 
     Word = 16, 
     DWord = 32 
    } 
    public MemoryLocation Add(DataTypes type) 
    {    
     var address = GetCurrentAddress(); 
     _dataSize += (int)type; 
     return address; 
    } 

    private MemoryLocation GetCurrentAddress() 
    { 
     int currentByteLocation = _dataSize/8; 
     int currentBitLocation = _dataSize % 8;    
     return new MemoryLocation(currentByteLocation, currentBitLocation); 
    }   
} 

public class MemoryLocation 
{ 
    public MemoryLocation(int byteLocation, int bitIndex) 
    { 
     ByteLocation = byteLocation; 
     BitIndex = bitIndex;    
    } 
    public int ByteLocation { get; private set; } 
    public int BitIndex { get; private set; }   
    public override string ToString() 
    { 
     return string.Format("[{0},{1}]", ByteLocation, BitIndex); 
    } 
} 

我掀起了这一点,真正的快,但是你可以用其他更简化的方法来产生一个地址。

0

您可以使用此:

public int BitWiseAdd() 
{ 
      int FirstNumber = 50; 
      int SecondNumber = 60; 
      while (SecondNumber !=0) 
      { 

       int carry = FirstNumber & SecondNumber; 
       FirstNumber = FirstNumber^SecondNumber; 
       SecondNumber = carry << 1; 
      } 
      return FirstNumber; 


}