Jump to content
therealhanuta

CommAPI - Serial and parallel communication with Windows API

Recommended Posts

3. Pls share your func: "I had to write  a  function to replace  _CommGetLine($sEndChar = @CR, $maxlen = 0, $maxtime = 0) found in CommMG.au3. I'll post it if requested."

Below is promised code. Append this function to CommInterface.au3:

 

Hello Marcsf73,

I have added a similar function, now.

An example you can find here: http://www.autoitscript.com/wiki/CommAPI_Examples#Separator

1. You are right. I have an old comminterface from 10/2013. Newer is fom 3/2014

The information what is newer and what is older should be a little more commucative organized.

 

Hello adom,

here you can find the changelog: http://www.autoitscript.com/wiki/CommAPI#Changelog

Share this post


Link to post
Share on other sites
CommAPI Examples
 

Hi TheRealHanuta, concerning Sample Script "Slow Devices" I have following Question:

Do I have to use _CommAPI_ChangeCommTimeoutsElement($hFile, "ReadTotalTimeoutMultiplier", 100)

before every call of _CommAPI_ReceiveData

or

is it necessary only once while initializing ComPort?

THX


Thanks! :bye:

Greetings

Andrew

 

Share this post


Link to post
Share on other sites

Do I have to use _CommAPI_ChangeCommTimeoutsElement($hFile, "ReadTotalTimeoutMultiplier", 100)

before every call of _CommAPI_ReceiveData

or

is it necessary only once while initializing ComPort?

 

Hi adom,

it is necessary only once.

Share this post


Link to post
Share on other sites

Hi TheRealHanuta,

Any direction or example for the use of _CommAPI_WaitCommEvent? Whatever I do on the opened port, that function returns 0.

I'm using it in the GUIGetMsg loop to call the concerned func when a character is pending on COM1.

Thanks,

Thoms

OS:WIN_7/Service Pack 1  CPU:X64 OS:X64

AutoIt3 V 3.3.10.2

Share this post


Link to post
Share on other sites

Hi,

Another question: I'm trying to connect on COM10. No way. Even no way to connect on ports higher than COM9.

The _WinAPI_GetLastErrorMessage reports "Bad parameter".

Any clue?

Thx

Thoms

Share this post


Link to post
Share on other sites

Hi,

Another question: I'm trying to connect on COM10. No way. Even no way to connect on ports higher than COM9.

The _WinAPI_GetLastErrorMessage reports "Bad parameter".

Any clue?

Thx

Thoms

 

Try to initialize these comports you want with a simulation: http://www.232analyzer.com/232default.htm.

To find out if they are already occupied.


Thanks! :bye:

Greetings

Andrew

 

Share this post


Link to post
Share on other sites

Hi adom,

I guess these comports are free : I'm using com0com to make 2 bridges (COM9<->COM10 and COM11<->COM12) and Realterm on each side (COM10 and COM12). I'm in the middle conditioning  data from COM9 to COM11 and vice-versa.

RealTerm can connect on any virtual comport, ie. COM10 or whatever, but NOT on busy ports.

Given that the first com0com bridge is between COM9 and COM10, I've to connect to COM9. If I try the other direction : RealTerm on COM9 and me on COM10, I get the error message. About the other side: COM11 or COM12, I'm really expecting something that works.

Is there something else I can check?

Thx

Thoms

Share this post


Link to post
Share on other sites

Hi adom,

I guess these comports are free : I'm using com0com to make 2 bridges (COM9<->COM10 and COM11<->COM12) and Realterm on each side (COM10 and COM12). I'm in the middle conditioning  data from COM9 to COM11 and vice-versa.

RealTerm can connect on any virtual comport, ie. COM10 or whatever, but NOT on busy ports.

Given that the first com0com bridge is between COM9 and COM10, I've to connect to COM9. If I try the other direction : RealTerm on COM9 and me on COM10, I get the error message. About the other side: COM11 or COM12, I'm really expecting something that works.

Is there something else I can check?

Thx

Thoms

Next ideas:

1. Check if you have the newest Inludes from http://www.autoitscript.com/w/index.php?title=CommAPI&oldid=12340 #Scripts

2. Use GetCOMPorts Func to see it what commAPI will find comports

3. If you want pls explain what you mean by Bridge? What does it exactly?

