Search code examples
c#ascii.net-cf-3.5

convert a Non-displayable ASCII array to decimal


I receive a byte array serial_port[4] {0x00, 0xA0, 0x05, 0xB1} from my serial port as below:

string rec_data += sp.ReadExisting();  

and I need to convert this string to a decimal value by using:

byte[] Temp = Encoding.ASCII.GetBytes(rec_data);
decimal r0 = Convert.ToDecimal(Temp[0]);
decimal r1 = Convert.ToDecimal(Temp[1]);
decimal r2 = Convert.ToDecimal(Temp[2]);
decimal r3 = Convert.ToDecimal(Temp[3]); 

But result values are not my desire:

r0 = 0
r1 = 63
r2 = 5
r3 = 63

as you can see, result of 8-bits HEX values are wrong and are equal with 63(0x3F) any suggestion to solve it?


Solution

  • ASCII is a 7-bit character set. There's no such thing as 0xA0 in ASCII. 63 just happens to be ? in ASCII - the character used when a particular value cannot be represented in the given character set.

    Don't read the data as character data when they aren't characters. Don't use ReadExisting, which assumes character data. Rather, you need something like this:

    var buffer = new byte[256];
    var bytesRead = sp.Read(buffer, 0, buffer.Length)
    
    // buffer[0..bytesRead-1] now contains all the data read from the port
    

    Of course, you may need to read multiple times to get the whole message, or you might want to only read a limited amount of bytes at a time, depending on how your protocol works.

    A simple SerialPort wrapper that handles this for you might look like this:

    class MySerialPort
    {
      private readonly SerialPort _port;
    
      public MySerialPort(SerialPort port)
      {
        this._port = port;
      }
    
      public byte[] ReadBytes(int amount)
      {
        var data = new byte[amount];
        var offset = 0;
    
        while (amount > 0)
        {
          var bytesRead = _port.Read(data, offset, amount);
          offset += bytesRead;
          amount -= bytesRead;
        }
    
        return data;
      }
    }
    

    Depending on what you're actually trying to do, you might want to add some buffering and what not, but this will work fine for the kind of protocols that are commonly used over serial port. If this is all you really need, you could simply make ReadBytes an extension method on SerialPort.

    Also, decimal is a, well, decimal number. You probably want to use byte or int instead.