Autor Téma: Nastavení virtuálního sériového portu  (Přečteno 349 krát)

Online Faltynek

  • Plnoletý
  • ***
  • Příspěvků: 167
  • Karma: 2
    • Verze Delphi: D5 Enterprise, D2009
Nastavení virtuálního sériového portu
« kdy: 11-04-2019, 21:12:23 »
Dobrý den,
nerad zase otravuji, potřeboval bych nakopnout co se týče nastavování comportu. Mám jakýsi hardware který komunikuje přes USB rozhraní. Už mi to léta běží pod Delphi, software načte přes Enumerate seznam portů, postupně je projde a zkusí poslat povel pro návrat sériového čísla hardwaru. Pokud přijde správná odezva - začíná to S00 a pokračuje sériovým číslem, pak se dějou další potřebné věci. Kód pro začátek komunikace je
Kód: Delphi [Vybrat]
  1.   procedure TfrmMain.NajdiKartu(var TypKarty: byte; var portik: string);
  2.   var     i, ii, j: integer;
  3.           porty: TStringList;
  4.           starttime, endtime: TTime;
  5.   begin
  6.     typkarty:=0;
  7.     if frmstart.chkSimulace.Checked then
  8.     begin     // typkarty = 3 - simulace
  9.         typkarty:=3;
  10.         Statusbar1.Panels[1].Text:='Režim simulace měření..';
  11.     end else
  12.     begin     // typkarty <> 3 - simulace
  13.     frmMain.txtRX.Text:='';
  14.     rx:='';
  15.     frmMain.Memo1.Lines.Add('Seznam nalezených portů:') ;
  16.     porty := TStringList.Create;
  17.     EnumComPorts(Porty);
  18.     frmMain.memo1.Lines.AddStrings(porty);
  19.     hlaska:='Prohledávám porty..';
  20.     Statusbar1.Panels[1].Text:=hlaska;
  21.     frmMain.Memo1.Lines.Add(hlaska);
  22.     j:=0;
  23.     if portik <> '' then
  24.     begin
  25.         for i:=0 to porty.Count-1 do
  26.         begin
  27.           ii:=pos(chr(0), porty[i]);
  28.           if copy(porty[i], 0, ii-1)=port then j:=i
  29.         end;
  30.     end;
  31.     for i:=j to porty.Count-1 do
  32.     begin
  33.       if comport1.Connected then comport1.Close;
  34.       application.ProcessMessages;
  35.       comport1.Port:= porty[i];
  36.       comport1.CustomBaudRate:=230400;
  37.       hlaska:='Otevírám port ' + porty[i];
  38.       Memo1.Lines.Add(hlaska);
  39.       Statusbar1.Panels[1].Text:=hlaska;
  40.       try
  41.       comport1.Open;
  42.       comport1.WriteStr('I_PS' + #13);
  43.       endtime:=time+0.5*1/(24*60*60);
  44.       Memo1.Lines.Add('Odeslán dotaz na sériové číslo 35954U..');
  45.       Statusbar1.Panels[1].Text:='Odeslán dotaz na sériové číslo interfejsu..';
  46.       repeat
  47.         application.ProcessMessages;
  48.       until ((time)>endtime) or (rx <> '');
  49. //      Memo1.Lines.Add('Odeslán dotaz na sériové číslo 35954U..');
  50.       sleep(200);
  51.       if pos('S00', rx)<>0 then
  52.       begin
  53.         cisloportu:=i;
  54.         comport1.Port:= porty[i];
  55.         portik:= copy(porty[i], 1, pos(chr(0), porty[i])-1);
  56.         hlaska:='Nalezen SNET interfejs 35954U sn: ' +rx + ' na ' + porty[i];
  57.         Memo1.Lines.Add(hlaska);
  58.         Statusbar1.Panels[1].Text:=hlaska;
  59.         porty.free;
  60.         cmdGo.Enabled:=true;
  61.         TypKarty:=1;
  62.         comport1.WriteStr('I_IN' + #13);
  63.         exit;
  64.       end;
  65.       except
  66.         beep;
  67.       end;
  68.     end;
  69.     porty.free;
  70.     Memo1.Lines.Add('Interfejs nenalezen, zkontroluj připojení k počítači!');
  71.     Statusbar1.Panels[1].Text:='Interfejs nenalezen, zkontroluj připojení k počítači!';
  72.     TypKarty:=0;
  73.   end;   // typkarty <> 3 - simulace
  74.   end;
  75.  

Používám TComPort, nastavení všech eventů je na True, controDTR a RTS je Enable, OutCTSFlow=True, OutDSRFlow=False, EventChar je #13, TrigersOnRxChar je true.

A teď nastala potřeba ovládat ten hardware a nastavit ten Com z Excelu. Vygooglil jsem, že ke comportu se dá přistupovat jako k souboru a našel jsem příklad:

Kód: Delphi [Vybrat]
  1.     Debug.Print "Open COM port 9"
  2.     Open "COM9:230400,E,8,1" For Binary Access Read Write As #1
  3.     transmit$ = "I_PS" + Chr(13)
  4.     receiveDummy$ = "~~~"
  5.  
  6.     ' transmit a message
  7.    Put #1, , transmit$
  8.    Debug.Print "Message sent."
  9.  
  10.    ' wait a bit for a response
  11.     Sleep 200
  12.  
  13.     ' check for received message
  14.    Debug.Print "Look for incoming message."
  15.    On Error Resume Next
  16.    Do While True
  17.        receive$ = receiveDummy$  'dummy value
  18.         Input #1, receive$
  19.         If receive$ = receiveDummy$ Then Exit Do  'the string didn't change, so move on
  20.         Debug.Print receive$
  21.     Loop
  22.     On Error GoTo 0
  23.  

Pokud předtím provedu nastavení portu aspoň jednou z původního programu v Delphi, tak to s drobnýma vadama funguje a vrátí to sériové číslo i když na začátku místo S00 jenom 00, ale pokud to spustím po připojení hardwaru přímo z Excelu, tak to zatuhne na prvním Input #1.
Tuším, že potíž je v nastavení buď EventChar, nebo Flowcontrol, ale nevím jak mám DCB z VBA nastavit.

Znovu se omlouvám za mimo platformovou otázku a pokud někdo poradí, klidně na dalikf@volny.cz.


Díky - Dalibor.
Dalibor (D2009 Enterprise, dřív D5Enterprise)

Online Faltynek

  • Plnoletý
  • ***
  • Příspěvků: 167
  • Karma: 2
    • Verze Delphi: D5 Enterprise, D2009
Re:Nastavení virtuálního sériového portu
« Odpověď #1 kdy: 11-04-2019, 22:23:11 »
Jednoduše to asi nepůjde, myslím jsem našel příslušné funkce ve winapi (au au), tak to zkusím a dám vědět.

Dalibor.
Dalibor (D2009 Enterprise, dřív D5Enterprise)

Offline geby

  • Plnoletý
  • ***
  • Příspěvků: 199
  • Karma: 16
    • Verze Delphi: 7, 2007, XE2, 10.2
    • Synapse
Re:Nastavení virtuálního sériového portu
« Odpověď #2 kdy: 12-04-2019, 06:54:56 »
Z Delphi kódu mi není jasné, jestli vůbec nastavuje s všechny parametry komunikace, jako počet bitů, parita a stopbity.

V Excelu to ale nějak nastavujes... Určitě správně?

Offline geby

  • Plnoletý
  • ***
  • Příspěvků: 199
  • Karma: 16
    • Verze Delphi: 7, 2007, XE2, 10.2
    • Synapse
Re:Nastavení virtuálního sériového portu
« Odpověď #3 kdy: 12-04-2019, 07:13:23 »
Ještě jedna myšlenka... Neznamená hodnota 1 u stopbitu náhodou 1.5 stopbitu, což není zrovna obvyklá hodnota? Pokud chceš 1 stopbit, zkus tam dát hodnotu 0.

Ve Windows API se to tak používá, ostatně v mém SynaSer také. Je dost možné, že to ten Excel má stejné.

Online Faltynek

  • Plnoletý
  • ***
  • Příspěvků: 167
  • Karma: 2
    • Verze Delphi: D5 Enterprise, D2009
Re:Nastavení virtuálního sériového portu
« Odpověď #4 kdy: 12-04-2019, 10:59:39 »
Citace
Z Delphi kódu mi není jasné, jestli vůbec nastavuje s všechny parametry komunikace, jako počet bitů, parita a stopbity.

Parametry nastavuji kromě čísla portu rovnou ve vlastnostech komponenty TComPort: Rychlot 230400, lichá parita, 8 bitů, 1 stopbit.

Citace
Neznamená hodnota 1 u stopbitu náhodou 1.5 stopbitu,

No to by byl gól, vyzkouším.
Dalibor (D2009 Enterprise, dřív D5Enterprise)

Online Faltynek

  • Plnoletý
  • ***
  • Příspěvků: 167
  • Karma: 2
    • Verze Delphi: D5 Enterprise, D2009
Re:Nastavení virtuálního sériového portu
« Odpověď #5 kdy: 13-04-2019, 21:14:26 »
Změna parametru počtu stopbitů na 0 je bez efektu, pořád to tuhne na inputu a to tak, že je nutné zavření excelu přes manažera aplikací.
Dalibor (D2009 Enterprise, dřív D5Enterprise)

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2502
  • Karma: 131
    • Verze Delphi: D2007, XE3, DX10
Re:Nastavení virtuálního sériového portu
« Odpověď #6 kdy: 13-04-2019, 22:00:51 »
Změna parametru počtu stopbitů na 0 je bez efektu, pořád to tuhne na inputu a to tak, že je nutné zavření excelu přes manažera aplikací.
No a neni to proto, ze ceka na prijem nejakych bytu a nic neprichazi resp. jich prijde min?

Offline Delfin

  • Padawan
  • ******
  • Příspěvků: 1744
  • Karma: 67
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:Nastavení virtuálního sériového portu
« Odpověď #7 kdy: 13-04-2019, 22:14:32 »
Me zarazi pozadavek obsluhy COM portu z Excelu. Je k tomu realny duvod? Prijde mi to jako drbat se v uchu pres analni otvor. Netvrdim, ze by to teoreticky nebylo mozne, ale pripada mi to extremne neohrabane (clumsy).

Sluzba (dejme tomu psana v Delphi) generujici data Excelu (pripadne do jejich Access databaze) by mi znela rozumneji.
« Poslední změna: 13-04-2019, 22:44:14 od Delfin »
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Offline Delfin

  • Padawan
  • ******
  • Příspěvků: 1744
  • Karma: 67
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:Nastavení virtuálního sériového portu
« Odpověď #8 kdy: 13-04-2019, 22:48:30 »
Me zarazi pozadavek obsluhy COM portu z Excelu. Je k tomu realny duvod? Prijde mi to jako drbat se v uchu pres analni otvor. Netvrdim, ze by to teoreticky nebylo mozne, ale pripada mi to extremne neohrabane (clumsy).

Doba, kdy se Excel snazil byt vyhradnim nastrojem manazeru zrejme neopadl, coz ovsem neznamena jim programovat vse co si preji. Pevne verim, ze mohou existovat i jina reseni v ramci jejich oblibeneho kancelarskeho baliku MS Office (byt mam v teto sfere dost velke mezery).
« Poslední změna: 13-04-2019, 22:50:29 od Delfin »
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Offline Daniel_Andrascik

  • Hrdina
  • ****
  • Příspěvků: 459
  • Karma: 19
    • Verze Delphi: D2007, XE3
Re:Nastavení virtuálního sériového portu
« Odpověď #9 kdy: 15-04-2019, 21:42:34 »
Ked sa ti to nebude moc darit, napis si vlastnu dll v delphi s TComPortom a volaj ju z excelu ;)

Online Faltynek

  • Plnoletý
  • ***
  • Příspěvků: 167
  • Karma: 2
    • Verze Delphi: D5 Enterprise, D2009
Re:Nastavení virtuálního sériového portu
« Odpověď #10 kdy: 25-04-2019, 19:50:03 »
Dobrý den všem,
konečně jsem se k tomu prokousal a už to funguje přes funkce kernelu. Ne že bych byl tak chytrý, abych to sám napsal, na webu bylo dost na toto téma, ale až toto mi funguje. Pokud by to někoho zajímalo, tady je příklad ve VBA (je to sice Delphi konference, ale třeba se to bude někomu hodit, až to po něm manažeři budou chtít. Deklarace funkcí a globálních konstant neuvádím, kdyby někdo chtěl, pošlu na mail): 
Kód: Delphi [Vybrat]
  1. Public Sub Init_Com()
  2.     Dim rc As Long
  3.     Dim h As Long
  4.     h = CreateFile("\\.\COM4", GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, _
  5.                                 FILE_ATTRIBUTE_NORMAL, 0)
  6.     'For serial port numbers higher than 9 see KB115831
  7.    If h = -1 Then
  8.        rc = Err.LastDllError
  9.        Select Case rc 'Two typical error codes when trying to open a serial port:
  10.          Case ERROR_ACCESS_DENIED  ' - The serial port opened by another application
  11.           MsgBox "The serial port is used by another program"
  12.         Case ERROR_FILE_NOT_FOUND ' - The serial port does not exist, check the port name specified in the CreateFile()
  13.            MsgBox "The serial port does not exist"
  14.          Case Else
  15.            MsgBox "CreateFile failed, the error code is " & Str(rc)
  16.         End Select
  17.         Exit Sub
  18.     End If
  19.  
  20.     Dim d As DCB 'The DCB structure and the SetCommState() function allow to set the baud rate and the byte size of the serial port.
  21.    rc = GetCommState(h, d)
  22.    d.ByteSize = 8
  23.    d.BaudRate = 230400
  24.    d.fBitFields = F_BINARY 'Windows does not support non-binary data transfers so the flag must always be set in the DCB structure.
  25.    
  26.     'Another example how to set some flags in the DCB.
  27.    'd.fBitFields = F_BINARY Or F_PARITY Or F_RTS_CONTROL_ENABLE
  28.    
  29.     d.StopBits = ONESTOPBIT
  30.     d.Parity = EVENPARITY
  31.     rc = SetCommState(h, d)
  32.     If rc = 0 Then
  33.       rc = Err.LastDllError
  34.       MsgBox "SetCommState failed, the error code is " & Str(rc)
  35.     End If
  36.    
  37.     Dim timeouts As COMMTIMEOUTS 'Because we don't want communication timeouts to hang the VB code,
  38.     rc = GetCommTimeouts(h, timeouts)  'we need to specify the maximum time Windows will wait for incoming data
  39.    timeouts.ReadIntervalTimeout = 3  'The max. time in milliseconds between arrival of any two bytes
  40.     timeouts.ReadTotalTimeoutConstant = 20 'The max. time the ReadFile() function will wait for data.
  41.    timeouts.ReadTotalTimeoutMultiplier = 0
  42.    rc = SetCommTimeouts(h, timeouts)
  43.    If rc = 0 Then
  44.      rc = Err.LastDllError
  45.      MsgBox "SetCommTimeouts failed, the error code is " & Str(rc)
  46.      GoTo close_and_exit
  47.    End If
  48.    
  49.  
  50. '    Dim bWrite(1 To 3) As Byte 'Sending an array of 3 bytes to a remote device.
  51. '    bWrite(1) = &HA1
  52. '    bWrite(2) = &HB2
  53. '    bWrite(3) = &HC3
  54.     Dim bWrite(1 To 5) As Byte 'Sending an array of 3 bytes to a remote device.
  55.    bWrite(1) = Asc("I")
  56.    bWrite(2) = Asc("_")
  57.    bWrite(3) = Asc("P")
  58.    bWrite(4) = Asc("S")
  59.    bWrite(5) = &HD
  60.    Dim wr As Long
  61.    rc = WriteFile(h, bWrite(1), 5, wr, 0) 'wr indicates how many bytes went to the port.
  62.     If rc = 0 Then
  63.       rc = Err.LastDllError
  64.       MsgBox "WriteFile failed, the error code is " & Str(rc)
  65.       GoTo close_and_exit
  66.     End If
  67.    
  68.     'Now we want to receive an answer from the remote device.
  69.    Dim bRead(1 To 20) As Byte  'We want to receive up to 20 bytes.
  70.     Dim rd As Long
  71.     rc = ReadFile(h, bRead(1), 20, rd, 0) 'rd indicates how many bytes received from the port.
  72.    If rc = 0 Then
  73.      rc = Err.LastDllError
  74.      MsgBox "ReadFile failed, the error code is " & Str(rc)
  75.      GoTo close_and_exit
  76.    End If
  77.    
  78.    Dim s As String 'Printing the received data in hexadecimal form.
  79.     Dim i As Long
  80.     For i = 1 To rd
  81.         s = s & Chr(bRead(i)) & " "
  82.     Next i
  83.     MsgBox s
  84.    
  85. close_and_exit:
  86.     rc = CloseHandle(h) 'In VBA, always execute this call. Or you will receive the ERROR_ACCESS_DENIED next time then opening the port
  87.                        'and you will need to reload Word/Excel/Access to free the port.
  88.  
  89. End Sub
  90.  
Dalibor.
Dalibor (D2009 Enterprise, dřív D5Enterprise)