Results 1 to 20 of 20

Thread: Accessing Com17 and up.

  1. #1

    Thread Starter
    New Member
    Join Date
    Jul 2001
    Location
    United Kingdom
    Posts
    13

    Post Accessing Com17 and up.

    Hi there,

    I need to be able to access com ports higher than the limitation of the MSComm control, which is 16.

    I need the software to run on Windows NT 4.0 or later.

    Any code which could help me achieve this would be appreciated.

  2. #2
    PowerPoster Chris's Avatar
    Join Date
    Jan 1999
    Location
    K-PAX
    Posts
    3,238
    use CreateFile API function call...

    PHP Code:
    /* A sample program to illustrate setting up a serial port. */

    #include <windows.h>

    int
    main
    (int argcchar *argv[])
    {
      
    DCB dcb;
      
    HANDLE hCom;
      
    BOOL fSuccess;
      
    char *pcCommPort "COM17";

      
    hCom CreateFilepcCommPort,
                         
    GENERIC_READ GENERIC_WRITE,
                         
    0,    // comm devices must be opened w/exclusive-access
                         
    NULL// no security attributes
                         
    OPEN_EXISTING// comm devices must use OPEN_EXISTING
                         
    0,    // not overlapped I/O
                         
    NULL  // hTemplate must be NULL for comm devices
                         
    );

      if (
    hCom == INVALID_HANDLE_VALUE) {
          
    // Handle the error.
          
    printf ("CreateFile failed with error %d.\n"GetLastError());
          return (
    1);
        }

      
    // We will build on the current configuration, and skip setting the size
      // of the input and output buffers with SetupComm.

      
    fSuccess GetCommState(hCom, &dcb);

      if (!
    fSuccess) {
          
    // Handle the error.
          
    printf ("GetCommState failed with error %d.\n"GetLastError());
          return (
    2);
        }

      
    // Fill in the DCB: baud=57,600 bps, 8 data bits, no parity, and 1 stop bit.

      
    dcb.BaudRate CBR_57600;     // set the baud rate
      
    dcb.ByteSize 8;             // data size, xmit, and rcv
      
    dcb.Parity NOPARITY;        // no parity bit
      
    dcb.StopBits ONESTOPBIT;    // one stop bit

      
    fSuccess SetCommState(hCom, &dcb);

      if (!
    fSuccess) {
          
    // Handle the error.
          
    printf ("SetCommState failed with error %d.\n"GetLastError());
          return (
    3);
        }

      
    printf ("Serial port %s successfully reconfigured.\n"pcCommPort);
      return (
    0);

    Full sample code from MSDN...

    [PHP]

  3. #3

    Thread Starter
    New Member
    Join Date
    Jul 2001
    Location
    United Kingdom
    Posts
    13
    Thanx for the reply, I was hoping for something in VB. I have been trying to port this, but my C++ skills are near non-existant.

    I did go to your website and saw that you have an example using the CreateFile API, but am not having luck with comm ports.

    I basically need to be able to open the com port (all the way to Com32) and then send a strings and close again.

    Thanx again for your help.

    Craig

  4. #4
    PowerPoster Chris's Avatar
    Join Date
    Jan 1999
    Location
    K-PAX
    Posts
    3,238
    CraigRK, here is the code for openning a Comm Port as well as sending data out from this comm port with pure API without any MSComm32.OCX control.

    As for the receiving part, I let you figure it out. If can't get it, juz let me knoe

    Good Luck

    VB Code:
    1. Option Explicit
    2. '// WIN32API Function
    3. Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
    4. Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long
    5. Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    6. Private Declare Function SetCommState Lib "kernel32" (ByVal hCommDev As Long, lpDCB As DCB) As Long
    7. Private Declare Function GetCommState Lib "kernel32" (ByVal nCid As Long, lpDCB As DCB) As Long
    8.  
    9. '// WIN32API Structure
    10. Private Type DCB
    11.         DCBlength As Long
    12.         BaudRate As Long
    13.         fBitFields As Long 'See Comments in Win32API.Txt
    14.         wReserved As Integer
    15.         XonLim As Integer
    16.         XoffLim As Integer
    17.         ByteSize As Byte
    18.         Parity As Byte
    19.         StopBits As Byte
    20.         XonChar As Byte
    21.         XoffChar As Byte
    22.         ErrorChar As Byte
    23.         EofChar As Byte
    24.         EvtChar As Byte
    25.         wReserved1 As Integer 'Reserved; Do Not Use
    26. End Type
    27.  
    28. '// WIN32API Constant
    29. Private Const GENERIC_READ = &H80000000
    30. Private Const GENERIC_WRITE = &H40000000
    31. Private Const OPEN_EXISTING = 3
    32. Private Const FILE_FLAG_OVERLAPPED = &H40000000
    33. Private Const INVALID_HANDLE_VALUE = -1
    34. Private Const NOPARITY = 0
    35. Private Const ONESTOPBIT = 0
    36.  
    37. '// Comm Port Handle
    38. Private hComm As Long
    39.  
    40. Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    41.     '// Close the opened Comm
    42.     If hComm <> 0 Then CloseHandle (hComm)
    43. End Sub
    44.  
    45. Private Sub CmdAction_Click(Index As Integer)
    46.     Dim Idx As Integer
    47.     Select Case Index
    48.     Case 0 '// Open/Close
    49.         If CmdAction(0).Caption = "&Open" Then
    50.             If OpenPort(txtCOMM(0).Text, CLng(txtCOMM(1).Text), CLng(txtCOMM(2).Text)) <> 0 Then
    51.                 CmdAction(0).Caption = "&Cancel"
    52.                 For Idx = 0 To 2: txtCOMM(Idx).Enabled = False: Next
    53.                 txtData.Enabled = True
    54.                 CmdAction(1).Enabled = True
    55.                 lblStatus.Caption = "Open Port Successful: Hanlde -> " & hComm
    56.             Else
    57.                 lblStatus.Caption = "Fail to open port!!!"
    58.             End If
    59.         Else
    60.             CloseHandle (hComm)
    61.             CmdAction(0).Caption = "&Open"
    62.             For Idx = 0 To 2: txtCOMM(Idx).Enabled = True: Next
    63.             txtData.Enabled = False
    64.             CmdAction(1).Enabled = False
    65.             lblStatus.Caption = "Port Closed"
    66.         End If
    67.     Case 1 '// Send
    68.         Write2Port txtData.Text
    69.     End Select
    70.  
    71. End Sub
    72.  
    73. Private Function OpenPort(ByVal strPort As String, ByVal lngBaudRate As String, ByVal lngDataBit As Long) As Long
    74.     Dim pDCB As DCB
    75.     Dim lpPort As String
    76.    
    77.     '// Create Comm Name Buffer
    78.     lpPort = String(6, Chr(0))
    79.     Mid$(lpPort, 1, 6) = "COM" & strPort & ":"
    80.    
    81.     '// Close the current opened Comm Port (If any)
    82.     If hComm > 0 Then CloseHandle (hComm)
    83.    
    84.     '// Open selected comm port
    85.     hComm = CreateFile(lpPort, _
    86.                         GENERIC_READ Or GENERIC_WRITE, _
    87.                         0, _
    88.                         vbNull, _
    89.                         OPEN_EXISTING, _
    90.                         0, _
    91.                         vbNull)
    92.  
    93.    
    94.     If hComm <> INVALID_HANDLE_VALUE Then
    95.         pDCB.DCBlength = Len(pDCB)
    96.        
    97.         '// Retrieve default Comm port settings
    98.         GetCommState hComm, pDCB
    99.        
    100.         '// Configure new Comm port settings
    101.         With pDCB
    102.             .BaudRate = lngBaudRate
    103.             .Parity = NOPARITY
    104.             .ByteSize = lngDataBit
    105.             .StopBits = ONESTOPBIT
    106.             .EofChar = 0
    107.             .ErrorChar = 0
    108.             .EvtChar = 0
    109.             .fBitFields = 20625
    110.             .XoffChar = 19
    111.             .XoffLim = 512
    112.             .XonChar = 17
    113.             .XonLim = 2048
    114.         End With
    115.        
    116.         '// Set new configure Comm port settings
    117.         If SetCommState(hComm, pDCB) = 0 Then
    118.             CloseHandle (hComm)
    119.             OpenPort = 0
    120.  
    121.             MsgBox "Fail to configure serial port!", vbExclamation + vbOKOnly, "Error"
    122.         Else
    123.             OpenPort = hComm
    124.         End If
    125.     Else
    126.         CloseHandle (hComm)
    127.         OpenPort = 0
    128.     End If
    129. End Function
    130.  
    131. Private Sub Write2Port(ByVal strData As String)
    132.     Dim dwByteWrite As Long
    133.     Dim Sz As Long, Idx As Long
    134.     Dim Bytes() As Byte
    135.    
    136.     '// Create & Convert str into array of Byte
    137.     Sz = Len(strData)
    138.     ReDim Bytes(Sz) As Byte
    139.     For Idx = 1 To Sz
    140.         Bytes(Idx - 1) = Asc(Mid$(strData, Idx, 1))
    141.     Next
    142.    
    143.     '// Write data into Open Comm Port
    144.     If hComm <> INVALID_HANDLE_VALUE Then
    145.         WriteFile hComm, _
    146.                     Bytes(0), _
    147.                     UBound(Bytes), _
    148.                     dwByteWrite, _
    149.                     ByVal 0&
    150.     Else
    151.         MsgBox "Invalid port handle", vbExclamation + vbOKOnly, "Error"
    152.     End If
    153.    
    154.     Erase Bytes
    155.    
    156. End Sub
    Last edited by Chris; Jul 30th, 2001 at 12:28 PM.

  5. #5
    PowerPoster Chris's Avatar
    Join Date
    Jan 1999
    Location
    K-PAX
    Posts
    3,238
    Fotget to upload the sample project file :P

  6. #6
    Addicted Member
    Join Date
    Jul 2001
    Posts
    133
    CraigRK,

    Your lucky to have Chris helping you, he is steering you done the correct path to enpower you to take control of serial communications the best you can through Windows.

    Be aware that there are many errors in his code and to understand the basics of what he is trying to show you - using the API. Like I said, you are lucky to have him putting so much effort into helping you, but help yourself also be understanding what it is your code is doing.

    I am exceedingling carefull when I write my code cause when I go and do research to determine how to do something I run across so much questionable code - even if they are errors on behalf of the author you still end up doing lots of work do determine if there is a good reason he did so.

    * For example, in OpenPort:

    ...
    lpPort = String(6, Chr(0))
    Mid$(lpPort, 1, 6) = "COM" & strPort & ":"
    ...
    hComm = CreateFile(lpPort, _
    GENERIC_READ Or GENERIC_WRITE, _
    0, _
    vbNull, _
    OPEN_EXISTING, _
    0, _
    vbNull)

    There is much pontential grief here. For one thing, if the port is >9 then there will be no chr(0) at the end of the string that you are passing to the API call. Remember that all strings passed to the API must end in a chr(0). It may work some of the time, but be warned.

    * For example, in Write2Port:

    ...
    Sz = Len(strData)
    ReDim Bytes(Sz) As Byte
    For Idx = 1 To Sz
    Bytes(Idx - 1) = Asc(Mid$(strData, Idx, 1))
    Next
    ...
    WriteFile hComm, _
    Bytes(0), _
    UBound(Bytes), _
    dwByteWrite, _
    ByVal 0&

    This will result in an extra byte being transmitted.

    *

    I also have reservation with the use of vbNull in the call to CreateFile. vbNull is used to represent a Variant-Type variable that contains no valid data. IT IS NOT the same as "null" as discussed regarding API calls.

  7. #7
    PowerPoster Chris's Avatar
    Join Date
    Jan 1999
    Location
    K-PAX
    Posts
    3,238
    First of all, thanks Jay Rogozinsky to correct my code
    I agree on the point 1 and 3 as...

    Pt.1, yes, there will be fail to open any port that creater than 9. "coz the lpFilename will lossing the string terminator character (NULL) in window env. So be aware of this

    Pt.3, yes, in VB, vbNull = 1 and not 0 So do correct it

    As for pt.2, I did retest it again and the result was as the attached 2 image file. The first one is declare a Bytes array with size 5 and have a string terminator (NULL). Whereas the second image was declare a Bytes array with size of 4 and without any space for the string terminator.

    After sent the data, the dwByteWrite return 4 and 3 in both scenario. And we can see that in case 2 will lost the last character, but not the first scenario.

    If Im wrong do correct too, 'coz we're in the learning curve





    regards,

  8. #8
    Addicted Member
    Join Date
    Jul 2001
    Posts
    133

    Wink

    Be apprised that the improper use of vbNull is in many places in the code. If you find it difficult to pass what you need to API calls you will find that Microsoft's DECLARES (Win32API.Txt) are both inappropriate and just plain wrong in some cases (I end up altering quite a few DECLARES for the API calls).

    Yes, I did read that code a bit hastily - it only took a few seconds of reading the article for things to pop out at me. (Also note that I did not read much of it.) It WILL NOT transmit an extra character, as I said in point 2. Specific to the cause of my hasty interpretation - I think the following code would be smaller, execute quicker, be more self-evident, and easier to troubleshoot:

    Sz = Len(strData)
    ReDim Bytes(1 to Sz) As Byte
    For Idx = 1 To Sz
    Bytes(Idx) = Asc(Mid(strData, Idx, 1))
    Next
    ...
    WriteFile hComm, _
    Bytes(1), _
    UBound(Bytes), _
    dwByteWrite, _
    ByVal 0&

    Also, I'm curious about copying the data to a byte array - why not use RtlMoveMemory instead of the Loop? Better yet, why not send the string directly, no byte array required? If the program (and indeed the system it's running on) requires efficiency (it sends lots of data), the loop will slow it down.

  9. #9
    PowerPoster Chris's Avatar
    Join Date
    Jan 1999
    Location
    K-PAX
    Posts
    3,238
    Thx for your correction

  10. #10

    Thread Starter
    New Member
    Join Date
    Jul 2001
    Location
    United Kingdom
    Posts
    13
    Chris & Jay,

    Thanx for all the effort you have put into answering this question.

    I will spend some time trying to ensure that I understand the code, rather than simply using it to achieve my own requirements.

    The reason I left the question quite broad at the beginning was exactly for this reason. I appreciate assistance which will help me to learn and improve my own skills, rather than asking someone else to provide a full working end product that will meet my needs.

    I have quite a bit o coding to do to get my program doing what I want, but at least I now have the start that I needed.

    I'll be sure to let you guys know if I come up with any issues that I can't figure out.

    Cheerio for now,

    Craig

  11. #11

    Thread Starter
    New Member
    Join Date
    Jul 2001
    Location
    United Kingdom
    Posts
    13
    Chris, Jay (anybody?)

    I got swamped with some other work, and didn't get back to this until today.

    With making only the changes recommended in this thread, I tested this software and it worked fine (with com1!! - I am using a notebook for development with only 1 com port).

    I then compiled the test app and sent it to the end user to test on com17 before spending more time on the project. It would even open com1.

    I then re-extracted your (Chris) original zip file that you uploaded, and when I run the exe that you included, it doesn't work either.

    Could anyone tell me why this code works in the design environment & NOT when compiled. Please

    Thanx,

    Craig

  12. #12
    Addicted Member
    Join Date
    Jul 2001
    Posts
    133
    You said that you applied my suggestions. I'm curious, I explained that vbNull was being used improperly yet I did not suggest how to solve for the vbNull use - how did you do that? (Do you understand?)

    Like I said earlier, It is very important to understand the DECLARES . . .

    ------------
    Change This:
    ------------

    Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long

    --------
    To This:
    --------

    Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long

    If you want to understand DECLARES better (how VB uses them), just ask :-)

    -----------------------------------------------
    Add this with the rest of the Const's (at top):
    -----------------------------------------------

    Private Const FILE_FLAG_NO_BUFFERING = &H20000000

    ------------
    Change This:
    ------------

    lpPort = String(6, Chr(0))
    Mid$(lpPort, 1, 6) = "COM" & strPort & ":"

    --------
    To This:
    --------

    lpPort = "\\.\COM" + strPort + vbNullChar

    ------------
    Change This:
    ------------

    hComm = CreateFile(lpPort, _
    GENERIC_READ Or GENERIC_WRITE, _
    0, _
    vbNull, _
    OPEN_EXISTING, _
    0, _
    vbNull)

    --------
    To This:
    --------

    hComm = CreateFile(lpPort, _
    GENERIC_READ Or GENERIC_WRITE, _
    0, _
    ByVal 0, _
    OPEN_EXISTING, _
    FILE_FLAG_NO_BUFFERING, _
    0)

    Assuming you addressed the other suggestions I made, the code MAY now work for you. Again, be apprised that I did NOT read through all the code (which is not mine) ... I am simply responding to issues as they arrise.

    :-)

  13. #13
    PowerPoster Chris's Avatar
    Join Date
    Jan 1999
    Location
    K-PAX
    Posts
    3,238
    CraigRK, you can change those sectin mention by Jay Rogozinsky.

    but I've a curious on the lpfilename. As according to the MSDN it should be something "COMx:", where x is the port number. Why need to add "\\.\" in front of the COM

    Also, as my posted image, I've no problem in openning the COM4 and I did try out COM3 as well

    regards,

  14. #14
    Addicted Member
    Join Date
    Jul 2001
    Posts
    133

    Talking

    The use of the "\\.\" relates to named piping.

    See Microsoft's KB Article ID: Q115831 ...

    ----------

    CreateFile() can be used to get a handle to a serial port. The "Win32 Programmer's Reference" entry for "CreateFile()" mentions that the share mode must be 0, the create parameter must be OPEN_EXISTING, and the template must be NULL.

    CreateFile() is successful when you use "COM1" through "COM9" for the name of the file; however, the message INVALID_HANDLE_VALUE is returned if you use "COM10" or greater.

    If the name of the port is \\.\COM10, the correct way to specify the serial port in a call to CreateFile() is as follows:
    ...

    ----------

    I have tested with and without this convention. However, it has always worked with. And since the KB points out a time when it MUST be used, it would seem to be wise to do so.

    I thought this would be a good item for your attention since it relates directly to the usage of higher COM ports.

  15. #15
    PowerPoster Chris's Avatar
    Join Date
    Jan 1999
    Location
    K-PAX
    Posts
    3,238
    Thank Jay.

  16. #16

    Thread Starter
    New Member
    Join Date
    Jul 2001
    Location
    United Kingdom
    Posts
    13
    Jay,

    Thanx for all that. I have tested the application with com17+ and it now seems to work. I will now spend some time trying to complete the application as I need it.

    As to your suggestion about Nulls. I remember reading about it, then procedded to implement the other changes you mentioned and forgot about the Nulls

    When the compiled software didn't work, and I tried Chris original compiled exe (which didn't work on my machine), I stopped looking, realising that it was something that I either didn't know about or hadn't been picked up.

    You are a great help, and I can see that your approach makes sense. Force the guys to think!!.

    I would appreciate it if you would give me some more pointers on exactly how VB deals with Declares. I am a pure VB developer (No C, etc) and this is my 1st real forray into API. I have gone through some of the tutorials that are out there on the web, but find that they tend to gloss over Declares, basically telling you to find the right one, without explaining how to trouble shoot if one is faulty, as you have found. Perhaps we shuld start a new thread for the Declares info?

    Craig

  17. #17
    Addicted Member
    Join Date
    Jul 2001
    Posts
    133
    Yes, it would be a good idea to start a thread on DECLARES. :-)

    Thanks to Chris for starting these events.

  18. #18
    Member
    Join Date
    Mar 2001
    Posts
    56

    Cool Try this VB source code comm control:

    True multithread VB source code control:
    http://www.banasoft.com/DownLoad/BNComm.exe

    Banasoft Communication Control is a multithread communication component written by VB completely. It 's compatible with MSComm control and have many enhanced features.

    A limitation in MSComm is that we can not use the serial port which number less than 16. Many applications may need 32 or more serial ports to exchange data with MCU. BNComm extend this to the WinNT limitation 256. You can use multiserial link hardware like MOXA freely. Also we are planning to implement parellel port communication in this control next time.

  19. #19
    Addicted Member
    Join Date
    Jul 2001
    Posts
    133
    I went to take a look and there does not appear to be a functioning www.banasoft.com.

    Since one of the authors posted that last message, I am curious:

    1) Did you create a VB OCX or a DLL. Which version of VB did you use - VB 6 does not appear to properly use CreateThread - maybe you didn't use this call. You propably did this 'part' through use of an ActiveX Exe.

    2) You say it's multithreaded - in your case your meaning what? - that it is thread safe or that it uses multiple threads. For sure, it would have to use multiple threads to properly wait for receive 'interrupts' from Windows via Ascync IO. Or did you bypass Windows and go directly to the UART?

    I have written assembly code which accesses the UARTS directly - I am an old hand at serial communications.

    To assist you I will tell you my griefs with MSComm control:

    1) it is an OCX - sometimes you don't have a place to 'seat' it.
    2) it does not properly handle lower baud rates (which should actually be referred to as bit rates, by the way).
    3) the limitation you mentioned.

  20. #20
    Member
    Join Date
    Mar 2001
    Posts
    56

    True multithread VB5 VB6 source code controls

    Please goto http://www.banasoft.com/, click the links of the controls to download directly.

    The comunication control and the winsock control are written in VB5 or VB6 using "CreateThread" API, True multithread with no crash!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width