Visualizzazione dei risultati da 1 a 3 su 3
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2010
    Messaggi
    20

    [VB6] Problema ricezione dati con MsComm indicizzati

    Salve a tutti, avrei bisogno di una grossa mano.
    Sto sviluppando un'interfaccia che deve gestire in contemporanea diversi oggetti (di cui ho scritto il firmware).
    Non so a priori quanti dispositivi verranno collegati al pc, mi occorre quindi riconoscerli, è stata però fatta la scelta di limitare il numero massimo di dispositivi collegabili a 10.

    A questo punto nella finestra di setting del sistema (dove vengono riconosciuti i dispositivi) ho deciso di scrivere una funzione che:

    - Prova ad aprire una porta utilizzando un oggetto mscomm temporaneo
    - Se viene dato errore passa alla porta successiva
    - Se riesce ad aprirla verifica che su quella porta sia collegato uno dei miei dispositivi.
    - Se è collegato uno dei miei dispositivi copio le impostazioni di questa porta in uno dei 10 oggetti MSComm "ufficiali" (cioè uno che non sia quello temporaneo che viene utilizzato solo in questa fase).

    Questo viene effettuato finchè non ho trovato 10 dispositivi o finchè non ho controllato la porta COM99 (cioè la massima possibile).
    A questo punto se non ho dispositivi collegati do errore, altrimenti utilizzo i dispositivi che ho.

    La funzione è questa:
    codice:
    Public Function ComOpener()
    Dim i As Integer
        
        ' Dalla porta a cui sono arrivato in poi
        For i = Portcnt To 10
            ' Se non ho giù aperto tutte le 10 porte
            If Commcnt < 10 Then
                ' Inizializza temp
                With cmmTmp
                  .CommPort = i
                    .Settings = COMM_SETTING
                    .InputMode = comInputModeBinary
                    .InputLen = 0
                    .RThreshold = 256
                    .DTREnable = False
                    On Error Resume Next
                    ' Apre la prossima porta
                    .PortOpen = True
                    ' Se c'è stato errore la porta non è disponibile
                    If Err Then
                            'MsgBox ("no port" & i)
                    Else
                        ' Sennò attiva il timer, inizializza le variabili e aspetta il risultato che indica se la porta è disponibile
                        tmrPortRec.Enabled = True
                        goodPort = 0
                        Portcnt = i
                        'inizializza la SM
                        PORT_SM_curr = WAIT_ESC
                        PORT_SM_next = WAIT_ESC
                        While (tmrPortRec.Enabled <> False) And (goodPort = 0)
                            DoEvents
                        Wend
                        ' Arrivati qua la funzione Verify_HW ha già verificato che la porta è disponibile
                        ' O il timer è scaduto e la porta non è disponibile
                        ' Se la porta è disponibile cmmTmp viene copiato sul primo mscomm libero dalla routine del timer
                    End If
                    .PortOpen = False
                End With
            End If
    
        Next
        If Commcnt = 0 Then
             MsgBox (GStr.REGErrNoDev)
        End If
    End Function
    Dove tutte le variabili non dichiarate ma utilizzate sono globali all'interno del modulo e COMM_SETTING è una costante che vale "115200, N, 8, 1".
    In particolare PORT_SM_curr e PORT_SM_next vengono utilizzzate in una macchina a stati che utilizzo per riconoscere il dispositivo.
    Questo perchè i miei dispositivi, quando alimentati iniziano ad inviare uno stream continuo di dati, formattati in un certo modo.
    Avendo un header, un payload e un footer (con CRC) la mia idea è di controllare che il pacchetto ricevuto sia coerente (CRC corretto, lunghezza dei dati uguale a quella indicata ecc)
    con quanto atteso.)

    Come si vede sopra se la porta viene aperta attivo un timer che viene inizializzato durante l'evento activate del form e che ha interval = 5000 (in realtà in 5 secondi ricevo
    un gran numero di pacchetti, ma per ora ho messo di proposito un tempo lungo per essere sicuro di riceverne almeno uno).
    Se il timer va in timeout considero il dispositivo collegato non valido (cioè non uno dei miei dispositivi).
    codice:
    Private Sub cmmTmp_OnComm()
    
        Dim data() As Byte
        Dim i As Integer
        data = cmmTmp.Input
    
        For i = 0 To 256
            If goodPort = 0 Then
                Verify_HW (data(i))
            End If
        Next
    
    End Sub
    Una macchina a stati (Verify_HW) mi permette di verificare che il pacchetto sia corretto, in questo caso fermo il timer tmrPortRec, setto goodPort a 1 e chiamo
    la routine di gestione di overflow del timer (queste operazione vengono effettuate dalla macchina a stati)...cioè questa:
    codice:
    Private Sub tmrPortRec_Timer()
            
        If goodPort = 1 Then
            cmmTmp.PortOpen = False
             With cmmInput(Commcnt)
                    .CommPort = Portcnt
                    .Settings = COMM_SETTING
                    .InputMode = comInputModeBinary
                    .InputLen = 0
                    .RThreshold = 256
                    .DTREnable = False
                If .PortOpen = True Then
                    .PortOpen = False
                End If
            End With
            Commcnt = Commcnt + 1
        End If
    
    tmrPortRec.Enabled = False
    
    End Sub
    che nel caso di cuscinetto buono (goodPort = 1) copia i valori della porta corrente in un altro oggetto MSComm come spiegato prima.

    Come si nota nel codice gli oggetti MsComm su cui vado a copiare i setting di cmmTmp sono indicizzati, si chiamano cioè tutti cmmInput e
    vengono identificati tramite un indice.

    Fin qua tutto ok, sembra funzionare tutto...ora vi spiego il problema vero e proprio.


    Una volta riconosciuto il numero di dispositivi collegati al pc devo riconoscere il loro ID. per fare ciò agisco come prima: ricevo cioè un pacchetto e ne lo elaboro come necessario...
    ciò che cambia rispetto a prima è l'oggetto MSComm.

    La routine del pulsante Wait è quella che si comporta in maniera analoga a ComOpener:
    codice:
    Private Sub btnWait_Click()
        Dim i As Integer
        btnSave.Enabled = False
        lblAddr.Caption = ""
    
        
        waiting4ID = 1
        
        ' Inizializza la SM
        ID_SM_curr = WAIT_ESC
        ID_SM_next = WAIT_ESC
        
        On Error Resume Next
        ' Apre le porte
        For i = 0 To Commcnt - 1
            With cmmInput(i)
                    .Settings = COMM_SETTING
                    .InputMode = comInputModeBinary
                    .InputLen = 0
                    .RThreshold = 256
                    .DTREnable = False
                    .PortOpen = True
            End With
        Next
       
        tmrIDrec.Enabled = True
        ' Aspetta l'ID
        While (tmrIDrec.Enabled <> False) And (waiting4ID = 1)
            DoEvents
        Wend
        
        On Error Resume Next
        'Chiude le porte
        For i = 0 To Commcnt
            cmmInput(i).PortOpen = False
        Next
        
        ' Se non ha trovato nulla
        If lblAddr.Caption = "" Then
            ' Lo segnala
            MsgBox (GStr.REGErrNoID)
        Else
            ' Sennò abilita il pulsante Save
            btnSave.Enabled = True
        End If
    
    End Sub
    waiting4id è una variabile globale che ha funzione simile a quella di goodPort con la differenza che questa rimane a 1 fino a che non è stato ricevuto un ID ( o fino a quando non scade il timer).

    In pratica da qua in poi il comportamento del programma dovrebbe essere quello di prima, con la differenza che viene chiamata una macchina a stati diversa da quella di prima.

    Il mio problema è però che l'evento OnComm dei vari cmmInput non viene mai scatenato, mentre io son sicuro che in quel momento dei dati stannoarrivando sulla seriale.
    Non arrivando dati il timer scade e non riconosco nessun ID...

    Per togliermi ogni dubbio ho provato anche a creare un ulteriore oggetto MSComm, inizializzarlo allo stesso modo di cmmInput(0) (per ora sto provando il tutto con un solo dispositivo) e vedere se in questo caso
    ricevo dati e la risposta è si..funziona correttamente.
    Mi viene quindi il dubbio che il problema stia nel fatto che i miei cmmInput sono indicizzati.
    Per completezza vi metto anche la routine di gestione dell'evento OnComm deio vari cmmInput.
    codice:
    Private Sub cmmInput_OnComm(Index As Integer)
        Dim data() As Byte
        Dim i As Integer
        data = cmmInput(Index).Input
    
        For i = 0 To 256
            If waiting4ID = 1 Then
                Receiver_SM (data(i))
            End If
        Next
    End Sub
    Mi rendo conto di aver sbrodolato un po' la faccenda ma spero di essere stato chiaro... vi sarei grato se qualcuno potesse spiegarmi dove sta il problema perchè io non so più dive sbattere la testa.

    Grazie mille in anticipo

  2. #2
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    758

    Re: [VB6] Problema ricezione dati con MsComm indicizzati

    Originariamente inviato da Apoman
    Il mio problema è però che l'evento OnComm dei vari cmmInput non viene mai scatenato, mentre io son sicuro che in quel momento dei dati stannoarrivando sulla seriale.
    Quanti dati? Almeno 256 bytes (valore di Rthreshold)?
    Non ho esaminato in dettaglio il codice (è un po' troppo). Caso mai, se il motivo non è quello che ti ho indicato un po' a naso, cerca di sintetizzare un po' sia la descrizione che il codice, isolando il problema.

  3. #3
    Utente di HTML.it
    Registrato dal
    Jun 2010
    Messaggi
    20
    Ciao,
    arrivano ben più di 256 campioni.
    Ora, sinceramente ieri son tornato dalla pausa pranzo, non ho cambiato una linea di codice che sia una e i dati venivano ricevuti.
    Io non me lo so spiegare...probabilmente è il mio PC che è posseduto. Grazie lo stesso per l'aiuto

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.