Jump to content

Serial Communication using kernel32.dll


TABALtd
 Share

Recommended Posts

Anyone interested in controlling the serial ports directly via kernel32 functions?

You need the following file "cfx.ini" with the settings of the used comm port

[Comm]
CommPort=1
CommBaud=9600
CommParity=0;0=none, 1=odd, 2=even, 3=mark, 4=space
CommBits=8;4-8
CommStop=1;0=0, 1=1,5, 2=2
CommCtrl=0x0011
LogDir=""
Debug=1

I spent much time to find an alternative to mscomm32 or other udfs using a dll.

The test script sends a reset to a modem and shows the response.

Sending chr(0) is possible, but I have to find a solution to receive chr(0).

With the settings above (CommCtrl) the serial port is able to receive chr(0), the "BytesReceived" value shows that a character was received.

The problem is, that chr(0) marks the end of a string.

Questions: Does it works with Win98 or Vista?

Any comments are welcome.

Uwe

cfxtest0.au3

cfx.au3

Edited by TABALtd
Link to comment
Share on other sites

Anyone interested in controlling the serial ports directly via kernel32 functions?

You need the following file "cfx.ini" with the settings of the used comm port

[Comm]
CommPort=1
CommBaud=9600
CommParity=0;0=none, 1=odd, 2=even, 3=mark, 4=space
CommBits=8;4-8
CommStop=1;0=0, 1=1,5, 2=2
CommCtrl=0x0011
LogDir=""
Debug=1

I spent much time to find an alternative to mscomm32 or other udfs using a dll.

The test script sends a reset to a modem and shows the response.

Sending chr(0) is possible, but I have to find a solution to receive chr(0).

With the settings above (CommCtrl) the serial port is able to receive chr(0), the "BytesReceived" value shows that a character was received.

The problem is, that chr(0) marks the end of a string.

Questions: Does it works with Win98 or Vista?

Any comments are welcome.

Uwe

Looks really good TABALtd, and impressive for as first post!

Doesn't the ReadFile function allow you to read chr(0)? Your _rxwait function is treating the received data as a string and that won't work if you want binary data which includes 0x0. You need to create a byte array struct and send the pointer to that struct fo rthe buffer pointer and read it as binary.

Something like this which I haven't tested

Func _rxwaitB($n,$t)
    if $DEBUG=1 then FileWriteLine("debug.txt","Wait " & $n & " " &$t) 
    $lptr0=dllstructcreate("long_ptr")
    Local $InBuf = dllstructcreate("byte[" & $n & "]")
    Local $pInBuf = DllStructGetPtr($InBuf)
    Local $totalin = 0
    $rc=" "
    
    $rlen=1
    $jetza=TimerInit()

    Do
        if $n - $totalin < $rlen then $rlen = $n - $totalin;in case $rlen increased
        $rxr=dllcall($dll,"int","ReadFile","hwnd",$hSerialPort[0], _
                            "ptr",$pInBuf, _
                            "int",$rlen, _ 
                            "long_ptr", DllStructGetPtr($lptr0) + $totalin, _ 
                            "ptr", 0)
        if @error Then
            errpr()
            Exit
        EndIf
        $totalin += DllStructGetData($lptr0,1)
        ConsoleWrite("R0:" & $rxr[0] & " |R1:" & "0x" & DllStructGetData($InBuf,1,1+$totalin) & " |R2:" & $rxr[2] & " |rxl:" & $totalin & " |R4:" & $rxr[4] & @CRLF)
    
        $to=TimerDiff($jetza)
    Until $totalin>=$n OR $to>$t  
    return dllstructgetdata($InBuf);returns a binbary type

It would be nice if your _opencomm function had parameters rather than use an ini file, or maybe have parameters with an option to use an ini file like this

_opencomm($inifile = "cfg.ini",$baud = 9600, $parity = 0, $stopbits = 1.....)

if $inifile <> "" then read inifile

It looks to me like you haven't got much to do to be able to replace my serial port udf and dll. I look forward to your 2nd post. :)

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Thank you for your comments and suggestions.

I will post a new version as soon as I make the proposed changes.

One more thing: I tried to control an interface converter (RS232 to RS485) with the setting CommCtrl=0x3011.

This sets fRTSControl to Toggle.

The converter transmits when RTS is high and receives when RTS is low.

The problem is, that RTS returns to low before a character (or string) has been sent completely.

I know that this is not a question regarding AutoIt, but maybe somebody around here has a solution.

Uwe

Link to comment
Share on other sites

Sending chr(0) is possible, but I have to find a solution to receive chr(0).

With the settings above (CommCtrl) the serial port is able to receive chr(0), the "BytesReceived" value shows that a character was received.

The problem is, that chr(0) marks the end of a string.

You should create a byte-Array and use this, instead of using Strings :)

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

You should create a byte-Array and use this, instead of using Strings :)

As in post #2?
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

  • 3 weeks later...
  • 3 months later...

Hello,