I am new with comAPI and doing currently my first comm APP. So feel free to ask the community if my ideas are not helpful.


Thanks! :bye:

Greetings

Andrew

 

Share this post


Link to post
Share on other sites

Any direction or example for the use of _CommAPI_WaitCommEvent? Whatever I do on the opened port, that function returns 0.

I'm using it in the GUIGetMsg loop to call the concerned func when a character is pending on COM1.

 

Hi thoms,

I fixed @error handling, but I can't help you to create an example, because I have never used this function.

Maybe this can help you to create an examples for us: http://www.codeproject.com/Articles/2682/Serial-Communication-in-Windows (Search for WaitCommEvent)

Share this post


Link to post
Share on other sites

Another question: I'm trying to connect on COM10. No way. Even no way to connect on ports higher than COM9.

The _WinAPI_GetLastErrorMessage reports "Bad parameter".

 

Hi thoms,

I can't find any error. For me COM10 is working fine.

Are you using function _CommAPI_OpenPort or _CommAPI_OpenCOMPort?

Func _CommAPI_OpenPort(Const $sMode)
    Local $sFileName = "\\.\" & StringLeft($sMode, StringInStr($sMode, ":") - 1)
    Local $hFile = _WinAPI_CreateFile($sFileName, 3, 6)

Line 103 is responsible for COM ports greater than 9.

Share this post


Link to post
Share on other sites

Next ideas:

1. Check if you have the newest Inludes from http://www.autoitscript.com/w/index.php?title=CommAPI&oldid=12340 #Scripts

2. Use GetCOMPorts Func to see it what commAPI will find comports

3. If you want pls explain what you mean by Bridge? What does it exactly?

I am new with comAPI and doing currently my first comm APP. So feel free to ask the community if my ideas are not helpful.

Adom,

1. I'm using the later includes dated 03/27/14 downloaded 03/29/14 :thumbsup:

2. I'm using GetCOMPort to fill  a combobox when my program launches. Regarding that GetCOMPort, maybe a WinAPI, GetDefaultCommConfig would give another result. Don't know, need to try but i'm kind of lazy ;)

3. I say bridge, which it is between 2 virtual COM ports; in other words, it's a virtual null modem. This allow my program to communicate with 2 devices that actually are 2 terminals (Hyperterm, Realterm, putty, ...). As I know the langage of the 1st device, I can enter it on the 1s terminal, translate it and send it to the 2nd terminal in the correct langage. Easy, no? :sweating:

Thoms

Share this post


Link to post
Share on other sites

Hi thoms,

I fixed @error handling, but I can't help you to create an example, because I have never used this function.

Maybe this can help you to create an examples for us: http://www.codeproject.com/Articles/2682/Serial-Communication-in-Windows (Search for WaitCommEvent)

 

Hi TheRealHanuta,

I still didn't try this one again. I'm only checking if a character was received. As the include allows not to check for only one char, it's a lot more easier. Thx.

But as soon as I can, i'll try it and give some example.

Hi thoms,

I can't find any error. For me COM10 is working fine.

Are you using function _CommAPI_OpenPort or _CommAPI_OpenCOMPort?

Func _CommAPI_OpenPort(Const $sMode)
    Local $sFileName = "\\.\" & StringLeft($sMode, StringInStr($sMode, ":") - 1)
    Local $hFile = _WinAPI_CreateFile($sFileName, 3, 6)

Line 103 is responsible for COM ports greater than 9.

 

I just tried both of them, same result : @error = -1, _WinAPI_GetLastErrorMessage() = Bad parameter.

Maybe that line, but I'm not specialist and don't know how to access that adress .COM and what is there.

Thx

Thoms

Share this post


Link to post
Share on other sites

Hi TheRealHanuta,

I still didn't try this one again. I'm only checking if a character was received. As the include allows not to check for only one char, it's a lot more easier. Thx.

But as soon as I can, i'll try it and give some example.

 

I just tried both of them, same result : @error = -1, _WinAPI_GetLastErrorMessage() = Bad parameter.

Maybe that line, but I'm not specialist and don't know how to access that adress .COM and what is there.

Thx

Thoms

 

TheRealHanuta,

Guess what! I changed a physical USB COM2 Port to COM20. It works! So, it's probably an issue with virtual ports  :think:   . I forgott to ask if virtual or physical Port when you said it was working with your COM10 :oops: .

