2016-07-27 5 views
1

Je reçois un tableau d'octets serial_port[4] {0x00, 0xA0, 0x05, 0xB1} de mon port série comme ci-dessous:convertir un tableau ASCII non affichables en décimal

string rec_data += sp.ReadExisting(); 

et je dois convertir cette chaîne à une valeur décimale en utilisant:

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]); 

Mais les valeurs de résultat ne sont pas mon désir:

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

comme vous pouvez le voir, le résultat des valeurs HEX 8 bits sont faux et sont égaux à 63 (0x3F) toute suggestion pour le résoudre?

+0

Lit les octets du port série au lieu de la chaîne. Ou essayez d'utiliser 'Encoding.Default' au lieu de' Encoding.ASCII'. –

+0

Résultat @Alexander Petrov pour 'Encoding.default' était similaire –

+1

Parce que le codage du port série est toujours' Encoding.ASCII'. Vous devriez aussi changer 'sp.Encoding' (idéalement juste après avoir créé l'instance' SerialPort'). ASCII est un jeu de caractères de 7 bits, vous ne pouvez pas représenter des valeurs supérieures à 127. '0xA0' est plus grand que 127, donc il est encodé en 63 -'? '. – Luaan

Répondre

5

ASCII est un jeu de caractères 7 bits. Il n'y a rien de tel que 0xA0 en ASCII. 63 se trouve être ? en ASCII - le caractère utilisé lorsqu'une valeur particulière ne peut pas être représentée dans le jeu de caractères donné.

Ne pas lire les données sous forme de données de type lorsqu'elles ne sont pas des caractères. N'utilisez pas ReadExisting, qui suppose des données de caractères. Au contraire, vous besoin de quelque chose comme ceci:

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 

Bien sûr, vous devrez peut-être lire plusieurs fois pour obtenir l'ensemble du message, ou vous voudrez peut-être en lecture seule une quantité limitée d'octets à la fois, selon la votre protocole fonctionne.

Un emballage SerialPort simple qui gère pour vous pourrait ressembler à ceci:

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; 
    } 
} 

Selon ce que vous essayez de faire en fait, vous pouvez ajouter un peu de mise en mémoire tampon et ce pas, mais cela fonctionne bien pour le type de protocoles qui sont couramment utilisés sur le port série. Si c'est tout ce dont vous avez vraiment besoin, vous pouvez simplement faire ReadBytes une méthode d'extension sur SerialPort. En outre, decimal est également un nombre décimal. Vous voulez probablement utiliser byte ou int à la place.

+0

Aide l'OP tomber dans la fosse du succès, la variable * buffer * devrait toujours être un champ de la classe et le 2ème argument à Read() devrait Toujours être une variable qui compte le nombre d'octets dans le tampon. –

0

Vous n'avez pas besoin de convertir octets en décimal:

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

Les valeurs des années int:

r0 - 0 
r1 - 160 
r2 - 5 
r3 - 177 
+0

Je l'ai essayé aussi bien. Le résultat était similaire –

+0

@ Ehsan.Da J'ai édité ma réponse. Est-ce que ça marche pour toi? –

+0

Merci, je l'ai vérifié dès maintenant. Mais n'a pas fonctionné. Je suppose que peut-être ma chaîne reçue n'est pas une chaîne correcte pour l'octet HEX de 8 bits –