Newsgroup: it.comp.lang.visual-basic
Titolo: Comunicazioni sulla seriale

Sto provando del codice che ho trovato sulla knowledge base italiana del
sito microsoft intitolato Esempio di uso delle API per la comunicazione
seriale id articolo: I14415
purtroppo non funziona cioč in ricezione non riceve nulla e sulla textbox in
cui dovrebbe apparire il testo inviato non appare nulla. Ora mi chiedo ma
attacato alla porta seriale non  ci deve essere nulla ? anche perchč non
viene specificato nulla dalla microsoft
riporto di seguito l'intero testo che ho reperito
L'esempio che segue illustra una applicazione Visual Basic che permette di
inviare e ricevere del testo sulla seriale. Il testo inviato e' quello che
viene editato in una text box (txtSend), mentre il testo ricevuto compare su
una seconda text box (txtReceive).
Occorre aprire un nuovo progetto Visual Basic StandardEXE con un form
(FORM1) e un modulo standard (MODULE1).
MODULE1.BAS
Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _
  ByVal lpFileName As String, _
  ByVal dwDesiredAccess As Long, _
  ByVal dwShareMode As Long, _
  ByVal lpSecurityAttributes As Long, _
  ByVal dwCreationDisposition As Long, _
  ByVal dwFlagsAndAttributes As Long, _
  ByVal hTemplateFile As Long) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Declare Function GetCommState Lib "kernel32" ( _
  ByVal nCid As Long, _
  lpDCB As DCB) As Long
Declare Function SetCommState Lib "kernel32" ( _
  ByVal hCommDev As Long, _
  lpDCB As DCB) As Long
Declare Function FlushFileBuffers Lib "kernel32" (ByVal hFile As Long) _
  As Long
Declare Function WriteFile Lib "kernel32" ( _
  ByVal hFile As Long, _
  lpBuffer As Any, _
  ByVal nNumberOfBytesToWrite As Long, _
  lpNumberOfBytesWritten As Long, _
  ByVal lpOverlapped As Long) As Long
Declare Function ReadFile Lib "kernel32" ( _
  ByVal hFile As Long, _
  lpBuffer As Any, _
  ByVal nNumberOfBytesToRead As Long, _
  lpNumberOfBytesRead As Long, _
  ByVal lpOverlapped As Long) As Long
Declare Function GetCommTimeouts Lib "kernel32" ( _
  ByVal hFile As Long, _
  lpCommTimeouts As COMMTIMEOUTS) As Long
Declare Function SetCommTimeouts Lib "kernel32" ( _
  ByVal hFile As Long, _
  lpCommTimeouts As COMMTIMEOUTS) As Long
Type COMMTIMEOUTS
        ReadIntervalTimeout As Long
        ReadTotalTimeoutMultiplier As Long
        ReadTotalTimeoutConstant As Long
        WriteTotalTimeoutMultiplier As Long
        WriteTotalTimeoutConstant As Long
End Type
' Nota: La definizione del tipo DCB fornita dall'API VIEWER di ' Visual
Basic 4.0 e' scorretta! La seguente e' quella corretta, ' cosi' come fornita
dall'API VIEWER di Visual Basic 5.0.
Type DCB
        DCBlength As Long
        BaudRate As Long
        fBitFields As Long ' Vedi i commenti in Win32API.Txt
        wReserved As Integer
        XonLim As Integer
        XoffLim As Integer
        ByteSize As Byte
        Parity As Byte
        StopBits As Byte
        XonChar As Byte
        XoffChar As Byte
        ErrorChar As Byte
        EofChar As Byte
        EvtChar As Byte
        wReserved1 As Integer ' Riservata; da non usare
End Type
Public Const GENERIC_READ = &H80000000 Public Const GENERIC_WRITE =
&H40000000 Public Const INVALID_HANDLE_VALUE = -1& Public Const
OPEN_EXISTING = 3 Public Const NOPARITY = 0
Public Const ONESTOPBIT = 0 Public Const MAXDWORD = &HFFFF
FORM1.FRM
FORM1 contiene 5 controlli:
Due controlli text box (txtSend e txtReceive) con la proprieta' Multiline su
True;
Due command button (cmdInitialize e cmdClose);
Un controllo timer (tmrReceive) con la proprieta' Interval impostata su un
opportuno valore diverso da 0 (es. 300 msec).
Option Explicit
' handle al file sulla porta seriale Private hCom As Long
Private Sub cmdClose_Click()
    ' inibisce il timer per la lettura periodica sulla porta seriale
    tmrReceive.Enabled = False
    ' Chiude il file di comunicazione
    CloseHandle (hCom)
End Sub
Private Sub Form_Load()
    ' inibisce il timer per la lettura periodica sulla porta seriale
    tmrReceive.Enabled = False