I'll try to bypass that with the physical COM1 (on dock station) already bridged (say connected thru crossover cable) with (now) COM20 on USB :idea: .

Anyway, I follow that topic to see if someone finds another solution concerning (maybe) virtual ports.

Thanks a lot!

Share this post


Link to post
Share on other sites

Hi,

Another issue: when receiving data, ie. Chr(0), Chr(1) ... Chr(255) (0x00 to 0xFF), the first half is correct. But, after Chr(127)(0x7F), I receive only Chr(63)(0x3F) and the same character till Chr(255).

I watched the COM with PortMon (SysInternal) so I'm sure the correct data was transmitted.

In the other direction, sending Chr(0) to Chr(255), it's normal.

Any idea? Do I do something wrong? :(

Thx,

Thoms

Share this post


Link to post
Share on other sites

Another issue: when receiving data, ie. Chr(0), Chr(1) ... Chr(255) (0x00 to 0xFF), the first half is correct. But, after Chr(127)(0x7F), I receive only Chr(63)(0x3F) and the same character till Chr(255).

I watched the COM with PortMon (SysInternal) so I'm sure the correct data was transmitted.

In the other direction, sending Chr(0) to Chr(255), it's normal.

 

Hi thoms,

please try again with current CommInterface.au3

I have fixed some errors, now.

Share this post


Link to post
Share on other sites

Hi theReal.

Thanks for your quick reply and update. But still some data are not going thru. Weird!

Please take a look at the attached file. This is what I receive when sending Chr(0) to Chr(255).

Thx

Thoms

Received.txt

Share this post


Link to post
Share on other sites

Hi,

Yes, I (we) got it! :dance:

What I really wanted was only to get BYTES, not char or else. So the best way was to declare a byte structure and to initialize the returned value as number. $sResult should change to $(?)Result, I don't know the prefix for byte. Of course, the calling function as to know that it will receive a byte (or byte array) instead of a string.

That way can be very useful when you want to receive one byte or char. In case you want several of them, you have to create and return a Byte array. I'll try to write an example, but not now. I need to sleep sometimes.

Here is your modified Func:

Func _CommAPI_ReadOneByte(Const $hFile, Const $iTimeout = 1)
    Local $tBuffer = DllStructCreate("byte")
    Local $hTimer = TimerInit()
    Local $iWritten = 0
    Local $sResult = 0
    While 1
        _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer), 1, $iWritten)
        If @error Then Return SetError(@error, @ScriptLineNumber, $sResult)
        If $iWritten Then
            $sResult = DllStructGetData($tBuffer, 1)
            ConsoleWrite("tb=" & hex(DllStructGetData($tBuffer, 1),4) & " sR=" & $sResult & " " & Binary($sResult) & " ")
            Return $sResult
        Else
            If $iTimeout >= 0 And $iTimeout < TimerDiff($hTimer) Then Return SetError(-2, @ScriptLineNumber, $sResult)
        EndIf
    WEnd
    Return $sResult
EndFunc   ;==>_CommAPI_ReadOneByte

So, for my immediate need, this problem is solved. But I'll try to go further with CommAPI, as I'm very often using one or more RS232 ports ; each of them having his own protocol, byte, char, wchar... Nice!

And i'm going to seek deeply in the FileCreate to understand why some softwares can see some ports, and other softwares can see other ports.

Thx for that UDF,

Thoms

Edit: oops! Iforgot to remove the consolewrite line that was only for debug.

Edited by thoms

Share this post


Link to post
Share on other sites

What I really wanted was only to get BYTES, not char or else. So the best way was to declare a byte structure and to initialize the returned value as number. $sResult should change to $(?)Result, I don't know the prefix for byte. Of course, the calling function as to know that it will receive a byte (or byte array) instead of a string.

That way can be very useful when you want to receive one byte or char. In case you want several of them, you have to create and return a Byte array. I'll try to write an example, but not now. I need to sleep sometimes.

Hi thoms,

thanks for your solution. I have taken your approach and have made some changes.

I have replaced ReceiveData & ReceiveLine with ReceiveBinary & ReceiveString.

To read only one byte: _CommAPI_ReceiveByte($hFile, 1, 1)