I get an "Open Error" in the console.

Why?

[list][font="Century Gothic"]If nothing is certain, everything is possible.[/font][/list][font="Century Gothic"]Experience is something you get, just after you need it.[/font]

Link to comment
Share on other sites

It's nice when somebody brings forward a post I have missed and it is an useful one :)

I can see that there were no updates for quite a long time and I hope the author will continue working on it. (hope ...)

Thanks TABALtd for sharing this.

SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Link to comment
Share on other sites

  • 1 month later...

I follow this thread from time to time, and I find this solution for serial communication extremely interesting. I am very impressed by the work this far, and I keep my fingers crossed that this udf will be further developed.

Many thanks for the work done already!

Link to comment
Share on other sites

  • 1 month later...

This solution has nice no-dll advantages over COMMG.

However, I see the following in the .ini file: CommCtrl=0x0011

It seems when this is read in by AutoIt3, the AutoIt3 variable actually read in is '0' if I am debugging correctly.

Anyway, for me this 0x0011 setting works with the sending text commands, but not receiving text from our nice A&D GX-1000 precision balance.

The receiving is correct # characters, but they are not correct.

Should be: ST,+0011.584 g (with a @CRLF at the end)

Actual: [W/+??;?/;7;??wmk

When I used the COMMG.dll I get correct answer for both sending and receiving text from the balance.

CommG settings are: _CommSetPort(4, $sErr, 2400, 7, 2, 1, 0)

(iFlow = 0 = sets hardware flow control)

Finally, my question:

if iFlow=0 with Commg.dll works, what should CommCtrl=??? for TABALtd's method so it too will work when reading text from serial line?

Thank you,

Ben

Anyone interested in controlling the serial ports directly via kernel32 functions?

You need the following file "cfx.ini" with the settings of the used comm port

[Comm]
CommPort=1
CommBaud=9600
CommParity=0;0=none, 1=odd, 2=even, 3=mark, 4=space
CommBits=8;4-8
CommStop=1;0=0, 1=1,5, 2=2
CommCtrl=0x0011
LogDir=""
Debug=1

I spent much time to find an alternative to mscomm32 or other udfs using a dll.

The test script sends a reset to a modem and shows the response.

Sending chr(0) is possible, but I have to find a solution to receive chr(0).

With the settings above (CommCtrl) the serial port is able to receive chr(0), the "BytesReceived" value shows that a character was received.

The problem is, that chr(0) marks the end of a string.

Questions: Does it works with Win98 or Vista?

Any comments are welcome.

Uwe

Link to comment
Share on other sites

This solution has nice no-dll advantages over COMMG.

However, I see the following in the .ini file: CommCtrl=0x0011

It seems when this is read in by AutoIt3, the AutoIt3 variable actually read in is '0' if I am debugging correctly.

Anyway, for me this 0x0011 setting works with the sending text commands, but not receiving text from our nice A&D GX-1000 precision balance.

The receiving is correct # characters, but they are not correct.

Should be: ST,+0011.584 g (with a @CRLF at the end)

Actual: [W/+??;?/;7;??wmk

When I used the COMMG.dll I get correct answer for both sending and receiving text from the balance.

CommG settings are: _CommSetPort(4, $sErr, 2400, 7, 2, 1, 0)

(iFlow = 0 = sets hardware flow control)

Finally, my question:

if iFlow=0 with Commg.dll works, what should CommCtrl=??? for TABALtd's method so it too will work when reading text from serial line?

Thank you,

Ben

I haven't tried but maybe you need to change the code from

$CommCtrl=get_config("CommCtrl")

to

$CommCtrl= Number(get_config("CommCtrl"))
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Thank you. Unfortunately it doesn't work (same result)

I'd also tried creating a _opencomm2($CommCtrl2) and looping through a lot of values for CommCtrl2, but there isn't any difference in the output.

I'd never rule out stupidity on my part, but since the commg dll method does work, I may need to stick with that since the commctrl hex codes seem to be undocumented. But if there are any other ideas, I'm game to try.

Thank you,

Ben

I haven't tried but maybe you need to change the code from

$CommCtrl=get_config("CommCtrl")

to

$CommCtrl= Number(get_config("CommCtrl"))
Link to comment
Share on other sites

I have noticed that the OP hasn't updated the thread for a long time and he's been around here recently.

My guess: we can consider this UDF a "dead one" because there is no further implication from its author. Since it is still not working properly, we better stick with the "old one" (thanks martin) which has active support and it is proven to work.

SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Link to comment
Share on other sites

I started trying to make a UDF out of this. I am just trying to read gps data.

This was my test script to read a line of data from the gps

#include "cfxUDF.au3"
Dim $CommPort = '4', $CommBaud = '4800', $CommBits = '8', $CommParity = '0', $CommStop = '0', $CommCtrl = '0011'

$CommID = _opencomm($CommPort, $CommBaud, $CommBits, $CommParity, $CommStop, $CommCtrl)
If $CommID <> "-1" Then
;While 1
    $BufferData = _rxwait($CommID, 75, 800)
    ConsoleWrite($BufferData & @CRLF)
;WEnd
    _closecomm($CommID)
EndIf

cfxUDF.au3

Andrew Calcutt

Http://www.Vistumbler.net

Http://www.TechIdiots.net

Its not an error, its a undocumented feature

Link to comment
Share on other sites

  • 8 months later...
  • 2 weeks later...

Hello,

I've found this code really useful. I'm writing an application to interface with Diabetic Blood Glucose Meters and have got 2 working so far (Lifescan OneTouch UltraEasy and UltraSmart). I'm now working on an interface to an Abbott Optium Xceed. Nearly all these meters use a USB-to-Serial cable (although the Abbott creates UMPPorts which I've never heard of) and therefore always have a COM port.

I've modified the code so that the _OpenComm accepts parameters, and I've got it doing everything in binary (using bytes) so it can handle chr(0). I've also removed the _rx function and just do everything in the _rxwait, returning a byte with the data that was read.

I also added a little de-bugging by outputting the _tx requests and _rxwait answers in hex pairs to make it easier to read.

The only thing I've never figured out is if theres a way to receive a message without telling it how many bytes to expect beforehand (ie get it to automatically figure out the end of message) Anyone have any ideas? I tried checking the value of $rxr and also tried calling the GetLastError() function of kernel32.dll but it seems that as long as the cable is connected it will always read data (using nulls if it goes past the end of the message)

NiVZ

Link to comment
Share on other sites

does anybody know what the other options might be for this setting?

$CommCtrl = '0011'

I believe it's for flow control.

I googled but could not find anything helpful.

thanks

Hello,

I found this in WIN32API.txt which might explain it

' The fourteen actual DCB bit-sized data fields within the four bytes of fBitFields can be manipulated by bitwise logical And/Or operations.
' FieldName             Bit #     Description
' -----------------     -----     ------------------------------
' fBinary                 1       binary mode, no EOF check
' fParity                 2       enable parity checking
' fOutxCtsFlow            3       CTS output flow control
' fOutxDsrFlow            4       DSR output flow control
' fDtrControl             5       DTR flow control type (2 bits)
' fDsrSensitivity         7       DSR sensitivity
' fTXContinueOnXoff       8       XOFF continues Tx
' fOutX                   9       XON/XOFF out flow control
' fInX                   10       XON/XOFF in flow control
' fErrorChar             11       enable error replacement
' fNull                  12       enable null stripping
' fRtsControl            13       RTS flow control (2 bits)
' fAbortonerror          15       abort reads/writes on error
' fDummy2                16       reserved
Edited by NiVZ
Link to comment
Share on other sites

  • 2 weeks later...

Here is a version that can be used for RS485 communication with converters which use the RTS signal to enable transmission. This works fine for 9600 Baud.

NUL characters can be received. (When the receive count=1 and the string is empty, it has to be a NUL.)

Receiving is done by periodically calling the function _receive(), the number of characters and the received message is stored in global variables.

The function _rx($n) reads a number of characters, _rx (0) or _rx() all received characters.

The function _waitrx uses _receive() to wait for a given time and a number of characters.

Serial parameters can be changed without closing and reopening the port with _setcomm($baud,...).

The use of $CommCtrl is documented in the udf, but not intirely tested.

The sample application can be easily adapted for polling serial devices.

Some BCC and CRC functions I needed are included.

The example script sends ATZ to a modem and displays the answer.

When the button "Send" is pressed, AT&V is sent.

Other possibilities I used for testing are commented out.

Use it and don't blame me.

Uwe

cfxbintest2.au3

cfxbin.au3

Link to comment
Share on other sites

  • 11 months later...

Thanks about this really nice UDF, TABALtd!

I use it to with Customer Display... Only problem that I have notice is some conflict when I try use features of Date.au3(...if I remind file correct) - That file is included to AutoIt instalation. I hope that also this UDF would be included in to official AutoIt instalation program... I think that it would be worth of it.

I tested also "bin" version, but that seems to write data much slower to screen with same COM port settings - I can even see that it write string to screen with putting char after char... Realy.

Edit:

Testing of cfxUDF.au3 is in progress... I noticed that version just now.

Edit (2):

cfxUDF.au3 is now tested and I have notice that Date.au3 cause conflict also with this version:

C:\Program Files\AutoIt3\Include\cfxUDF.au3 (48) : ==> Can not redeclare a constant.:
const $OPEN_EXISTING=3
const ^ ERROR

Also, cfxUDF.au3 cause error when I use AutoItSetOption ("MustDeclareVars",1) on script file (And I prefer to use it):

C:\Program Files\AutoIt3\Include\cfxUDF.au3 (40) : ==> Variable used without being declared.:
$dcbs="long DCBlength;long BaudRate; long fBitFields;short wReserved;"
^ ERROR
Edited by mikkokh

- miXza-81 -

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...