Solved

Problem with half duplex com port in VBA API

Posted on 2009-05-15
1
745 Views
Last Modified: 2013-11-27
I open the com port to a half duplex device (Minolta CR-400 camera) and can only successfully write to the device.  It accepts the 'take picture' command and takes the picture, but does not send anything back to me (or at least I can't get it).  It reads data correctly in a utility pgm that comes with the camera, so the camera is working.  I have the port open read+write access and all parms are set correctly (9600, 8, none, 1).  I have this same routine working in over 10 other projects so the syntax for the com port routines are fine.  The only difference between this project and the others is half duplex.  Is there some special configuration for half duplex?

I then tried to open a separate read channel and separate write channel to the camera com port.  I tried all the sharing options and no matter what combination I use, it fails on the second open with an INVALID_FILE_HANDLE error code (-1).  Here is the code called with "Output" on first call and "Input" on 2nd call.  I tried calling with "input" first and "output" second also.

Public Function OpenCom(ComPort As String, BaudRate As Long, DataBits As Integer, _
                        Parity As String, StopBits As String, Mode As String) As Long
Dim ComHwnd As Long
Dim ComDCB As DCB
Dim strParity As String
Dim strStopBits As String
Dim ComPortParms As String
     
    If Mode = "Input" Then
        ComHwnd = CreateFileA(ComPort, GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
    ElseIf Mode = "Output" Then
        ComHwnd = CreateFileA(ComPort, GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
    Else
        ComHwnd = CreateFileA(ComPort, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_NONE, 0, OPEN_EXISTING, 0, 0)
    End If
   
    If ComHwnd <> INVALID_FILE_HANDLE Then
       
        ' set parity string
        Select Case Parity
            Case "None"
                strParity = "N"
            Case "Even"
                strParity = "E"
            Case "Odd"
                strParity = "O"
            Case "Mark"
                strParity = "M"
            Case Else
                strParity = "N"
        End Select
       
        ' set stop bits string
        Select Case StopBits
            Case "1", "1 ", "1  "
               strStopBits = "1"
            Case "1.5"
               strStopBits = "1.5"
            Case "2", "2 ", "2  "
               strStopBits = "2"
            Case Else
               strStopBits = "1"
        End Select
       
        ComPortParms = "baud=" & BaudRate & " parity=" & strParity & " data=" & DataBits & " stop=" & strStopBits
        Call BuildCommDCBA(ComPortParms, ComDCB)
        Call SetCommState(ComHwnd, ComDCB)
        Call SetupComm(ComHwnd, INPUT_BUFFER_SIZE, OUTPUT_BUFFER_SIZE)
        OpenCom = ComHwnd
    Else
        OpenCom = INVALID_FILE_HANDLE
    End If

End Function

All the appropriate function declare and const declare is included at the top of this module.

Goal:
1.  I would prefer to open one channel (for read/wriite) to the com port and be able to write data to the camera and read responses from the camera.
2.  If that is not possible with half duplex, I want to be able to open the two comm channels and be able to write data to the camera and read responses from the camera.

Any help would be greatly appreciated, time is extremely urget.  Thanks.
0
Comment
Question by:compuzak1
1 Comment
 

Accepted Solution

by:
compuzak1 earned 0 total points
ID: 24403204
I got this problem figured out.  It had nothing to do with Half Duplex, had to do with flow control.  I was told I needed no flow control but in reality needed software flow control.  In the process, I cleaned this code up considerably and will post it here just in case someone else needs it.

OPEN COM PORT:

'  createfile constants
Public Const INVALID_FILE_HANDLE = -1
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const FILE_SHARE_NONE = &H0
Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2
Private Const OPEN_EXISTING = &H3

'  DCB structure constants
Private Const NOPARITY = 0
Private Const ODDPARITY = 1
Private Const EVENPARITY = 2
Private Const MARKPARITY = 3
Private Const ONESTOPBIT = 0
Private Const ONE5STOPBITS = 1
Private Const TWOSTOPBITS = 2
Private Const FBIT_XONFLOW = 21393
Private Const FBIT_NOFLOW = 20625
Private Const FBIT_HWFLOW = 24725

'  SetupComm constants
Private Const INPUT_BUFFER_SIZE = 255
Private Const OUTPUT_BUFFER_SIZE = 255

Private Type DCB
        DCBlength As Long
        BaudRate As Long
        fBitFields As Long ' See Comments in Win32API.Txt
        wReserved As Integer  ' reserved Do not use
        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 'Reserved; Do Not Use
End Type

Private Type COMMTIMEOUTS
    ReadIntervalTimeout As Long
    ReadTotalTimeoutMultiplier As Long
    ReadTotalTimeoutConstant As Long
    WriteTotalTimeoutMultiplier As Long
    WriteTotalTimeoutConstant As Long
End Type

Type COMSTAT
    fCtsHold As Integer
    fDsrHold As Integer
    fRlsdHold As Integer
    fXoffHold As Integer
    fXoffSent As Integer
    fEof As Integer
    fTxim As Integer
    fReserved As Integer
    cbInQue As Integer
    cbOutQue As Integer
End Type

Declare Function CreateFileA Lib "kernel32" _
       (ByVal lpFileName As String, _
        ByVal dwDesiredAccess As Long, _
        ByVal dwShareMode As Long, _
        ByVal lpSecurityAttributes As Long, _
        ByVal dwCreationDistribution As Long, _
        ByVal dwFlagsAndAttributes As Long, _
        ByVal hTemplateFile As Long) As Long

Declare Function BuildCommDCBA Lib "kernel32" _
        (ByVal lpDef As String, _
         lpDCB As DCB) As Integer
                 
Declare Function CloseHandle Lib "kernel32" _
        (ByVal idComDev As Long) As Long
       
Declare Function GetCommState Lib "kernel32" _
        (ByVal idComDev As Integer, _
         lpConfig As DCB) As Integer
         
Declare Function FlushFileBuffers Lib "kernel32" _
        (ByVal idComDev As Long) As Boolean
       
Declare Function WriteFile Lib "kernel32" _
        (ByVal idComDev As Long, _
         lpBuffer As Any, _
         ByVal nNumberOfBytesToWrite As Long, _
         lpNumberOfBytesWritten As Long, _
         ByVal lpOverlapped As Long) As Long
         
Declare Function ReadFile Lib "kernel32" _
        (ByVal idComDev As Long, _
         lpBuffer As Any, _
         ByVal nNumberOfBytesToRead As Long, _
         lpNumberOfBytesRead As Long, _
         lpOverlapped As Long) As Long
       
Declare Function SetCommState Lib "kernel32" _
        (ByVal idComDev As Long, _
         lpDCB As DCB) As Boolean
         
Declare Function SetCommTimeouts Lib "kernel32" _
        (ByVal hFile As Long, _
         lpCommTimeouts As COMMTIMEOUTS) As Long

Declare Function SetupComm Lib "kernel32" _
        (ByVal idComDev As Long, _
         ByVal dwInQueue As Long, _
         ByVal dwOutQueue As Long) As Boolean

Declare Function ClearCommError Lib "kernel32" _
        (ByVal idComDev As Long, _
         ByVal lpErrors As Long, _
         lpStat As COMSTAT) As Boolean
         
Declare Function GetLastError Lib "kernel32" () As Long

' open com port for read, write, or read & write
Public Function OpenCom(ComPort As String, OpenMode As String, BaudRate As Long, DataBits As Integer, _
                        Parity As String, StopBits As String, FlowControl As String) As Long

Dim ComDCB As DCB
Dim ComPortHandle As Long
     
    '  open com port for read, write, or both (no sharing)
    If OpenMode = "Input" Then
        ComPortHandle = CreateFileA(ComPort, GENERIC_READ, FILE_SHARE_NONE, 0, OPEN_EXISTING, 0, 0)
    ElseIf OpenMode = "Output" Then
        ComPortHandle = CreateFileA(ComPort, GENERIC_WRITE, FILE_SHARE_NONE, 0, OPEN_EXISTING, 0, 0)
    Else
        ComPortHandle = CreateFileA(ComPort, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_NONE, 0, OPEN_EXISTING, 0, 0)
    End If
   
    '  exit if there is an error
    If ComPortHandle = INVALID_FILE_HANDLE Then
        OpenCom = INVALID_FILE_HANDLE
        Exit Function
    End If
       
    '  setup DCB structure
    ComDCB.BaudRate = BaudRate
    ComDCB.ByteSize = DataBits
    ComDCB.DCBlength = 28
    ComDCB.EofChar = 0
    ComDCB.ErrorChar = 0
    ComDCB.EvtChar = 0
    ComDCB.wReserved = 0
    ComDCB.wReserved1 = 0

    ' set parity
    Select Case Trim(Parity)
        Case "None"
            ComDCB.Parity = NOPARITY
        Case "Even"
            ComDCB.Parity = EVENPARITY
        Case "Odd"
            ComDCB.Parity = ODDPARITY
        Case "Mark"
            ComDCB.Parity = MARKPARITY
        Case Else
            ComDCB.Parity = NOPARITY
    End Select
       
    ' set stop bits string
    Select Case Trim(StopBits)
        Case "1"
           ComDCB.StopBits = ONESTOPBIT
        Case "1.5"
           ComDCB.StopBits = ONE5STOPBITS
        Case "2"
           ComDCB.StopBits = TWOSTOPBIT
        Case Else
           ComDCB.StopBits = ONESTOPBIT
    End Select
       
    ' set flow control
    Select Case Trim(FlowControl)
        Case "Xon Flow"
            ComDCB.fBitFields = FBIT_XONFLOW
            ComDCB.XoffChar = &H13
            ComDCB.XoffLim = 512
            ComDCB.XonChar = &H11
            ComDCB.XonLim = 2048
        Case "HW Flow"
            ComDCB.fBitFields = FBIT_HWFLOW
            ComDCB.XoffChar = 0
            ComDCB.XoffLim = 0
            ComDCB.XonChar = 0
            ComDCB.XonLim = 0
        Case "No Flow"
            ComDCB.fBitFields = FBIT_NOFLOW
            ComDCB.XoffChar = 0
            ComDCB.XoffLim = 0
            ComDCB.XonChar = 0
            ComDCB.XonLim = 0
        Case Else
            ComDCB.fBitFields = FBIT_NOFLOW
    End Select
   
    '  set up com port with DCB parms
    Call SetCommState(ComPortHandle, ComDCB)
    Call SetupComm(ComPortHandle, INPUT_BUFFER_SIZE, OUTPUT_BUFFER_SIZE)
   
    '  return file handle
    OpenCom = ComPortHandle
   
End Function
0

Featured Post

Use Case: Protecting a Hybrid Cloud Infrastructure

Microsoft Azure is rapidly becoming the norm in dynamic IT environments. This document describes the challenges that organizations face when protecting data in a hybrid cloud IT environment and presents a use case to demonstrate how Acronis Backup protects all data.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Overview: This article:       (a) explains one principle method to cross-reference invoice items in Quickbooks®       (b) explores the reasons one might need to cross-reference invoice items       (c) provides a sample process for creating a M…
Phishing attempts can come in all forms, shapes and sizes. No matter how familiar you think you are with them, always remember to take extra precaution when opening an email with attachments or links.
In Microsoft Access, learn different ways of passing a string value within a string argument. Also learn what a “Type Mis-match” error is about.
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question