To read a line: _CommAPI_ReceiveString($hFile, 1, 0, @CRLF)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By cheeroke
      Hi all,
      I got this code and would like to be able to change Baud Rate and instead of sending character by character i would like to be able (if possible) to send whole string. But i don't know how to change it.
      I am taking input from file and processing whole line (this is done in FilesHandling.au3).
      To execute this i am just calling SendData("FileName", int) in "main" script.
      Any help very appreciated.
      #include <WinAPI.au3> #include <Array.au3> #include "FilesHandling.au3" ;init DLL function, we need handle to call the function $h = DllCall("Kernel32.dll", "hwnd", "CreateFile", "str", "\\.\COM19", "int", BitOR($GENERIC_READ,$GENERIC_WRITE), "int", 0, "ptr", 0, "int", $OPEN_EXISTING, "int", $FILE_ATTRIBUTE_NORMAL, "int", 0) $handle=$h[0] Func SendData($FileName, $LineNumber) ;string to be send $c = readFile($FileName, $LineNumber) $cLenght = StringLen($c) $aArray = StringSplit($c, "") ;_ArrayDisplay($aArray, "", Default, 64) For $i = 1 To $cLenght writeChar($handle, $aArray[$i], $cLenght) Next ;move to next line writeChar($handle, @CR,1) EndFunc ;write a single char func writeChar($handle,$c,) $stString = DLLStructCreate("char str") $lpNumberOfBytesWritten = 0 DllStructSetData($stString, 1, $c) $res = _WinAPI_WriteFile($handle, DllStructGetPtr($stString, "str"), 1,$lpNumberOfBytesWritten) if ($res<>true) then ConsoleWrite ( _WinAPI_GetLastErrorMessage() & @LF) EndIf EndFunc  
    • By MazeM
      Hi
      here's another UDF for the serial port. It is very similar to CommAPI using kernel32.dll, but all code is packed into a single file without any dependencies, not even using WinAPI.au3. It differs from existing UDF that it doesn't allow a timeout when reading, instead it always returns immediately, either with the requested amount ob bytes read or with a failure status. And of course there is a function provided to query the amount of available bytes in the receive buffer. The reason behind this design decision: You can do 1000 other things in the main loop while checking from time to time if enough data bytes arrived. There's no point to block the program waiting for the serial port.
      It is currently a work-in-progress, as I didn't test all functions yet. The code was developed and tested on Windows 7 64 bit.  The ComUDF-Tests.au3 shows some tests and basic usage of the UDF. Maybe there's no reason to use this UDF, given the existence of the others UDFs, but I did it to get to know DllCall better - I use structs no only to pass but also to get data back (I don't use the array returned by DllCall to read that data, unless required). You're welcome to test it on older and newer Windows versions.
      Here's a list of the implemented functions:
      ; _ComListPorts ; _ComOpenPort ; _ComSetTimeouts ; _ComClosePort ; ; _ComSetBreak ; _ComClearBreak ; _ComGetInputcount ; _ComGetOutputcount ; _ComClearOutputBuffer ; _ComClearInputBuffer ; ; _ComSendByte ; _ComReadByte ; _ComSendBinary ; _ComReadBinary ; ; _ComSendChar ; _ComReadChar ; _ComSendCharArray ; _ComReadCharArray ; _ComSendString ; _ComReadString ; ; __ComClearCommError ; __PurgeComm Maze
       
      ComUDF.au3
      ComUDF-Tests.au3
    • By OldNoob
      I'm attempting to call the winapi function EnumSystemFirmwareTables using DllCall "Kernel32.dll" without success. I am a total noob when it comes to this and could use some direction. Based on the documentation "Dealing with Dlls in AutoIt" by Andreas Karlsson, I have tried using the following code to obtain the buffersize of the Firmware Table Buffer.
      Thanks in advance for any help
      #include <WinAPI.au3> MsgBox(0, "ESFT BufferSize", "BufferSize = " & _EnumSystemFirmwareTables()) Func _EnumSystemFirmwareTables() $aRet = DllCall ("Kernel32.dll", "UINT", "EnumSystemFirmwareTables", "DWORD", "ACPI", "PVOID" ,Null , "DWORD" ,Null) if @error Then MsgBox (0,"Error","An error ocurred with the DLLCALL, error returned = " & @error &@CRLF & "GetLastError = " & _WinAPI_GetLastError ( ),0) Exit else Return $aRet endif EndFunc  
×
×
  • Create New...