C# komunikace na sériové sběrnici rubrika: Programování: .Net

Anonym
položil/-a 27.9.2021
 
upravil/-a 27.9.2021

Ahoj,

programuji komunikaci na sériové sběrnici se čtečkami od dodavatele HW. Je to naprosto triviální, ale dělá mi to celkem problém při vyčítání dat. Potřebuji na sběrnici zapsat 2 bajty adresu(0x00 a 0x01) a následně si přečíst 1 bajt odpověď. Pokud tohle udělám skrze software dodavatele HW, tak se zapíše adresa a odpověď vrátí 1 bajt(0xAA). Když to však pošlu úplně stejně přes můj software, tak se mi vrátí odpověď ve druhém nebo třetím bajtu. První a někdy druhý bajt má hodnotu(0x3F).

Ke komunikaci používám SerialPort objekt v C#. SW dodavatele je napsaný v Pascalu(knihovna synaser) - zdrojáky nemám. Sehnal jsem na internetu software na monitoring sběrnice. Data se tam zašlou naprosto stejná, nicméně při čtení to prostě vrací jinak. Mám takové tušení, že tam něco na pozadí dělá ještě ten C#, ale nemohu přijít na to co. Zapisuje čistě bajty, nikoliv stringy.

 
private bool SendAddress()
        {
            int confirmation;
            byte[] address = { (byte)((Address >> 8) & 0xFFu), Address };
            var confirmed = false;
            var port = new SerialPort(Port, 19200, Parity.Mark, 8);
 
            port.WriteTimeout = 200;
            port.ReadTimeout = 200;
 
            StatusReaderService.PortLoggers[Port].Debug(Name + " Opening port for address.");
            port.Open();
            StatusReaderService.PortLoggers[Port].Debug(Name + " Port opened.");
            StatusReaderService.PortLoggers[Port].Debug(Name + " Discarding buffers.");
            port.DiscardOutBuffer();
            port.DiscardInBuffer();
            StatusReaderService.PortLoggers[Port].Debug(Name + " Buffers discarded.");
            StatusReaderService.PortLoggers[Port].Debug(Name + " Writing address: " + BitConverter.ToString(address));
            //port.Write(address, 0, address.Length);
            port.BaseStream.WriteByte(0x00);
            port.BaseStream.WriteByte(0x01);
            StatusReaderService.PortLoggers[Port].Debug(Name + " Address written.");
 
            try
            {
                for (int i = 0; i < 3; i++)
                {
                    StatusReaderService.PortLoggers[Port].Debug(Name + " Waiting for confirmation.");
                    confirmation = port.ReadByte();
                    StatusReaderService.PortLoggers[Port].Debug(Name + " Confirmation value received: " + BitConverter.ToString(BitConverter.GetBytes(confirmation), 0, 1));
 
                    if (confirmation == 0xAA)
                    {
                        StatusReaderService.PortLoggers[Port].Debug(Name + " Confirmed.");
                        confirmed = true;
                        break;
                    }
                    else
                    {
                        StatusReaderService.PortLoggers[Port].Debug(Name + " Invalid confirmation value.");
                    }
                }
            } catch(TimeoutException)
            {
                port.Close();
                throw;
            }
 
            StatusReaderService.PortLoggers[Port].Debug(Name + " Closing port.");
            port.Close();
            Console.ReadKey();
 
            if (confirmed == false)
            {
                StatusReaderService.PortLoggers[Port].Debug(Name + " Confirmation not received.");
                return confirmed;
            }
 
            return confirmed;
        }

Ještě posílám jak přesně vypadá ta sekvence:

V mém případě:
Read: 0x3F 0x3F 0xAA
Write: 0x00 0x01

V případě SW dodavatele:
Read: 0xAA
Write: 0x00 0x01

Musím tam mít proto ten cyklus na kontrolu výsledku, nicméně to je nechtěný stav. Nesetkal se někdo s něčím podobným?

odkaz Vyřešeno
Anonym
odpověděl/-a 27.9.2021

Dostalo se mi pomoci na Stackoverflow. Hodnota 0x3F je tam kvůli chybě parity. Dle dokumentace od dodavatele se má zasílat adresa s paritou nastavenou na 1. HW však při následném potvrzení zasílá data již bez parity. Tudíž vznikne chyba parity a C# nastaví hodnotu 0x3F - ta se nastavuje v SerialPort.ParityReplace. Kdybych si přidal do kódu error handler, tak by to na mě vyskočilo dříve. Nemám tolik zkušeností s komunikací na sériovém portu.

Pro plný přístup na Devel.cz se prosím přihlaste:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.