End Sub
Private Sub tmrReceive_Timer()
    ' effettua una lettura periodica dalla
    ' porta seriale, usando un buffer di 10 byte;
    ' trasferisce inoltre il contenuto del buffer in una text box.
    Const BufferLen = 10
    Dim ReceivedBytes As Long
    Dim Buffer(1 To BufferLen) As Byte
    Dim i As Long
    Dim fSuccess As Integer
    Dim ferror As Integer
    ' legge dalla porta seriale; in particolare, imposta a 0 (NULL)
    ' l'ultimo parametro della ReadFile, poiche' la comunicazione
    ' sara' sincrona (non overlapped)
    fSuccess = ReadFile(hCom, Buffer(1), BufferLen, ReceivedBytes, 0)
    If (fSuccess <> 0) Then
        If ReceivedBytes <> 0 Then
            For i = 1 To ReceivedBytes
                txtReceive = txtReceive & Chr(Buffer(i))
            Next i
        End If
    Else
        ferror = Err.LastDllError
        ' gestione errore
    End If
End Sub
Private Sub NewTX(txtString As String)
    ' trasmette una stringa (txtString) sulla porta seriale, dopo
    ' averla impacchettata in un buffer di byte
    Dim BytesToBeSent As Long
    Dim SentBytes As Long
    Dim Buffer() As Byte
    Dim i As Long
    Dim fSuccess As Integer
    Dim ferror As Integer
    If txtString = "" Then Exit Sub
    BytesToBeSent = Len(txtString)
    ReDim Buffer(1 To BytesToBeSent)
    For i = 1 To BytesToBeSent
        Buffer(i) = Asc(Mid(txtString, i, 1))
    Next i
    ' scrive sulla porta seriale; in particolare, imposta a 0 (NULL)
    ' l'ultimo parametro della WriteFile, poiche' la comunicazione
    ' sara' sincrona (non overlapped)
    fSuccess = WriteFile(hCom, Buffer(1), BytesToBeSent, SentBytes, 0)
    If (fSuccess <> 0) And (SentBytes = BytesToBeSent) Then
        FlushFileBuffers (hCom)
    Else
        ferror = Err.LastDllError
        ' gestione errore
    End If
End Sub
Private Sub cmdInitialize_Click()
    ' inizializza la comunicazione sulla porta seriale
    Dim dcbVar As DCB
    Dim CommTimeoutsVar As COMMTIMEOUTS
    Dim fSuccess As Integer
    ' Apre un file associato alla porta seriale, in lettura e scrittura,
    ' usando l'opzione OPEN_EXISTING; in particolare, impostando a 0
    ' (nessun flag settato) il penultimo parametro della CreateFile,
    ' stabilisce indirettamente che la comunicazione sara' sincrona
    ' (non overlapped)
    hCom = CreateFile("COM1", GENERIC_READ Or GENERIC_WRITE, _
        0, 0&, OPEN_EXISTING, 0, 0)
    If hCom = INVALID_HANDLE_VALUE Then
        'gestione errori
        Exit Sub
    End If
    ' recupera le impostazioni di default della porta seriale e
    ' vi apporta i cambiamenti necessari (BaudRate, ByteSize ecc.)
    fSuccess = GetCommState(hCom, dcbVar)
    If fSuccess = False Then
        'gestione errori
        Exit Sub
    End If
    dcbVar.BaudRate = 38400
    dcbVar.ByteSize = 8
    dcbVar.Parity = NOPARITY
    dcbVar.StopBits = ONESTOPBIT
    ' Recupera le impostazioni di default riguardanti i timeout per
    ' la comunicazione sulla porta seriale e vi apporta i cambiamenti
    ' necessari; in particolare il valore MAXDWORD per ReadIntervalTimeout,
    ' combinato con il valore 0 per ReadTotalTimeoutMultiplier e
    ' ReadTotalTimeoutConstant, specifica che l'operazione di lettura deve
    ' finire immediatamente ritornando i byte che sono gia' stati ricevuti,
    ' persino se nessun byte e' stato ricevuto
    fSuccess = SetCommState(hCom, dcbVar)
    If fSuccess = False Then
        'gestione errori
        Exit Sub
    End If
    fSuccess = GetCommTimeouts(hCom, CommTimeoutsVar)
    If fSuccess = False Then
        'gestione errori
        Exit Sub
    End If
    CommTimeoutsVar.ReadIntervalTimeout = MAXDWORD
    CommTimeoutsVar.ReadTotalTimeoutMultiplier = 0
    CommTimeoutsVar.ReadTotalTimeoutConstant = 0
    fSuccess = SetCommTimeouts(hCom, CommTimeoutsVar)
    If fSuccess = False Then
        'gestione errori
        Exit Sub
    End If
    tmrReceive.Enabled = True
End Sub
Private Sub txtSend_KeyPress(KeyAscii As Integer)
    Dim s As String
    s = Chr(KeyAscii)
    NewTX (s)
End Sub

 attacato alla porta seriale non  ci deve essere nulla ?
Non dovrebbe essere necessario.
...(...)...
In realta' l' esempio non e' fatto molto bene, imho.
Il difetto principale ritengo sia il fatto che nello scaricamento del form
non controlla se la porta e' rimasta aperta. Sicche', se dai una cliccata di
troppo sul bottone che la apre, la com ti rimane aperta e non funziona piu'
nessun tentativo successivo di riaprirla.
Se riesegui il codice fai attenzione a seguire questi passi:
1) pulisci le text box;
2) clicca 1 volta su cmdInitialize;
3) scrivi nel txtSend e gustati il mirror su txtReceive;
4) clicca su cmdClose (o come diavolo l' hanno chiamato);
5) chiudi il form.
Ciao
Aldo