#Requires AutoHotkey v2.0
ComHandle := ComOpen("COM3", 115200, "N", 8, 1) ; 1 stop bit
;ComHandle := ComClose(ComHandle)
ComWriteHex(ComHandle, "01 05 00 00 ff 00 8C 3A")   ;16进制发送
;ComWriteString(ComHandle, "hello")                 ;字符串发送
Sleep(200)                                          ;延迟200毫秒
MsgBox(ComReadByte(ComHandle))                      ;接收
return


; NOTE: See the Changelog at the end of this file.
;###############################################################################
;###############################################################################
; COM Library Subroutines. This uses the Win32 API even with 64-bit Win & AHK.
; (other DLL calls that could be useful: EscapeCommFunction, GetCommModemStatus)
;###############################################################################
;###############################################################################
;###############################################################################
; COM Open Subroutine 
; This opens a COM Port returns a COM Port File Handle. If unsuccessful,
; this returns a null (""). Port is COM1, COM2, ..., COM10, COM11, etc. 
; Baud is 9600 for example. What bauds work depends on the COM hardware.
; Parity is N, E, O, M, S. Stop is 1, 2, maybe others. 
; Settings for handshake lines and flow control could also be added. 
;###############################################################################
ComOpen(Port, Baud, Parity, Data, Stop)
{
  ;MsgBox("Port=" Port " Baud=" Baud " Parity=" Parity " Data=" Data " Stop=" Stop)
  COM_Settings := Port " baud=" Baud " parity=" Parity " data=" Data " stop=" Stop
  ;###### Build COM DCB ######
  DCB := Buffer(90) ;Create the DCB structure (actually 40 words, 80 bytes long)
  BCD_Result := DllCall("BuildCommDCB"
      , "str", COM_Settings
      , "ptr", DCB)
  If (BCD_Result != 1)
    Return (MsgBox("Error opening port '" Port "' using BuildCommDCB"), "")
  ;###### Extract/Format the COM Port Number ######
  ;7/23/08 Thanks krisky68 for finding/solving the bug in which COM Ports
  ;  greater than 9 didn't work.
  ;For COM Ports > 9 \\.\ needs to prepended to the COMn name.
  ;So the valid names are ... COM8 COM9 \\.\COM10 \\.\COM11 ...
  If (StrLen(Port) > 4)
    Port := "\\.\" . Port
  ;###### Create COM File Handle ######
  ComFileHandle := DllCall("CreateFile"
      , "Str", Port
      , "UInt", 0xC0000000
      , "UInt", 3
      , "UInt", 0
      , "UInt", 3
      , "UInt", 0
      , "UInt", 0
      , "Int")
  If (ComFileHandle < 1)
    Return (MsgBox("Error opening port '" Port "' using CreateFile"), "")
  ;###### Set COM State (Port number, baud rate, etc.) ######
  SCS_Result := DllCall("SetCommState", "UInt", ComFileHandle, "ptr", DCB)
  If (SCS_Result != 1)
    Return (MsgBox("Error opening port '" Port "' using SetCommState"),
        ComClose(ComFileHandle))
  ;###### Set the COM Timeouts ######
  Data := Buffer(20, 0) ; 5 * sizeof(DWORD)
  NumPut("UInt", 0xffffffff, Data, 0)  ; ReadIntervalTimeout
  NumPut("UInt", 0x00000000, Data, 4)  ; ReadTotalTimeoutMultiplier
  NumPut("UInt", 0x00000000, Data, 8)  ; ReadTotalTimeoutConstant
  NumPut("UInt", 0x00000000, Data, 12) ; WriteTotalTimeoutMultiplier
  NumPut("UInt", 0x00000000, Data, 16) ; WriteTotalTimeoutConstant
  SCT_result := DllCall("SetCommTimeouts", "UInt", ComFileHandle, "ptr", Data)
  If (SCT_result != 1)
    Return (MsgBox("Error opening port '" Port "' using SetCommTimeouts"),
        ComClose(ComFileHandle))
  Return ComFileHandle
}
;###############################################################################
; COM Close Subroutine 
; This closes the COM port. It returns a null-string.
;###############################################################################
ComClose(ComFileHandle)
{
  If (!ComFileHandle)
  {
    ;MsgBox("Error: Cannot close COM port because it is already closed!")
    Return ""
  }
  If (DllCall("CloseHandle", "UInt", ComFileHandle) != 1)
    Return (MsgBox("Error closing COM port using CloseHandle"), "")
  Return ""
}
;###############################################################################
; COM Write Byte Subroutine 
; This writes a byte to ComFileHandle. This returns 1 for error and 0 for OK.
; If this is passed a string to write, the string cotents will be interpreted
; as a number (as opposed to using the first character's ordinal value/code).
;###############################################################################
ComWriteHex(ComFileHandle, Message)
{
  If (!Message || !ComFileHandle)
    Return 0
  Message := StrReplace(RegExReplace(Message, "(\w+)", "0x$1"), A_Space, ",") ;将报文变为"0x24,0x01,0x04,0x01"这种格式
  ;MsgBox Message
  Byte:=StrSplit(Message, ",",".")  ; 忽略句点.
  Data := Buffer(600, 0) ; 5 * sizeof(DWORD)
  loop(Byte.Length)
    {
      NumPut("UChar", Byte[A_Index], Data, A_Index -1)  ; ReadIntervalTimeout
    }
Size:=Byte.Length
  Bytes_Sent := 0 ; this prevents unset variable error
  Null_Var := 0 ; not used by the Win32 API
  WF_Result := DllCall("WriteFile" ; send message to COM port
      , "UInt", ComFileHandle
      , "ptr", Data
      , "UInt", Size
      , "UInt*", &Bytes_Sent
      , "Int", Null_Var)
  If (WF_Result != 1 || Bytes_Sent != Size)
    Return (MsgBox("Error writing COM port using WriteFile, "
          Bytes_Sent " of 1 bytes sent"), 1)
  Return 0
}
;###############################################################################
; COM Write String Subroutine 
; This writes string "Message" to COM port "ComFileHandle".
; This returns 1 for error and 0 for OK.
; NOTE: At this time, AutoHotkey v2 strings are always UTF-16.
; This handles character codes 1-127 for sure. Not so sure about 0 & 128+.
;###############################################################################
ComWriteString(ComFileHandle, Message)
{
  If (!Message || !ComFileHandle)
    Return 0
  Size := StrPut(Message, "") ; convert Messge from UTF-16 to bytes
  Buff := Buffer(Size)
  StrPut(Message, Buff, "")
  Size := Size - 1 ; don't treat the null terminator as data to output
  ;msgbox("Byte_Size=" Size " String=" Message)
  Bytes_Sent := 0 ; this prevents unset variable error
  Null_Var := 0 ; not used by the Win32 API
  WF_Result := DllCall("WriteFile" ; send message to COM port
      , "UInt", ComFileHandle
      , "ptr", Buff
      , "UInt", Size
      , "UInt*", &Bytes_Sent
      , "Int", Null_Var)
  If (WF_Result != 1 || Bytes_Sent != Size)
    Return (MsgBox("Error writing COM port using WriteFile, "
          Bytes_Sent " of 1 bytes sent"), 1)
  Return 0
}
;###############################################################################
; COM Read Byte Subroutine 
; This reads/returns a byte from COM port "ComFileHandle" or -1 if no data is
; available or there's an error. The return value ranges from 0 to 255
; (0x00 to 0xff), or -1 if there's no data available or there's an error.
; NOTE: At this time, AutoHotkey v2 strings are always UTF-16, so this doesn't
;       use strings at all.
;###############################################################################
ComReadByte(ComFileHandle)
{
  If (!ComFileHandle)
    Return -1
  Buff := Buffer(4000) ; bigger than needed
  Bytes_Received := 0 ; this prevents unset variable error
  RF_Result := DllCall("ReadFile"
      , "UInt", ComFileHandle
      , "ptr", Buff
      , "Int", 0XFF
      , "UInt*", &Bytes_Received
      , "Int", 0)
  ;MsgBox("Bytes_Received=" Bytes_Received) ;返回的字节数
  If (RF_Result != 1)
    Return (MsgBox("Error reading COM port using ReadFile, "
          Bytes_Received " bytes received"), -1)
  If (0 == Bytes_Received)
    Return -1
  RR:=""
  loop(Bytes_Received)
    {
      RR .= Format("{:02}",Format("{1:X}", NumGet(Buff, A_Index -1, "uchar")))
    }
  Return RR
}
/*
CHANGELOG FOR AUTOHOTKEY v2 COM LIBRARY
2023-08-28 v1.0 initial release (used AHK v2.0.5)
*/

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。