Accesso alle Porte Seriali
Possiamo accedere alle Porte Seriali [nota 1] aprendo e leggendo direttamentre i dati provenienti dai relativi file-device.
Poniamo l'esempio di avere una penna USB per la connessione ad Internet, e che alla sua connessione il sistema operativo abbia generato due relativi file-device: "/dev/ttyUSB0 " e "/dev/ttyUSB1 " [nota 2].
Possiamo leggere i dati provenienti dalla porta mediante due modalità:
- direttamente dal relativo file-device, ad esempio, "/dev/ttyUSB1 ";
- mediante l'apposita classe "SerialPort".
Indice
Mediante lettura diretta dal corrispondente file-device
Per il seguente esempio è necessario attivare anche il componente "gb.desktop", ed aver installato il programma "x-term":
Private fl As File Public Sub Button1_Click() ' Se il file non possiede i più ampi permessi... If Stat("/dev/ttyUSB1").Auth <> "rwsrwxrwx" Then ' ...allora modificheremo in quel senso i permessi del file: Desktop.RunAsRoot("chmod 4777 /dev/ttyUSB1") ' Restiamo in attesa fino a che i permessi non vengono modificati, come desiderato: Do Wait 0.01 Loop Until Stat("/dev/ttyUSB1").Auth = "rwsrwxrwx" Endif ' In alternativa all'algoritmo precedente, ' si potrà utilizzare il seguente codice per impostare il setUID ' e consentire l'apertura del file protetto: Exec ["gksu", "chmod 4777", "/dev/ttyUSB1"] Wait ' ...o ancor più facilmente: Shell "echo < mia_password > | sudo -S chmod 4777 '/dev/ttyUSB1'" Wait ' Apriamo il file-device aggiungendo la parola chiave "Watch": fl = Open "/dev/ttyUSB1" For Read Watch End Public Sub File_Read() Dim s As String While Not Eof(fl) ' Leggiamo i dati provenienti dal file-device...: Line Input #fl, s ' ...e li mostriamo in console: Print s Wend End
Lettura mediante la classe SerialPort
La lettura della Porta Seriale portà avvenire anche mediante l'uso della Classe "SerialPort" attivando il componente gb.net.
Private SerialPort1 As SerialPort Public Sub Button1_Click() SerialPort1 = New SerialPort As "portaseriale" ' Facciamo in modo da poter inserire la password di root ' per impostare il setUID e consentire l'apertura del file protetto: Shell "echo 'mia_password' | sudo -S chmod 4777 '/dev/ttyUSB1'" Wait With SerialPort1 .PortName = "/dev/ttyUSB1" .Speed = 19200 .Parity = 0 .DataBits = 8 .StopBits = 1 .FlowControl = 0 .Open End With End Public Sub portaseriale_Read() Dim s As String ' Legge i dati dalla porta.... Read #SerialPort1, s, Lof(SerialPort1) ' ...e li mostra in console: Print s End Public Sub Form_Close() If SerialPort1.Status = Net.Active Then SerialPort1.Close End
Mostriamo, di seguito, un altro codice [nota 3] più complesso che possiede alcune funzioni capaci di inviare richieste cicliche e di dare risposte a seconda dei dati giunti dalla seriale, nonché di conteggiare richieste e risposte.
Private SPort As SerialPort Private Timer1 As Timer Private ChkDTR As CheckBox Private ChkRTS As CheckBox Private ChkCTS As CheckBox Private ChkDCD As CheckBox Private ChkDSR As CheckBox Private ChkRNG As CheckBox Private TextLabel1 As TextLabel Private TextLabel2 As TextLabel Private TextLabel3 As TextLabel Private TextLabel4 As TextLabel Private TextLabel5 As TextLabel Private Label1 As Label Private TxtPort As TextBox Private CmbSpeed As ComboBox Private CmbParity As ComboBox Private CmbData As ComboBox Private CmbStop As ComboBox Private Button1 As Button Private ComboBox1 As ComboBox Private Esci As Button Private Separator1 As Separator Private CicloCheck As CheckBox Private SERIALE As TextLabel Private Label3 As Label Private CheckBox1 As CheckBox Private TEMPO As TextBox Private Label2 As Label Private TxtSend As TextBox Private TextLabel6 As TextLabel Private RUN_COUNT As TextLabel Private RUN As Button Private TextArea1 As TextArea Private COMPARA_BOX As CheckBox Private VALORE_COMPARA As TextBox Private NUMERO_CARATTERI As ComboBox Private Separator2 As Separator Private RISPONDI As CheckBox Private RISPOSTA As TextBox Private Label4 As Label Private COMP_OK As TextLabel Private RISPOSTE_OK As Label Private RISP_OK As TextLabel Public Sub _new() With Me .AutoResize = True .Expand = True .Center .H = 560 .W = 500 .Text = "Serial Port Exended" End With With SPort = New SerialPort As "SPort" .DataBits = .Bits8 .FlowControl = .Hardware .Parity = .None .Speed = 192000 .StopBits = .Bits1 End With Timer1 = New Timer With ChkDTR = New CheckBox(Me) As "ChkDTR" .H = 28 .W = 76 .X = 330 .Y = 7 .Text = "DTR" End With With ChkRTS = New CheckBox(Me) As "ChkRTS" .H = 28 .W = 76 .X = 330 .Y = 28 .Text = "RTS" End With With ChkCTS = New CheckBox(Me) .H = 28 .W = 76 .X = 330 .Y = 49 .Text = "CTS" End With With ChkDCD = New CheckBox(Me) .H = 28 .W = 76 .X = 330 .Y = 70 .Text = "DCD" End With With ChkDSR = New CheckBox(Me) .H = 28 .W = 76 .X = 330 .Y = 91 .Text = "DSR" End With With ChkRNG = New CheckBox(Me) .H = 28 .W = 76 .X = 330 .Y = 112 .Text = "RNG" End With With TextLabel1 = New TextLabel(Me) .H = 28 .W = 146 .X = 63 .Y = 7 .Alignment = Align.Left .Text = "Port Name :" End With With TextLabel2 = New TextLabel(Me) .H = 28 .W = 146 .X = 63 .Y = 35 .Alignment = Align.Left .Text = "Speed :" End With With TextLabel3 = New TextLabel(Me) .H = 28 .W = 146 .X = 63 .Y = 63 .Alignment = Align.Left .Text = "Parity :" End With With TextLabel4 = New TextLabel(Me) .H = 28 .W = 146 .X = 63 .Y = 91 .Alignment = Align.Left .Text = "Data Bits :" End With With TextLabel5 = New TextLabel(Me) .H = 28 .W = 146 .X = 63 .Y = 119 .Alignment = Align.Left .Text = "Stop Bits :" End With With Label1 = New Label(Me) .H = 28 .W = 105 .X = 77 .Y = 175 .Alignment = Align.Left .Text = "Flow control :" End With With TxtPort = New TextBox(Me) .H = 28 .W = 105 .X = 217 .Y = 7 .Alignment = Align.Center .Text = "/dev/ttyUSB0" End With With CmbSpeed = New ComboBox(Me) .H = 28 .W = 105 .X = 217 .Y = 35 .List = ["1200", "2400", "4800", "9600", "19200", "38400", "57600", "112000"] .ReadOnly = True End With With CmbParity = New ComboBox(Me) .H = 28 .W = 105 .X = 217 .Y = 63 .List = ["None", "Even", "Odd"] .ReadOnly = True .Text = .List[0] End With With CmbData = New ComboBox(Me) .H = 28 .W = 105 .X = 217 .Y = 91 .List = ["8", "7", "6", "5"] .ReadOnly = True .Text = .List[0] End With With CmbStop = New ComboBox(Me) .H = 28 .W = 105 .X = 217 .Y = 119 .List = ["1", "2"] .ReadOnly = True .Text = .List[0] End With With Button1 = New Button(Me) As "Open" .H = 28 .W = 105 .X = 217 .Y = 147 .Text = "&Open" .Tooltip = "Apre la comunicazione" End With With ComboBox1 = New ComboBox(Me) .H = 28 .W = 140 .X = 182 .Y = 175 .List = ["NONE", "CRTSCTS", "XON/XOFF", "CRTSCTS + XON/XOFF"] .ReadOnly = True .Text = .List[0] End With With Esci = New Button(Me) As "Esci" .H = 42 .W = 42 .X = 440 .Y = 14 .Picture = Picture["icon:/32/shutdown"] .Tooltip = "Esci" End With With Separator1 = New Separator(Me) .H = 14 .W = Me.W .X = 0 .Y = 202 End With With CicloCheck = New CheckBox(Me) .H = 21 .W = 21 .X = 35 .Y = 224 .Tooltip = "Invia in maniera ciclica" End With With SERIALE = New TextLabel(Me) .H = 28 .W = 28 .X = 63 .Y = 217 .Background = Color.Red .Border = Border.Plain End With With Label3 = New Label(Me) .H = 28 .W = 49 .X = 105 .Y = 217 .Text = "CICLO" End With With CheckBox1 = New CheckBox(Me) .H = 28 .W = 168 .X = 182 .Y = 217 .Text = "LETTURA SERIALE" .Tooltip = "Attiva il monitoraggio della seriale" .Value = True End With With TEMPO = New TextBox(Me) .H = 28 .W = 140 .X = 63 .Y = 245 .Text = "50" .Tooltip = "Durata del ciclo X5" End With With Label2 = New Label(Me) .H = 28 .W = 91 .X = 210 .Y = 245 .Text = "TEMPO ms X 5" End With With TxtSend = New TextBox(Me) .H = 28 .W = 140 .X = 63 .Y = 273 .Text = "Comando da inviare" End With With TextLabel6 = New TextLabel(Me) .H = 28 .W = 70 .X = 210 .Y = 273 .Alignment = Align.Left .Text = "COMANDO" End With With RUN_COUNT = New TextLabel(Me) .H = 28 .W = 77 .X = 287 .Y = 273 .Alignment = Align.Right .Background = &3F3FFF .Text = "0" .Tooltip = "Numero di comandi inviati, viene azzerato ad ogni invio manuale, per una statistica usare l'invio ciclico" End With With RUN = New Button(Me) .H = 28 .W = 70 .X = 372 .Y = 273 .AutoResize = True .Text = "RUN" .Tooltip = "Invia il comando" End With With TextArea1 = New TextArea(Me) .H = 174 .W = 482 .X = 7 .Y = 308 .Background = &FFFF9F .Tooltip = "Monitor dei dati ricevuti dalla seriale" End With With COMPARA_BOX = New CheckBox(Me) .H = 28 .W = 84 .X = 14 .Y = 490 .Text = "COMPARA" .Tooltip = "Esegui la comparazione del dato ricevuto" End With With VALORE_COMPARA = New TextBox(Me) .H = 28 .W = 70 .X = 105 .Y = 490 .Tooltip = "Dato da usare per la comparazione" End With With NUMERO_CARATTERI = New ComboBox(Me) .H = 28 .W = 42 .X = 182 .Y = 490 .List = ["1", "2", "3", "4", "5", "6", "7", "8"] .Text = "0" .Tooltip = "Numero di caratteri ricevuti da analizzare nella comparazione partendo dalla fine della stringa" End With With Separator2 = New Separator(Me) .H = 70 .W = 28 .X = 238 .Y = 483 End With With RISPONDI = New CheckBox(Me) .H = 28 .W = 90 .X = 322 .Y = 490 .Text = "RISPONDI" .Tooltip = "Invia una risposta se il dato di comparazione viene soddisfatto" End With With RISPOSTA = New TextBox(Me) .H = 28 .W = 70 .X = 413 .Y = 490 .Tooltip = "dato inviato come risposta" End With With Label4 = New Label(Me) .H = 21 .W = 106 .X = 14 .Y = 525 .Background = &FFDF7F .Text = "COMPARAZ. OK" End With With COMP_OK = New TextLabel(Me) .H = 21 .W = 56 .X = 119 .Y = 525 .Alignment = Align.Right .Background = &FF8000 .Text = "0" .Tooltip = "Numero di comparazioni corrette, viene azzerato ad ogni invio manuale, per una statistica usare l'invio ciclico" End With With RISPOSTE_OK = New Label(Me) .H = 21 .W = 105 .X = 322 .Y = 525 .Background = &FFDF7F .Text = "RISPOSTE OK" End With With RISP_OK = New TextLabel(Me) .H = 21 .W = 56 .X = 427 .Y = 525 .Alignment = Align.Right .Background = &FF8000 .Text = "0" .Tooltip = "Numero di risposte inviate" End With End Public Sub Form_Close() If Sport.Status = Net.Active Then Close Sport End Private Sub Check_Status() ChkDSR.Value = Sport.DSR ChkDTR.Value = Sport.DTR ChkCTS.Value = Sport.CTS ChkRTS.Value = Sport.RTS ChkDCD.Value = Sport.DCD ChkRNG.Value = Sport.RNG 'End Private HACK As String Private SC As Integer ' Controllo stabilità connessione Private RC As Integer ' Conteggio invii RUN Private NC As Integer ' Numero caratteri da comparare (da fine stringa) Public Sub Open_Click() If Sport.Status = Net.Active Then Close Sport Button1.Text = "&Open" Else ' Parametri: Sport.PortName = TxtPort.Text Sport.Speed = CmbSpeed.Text Sport.Parity = CmbParity.Index Sport.DataBits = CmbData.Text Sport.StopBits = CmbStop.Text Sport.FlowControl = ComboBox1.Index Sport.Open() Check_Status() TextArea1.Text = "Port Opened : " & Sport.PortName & " Settings : " & Sport.Speed & "," & Sport.Parity & "," & Sport.DataBits & "," & Sport.StopBits & Chr(13) & Chr(10) Button1.Text = "&Close" RC = 0 SC = 0 RUN_COUNT.Text = "0" COMP_OK.Text = "0" RISP_OK.Text = "0" Endif Catch Message.Info("Errore apertura seriale , verificare porta") End Public Sub SPort_Read() Dim s As String Read #Sport, s, Lof(Sport) If CheckBox1.Value = True Then TextArea1.Text = TextArea1.Text & s '***************************************** ANALISI STRINGA *************************************** ' COMPARAZIONE If COMPARA_BOX.Value = True Then NC = NUMERO_CARATTERI.Text If Right$(TextArea1.Text, (NC)) = VALORE_COMPARA.Text Then SC = SC + 1 COMP_OK.Text = SC If COMP_OK.Text = 300 Then TextArea1.Text = "" Endif Endif ' RISPOSTA If RISPONDI.Value = True Then NC = NUMERO_CARATTERI.Text If Right$(TextArea1.Text, (NC)) = VALORE_COMPARA.Text Then Print #Sport, RISPOSTA.Text; SC = SC + 1 RISP_OK.Text = SC If RISP_OK.Text = 300 Then TextArea1.Text = "" Endif Endif End Public Sub RUN_Click() Dim T As Integer If CicloCheck.Value Then If RUN.Text = "RUN" Then RUN.Text = "STOP" Else RUN.Text = "RUN" Endif Endif RC = 0 SC = 0 T = TEMPO.Text If CicloCheck.Value = True Then Timer1.Delay = TEMPO.Text If Timer1.Enabled Then Timer1.Enabled = False Else Timer1.Enabled = True Endif Else Print #Sport, TxtSend.Text; Endif Catch Message("Apri la porta!") End Public Sub ChkDTR_Click() Sport.DTR = ChkDTR.Value Check_Status End Public Sub ChkRTS_Click() Sport.RTS = ChkRTS.Value Check_Status End Public Sub ComboBox1_Click() Sport.FlowControl = ComboBox1.Index End Public Sub Form_Open() cmbSpeed.Index = cmbSpeed.Find("9600") End Private C As Integer Private IND As Integer Public Sub Timer1_Timer() If Sport.Status = Net.Inactive Then Message("Apri la porta!") RUN.Text = "RUN" Timer1.Enabled = False Else If IND < 33 Then IND = 33 If C = 5 Then If IND = 62 Then IND = 33 TextArea1.Clear Else IND = IND + 1 Endif Print #Sport, TxtSend.Text; C = 0 RC = RC + 1 RUN_COUNT.Text = RC Else C = C + 1 Endif SERIALE.Text = C Endif End Public Sub Esci_Click() If Button1.Text = "&Close" Then Open_Click Me.Close End
Note
[1] Vedere anche questa pagina: Approfondimento sull'accesso alle porte USB
[2] In tali altri casi il file-device creato può essere: "/dev/ttyACM0"
[3] Il codice è stato realizzato dal utente "astragalo ".