Link to home
Start Free TrialLog in
Avatar of joda1250
joda1250Flag for United States of America

asked on

How do I communicate with serial port in PowerBuilder

In this app, I have a hardware device that is sending a byte in through the serial port, I have to "listen" and determine when that byte comes in, grab the data and send a request back.  I would like to know how I can code to determine that data has just come in through COM 1.  The hardware I am communicating with does not offer an Active-X control for me.
Avatar of diasroshan
diasroshan
Flag of Kuwait image

Hi,

you will need the following OCX -->MSCOMM32.OCX
im sure u have it on ur machine already.
Now using OLE u can communicate with ur serial port.

Check the following links for more info,
https://www.experts-exchange.com/questions/20560721/Read-Write-in-ports-COM1-COM2.html
https://www.experts-exchange.com/questions/21349512/HOW-TO-CONTROL-A-CUSTOMER-DISPLAY-DEVICE-USING-COM-PORT.html

Attaching exported objects from below link,
https://www.experts-exchange.com/questions/20876598/accessing-COM-port.html


Hope This Helps...

Cheers,
Rosh
$PBExportHeader$n_cst_serialcom.sru
forward
global type n_cst_serialcom from nonvisualobject
end type
end forward
 
global type n_cst_serialcom from nonvisualobject autoinstantiate
end type
 
type prototypes
/* To create a file */
function ulong CreateFileA( ref string lpszName,  &
  ulong fdwAccess,  &
  ulong fdwShareMode,  &
  ulong lpsa,    &
  ulong fdwCreate,  &
  ulong fdwAttrsAndFlags,  &
  ulong hTemplateFile ) library "kernel32.dll"
 
/* to write to the file */
function boolean WriteFile( ulong hFile,  &
  ref string lpBuffer,  &
  ulong nNumberOfBytesToWrite, &
  ulong lpNumberOfBytesWritten, &
  st_overlapped lpOverlapped ) library "kernel32.dll" 
 
/* To get error information */
function ulong GetLastError() library "kernel32.dll"
 
/* To close the file */
function boolean CloseHandle(ulong hObject ) library "kernel32.dll" 
 
function boolean ReadFile( ulong fFile,    &
  ref string lpBuffer,    &
  ulong nNumberOfBytesToRead, &
  ulong lpNumberOfBytesRead, &
  ref st_overlapped lpOverlapped)  &
  library "Kernel32.dll"
 
/* Flush the file buffer */
function boolean FlushFileBuffers(  ulong hFile) library "kernel32.dll" 
 
/* Setup the Communications Port */
function boolean SetupComm( ulong hFile,  &
  ulong dwInQueue,  &
  ulong dwOutQueue) library "kernel32.dll"
 
/* Setup Com Port Timeouts */
function boolean SetCommTimeouts( ulong hFile,  &
    st_commtimeouts lpCommTimeouts) &
    library "kernel32.dll"
 
/* Setup Comm Mask */
function boolean SetCommMask( ulong hFile,  &
    ulong dwEvtMask)  &
    library "kernel32.dll"
 
/* Wait Comm Event */
function boolean WaitCommEvent(      ulong hFile,  &
    ref ulong lpEvtMask,  &
    st_overlapped lpOverlapped)  &
    library "kernel32.dll"
 
/* Purge Comm port */
function boolean PurgeComm(ulong hFile,  &
    ulong dwFlags)  &
    library "kernel32.dll"
 
/* Clear Comm Error 
function boolean ClearCommError( ulong hFile,      &
    ref ulong lpErrors,  &
    ref st_comstat lpStat) &
    library "kernel32.dll"*/
  
/* Set up the port */
function ulong BuildCommDCBA( ref string port_description,  &
  ref st_DCB DCB_structure) library "kernel32.dll"
  
function ulong SetCommState( ulong comm_id,  &
  ref st_DCB DCB_structure) library "kernel32.dll"
end prototypes
 
type variables
integer ii_comPort
integer il_comTimeout
 
end variables
 
forward prototypes
public function string read (integer al_read_length)
public function integer open (integer ai_comport)
public function integer close ()
public function integer write (ref string as_buffer)
public function long getcomtimeout ()
public subroutine setcomtimeout (long al_timeout)
public function integer readcharacter (ref string as_readstring)
end prototypes
 
public function string read (integer al_read_length);string        ls_buffer
long          ll_bytes_read = 0
long          ll_bytes_written = 0
boolean       lb_return
st_overlapped lst_overlapped
 
ls_buffer = space(al_read_length)
 
lst_overlapped.internal = 0
lst_overlapped.internalhigh = 0
lst_overlapped.offset = 0
lst_overlapped.offsethigh = 0
lst_overlapped.hevent = 0
 
lb_return = ReadFile(ii_comPort,ls_buffer,al_read_length,ll_bytes_read,lst_overlapped)
 
if lb_return = FALSE then
      messagebox("Read Failed","Handle = "+string(ii_comPort) + "~r~nError = "+string(getlasterror()))
else
      if lb_return = true and len(ls_buffer) = 0 then
      setnull(ls_buffer)      
   end if
end if
 
return ls_buffer
end function
 
public function integer open (integer ai_comport);CONSTANT long   EV_RXCHAR = 0
CONSTANT long   GENERIC_READ = 2147483648
CONSTANT long   GENERIC_WRITE = 1073741824
CONSTANT long   FILE_SHARE_NONE = 0 
CONSTANT long   OPEN_EXISTING = 1
CONSTANT long   PURGE_TXABORT = 1
CONSTANT long   PURGE_RXABORT = 1
CONSTANT long   PURGE_TXCLEAR = 1
CONSTANT long   PURGE_RXCLEAR = 1
CONSTANT long   FF_OVERLAPPED = 0
 
string ls_port
string ls_port_description
long   ll_null
long   ll_return_cd
st_commtimeouts     str_commtimeouts
st_DCB              str_DCB
 
ii_comPort = ai_comPort
 
if ai_comPort = 1 then
      ls_port = "COM1:"
      ls_port_description = "COM1: 9600,N,8,1"
elseif ai_comPort = 2 then
      ls_port = "COM2:"
      ls_port_description = "COM2: 9600,N,8,1"
elseif ai_comPort = 3 then
      ls_port = "COM3:"
      ls_port_description = "COM3: 9600,N,8,1"
elseif ai_comPort = 4 then
      ls_port = "COM4:"
      ls_port_description = "COM4: 9600,N,8,1"
else
      ai_comPort = 0
      messagebox("Port Error","An invalid com port was passed to the open port function")
end if
 
setnull(ll_null)
 
ii_comPort = CreateFileA(ls_port, GENERIC_READ + GENERIC_WRITE, FILE_SHARE_NONE, ll_null, OPEN_EXISTING, FF_OVERLAPPED, ll_null)
 
IF ii_comPort < 0 THEN
   MessageBox("OPEN ERROR", "Handle = " + string(ii_comPort) + "~r~nError = " + string(GetLastError()))
else
      // Set the port variables
      ll_return_cd = BuildCommDCBA(ls_port_description,str_DCB)
      
      if ll_return_cd = 0 then
            messagebox("Build Comm Error","Error code = "+string(ll_return_cd))
      else
            ll_return_cd = SetCommState(ii_comPort,str_DCB)
      end if
      
   // Setup the Comm mask
   if SetCommMask(ii_comPort, EV_RXCHAR) = FALSE then 
            MessageBox("SETCOMMMASK", "Handle = " + string(ii_comPort) + "~r~nError = " + string(GetLastError()))
      end if
      
      // Setup the buffers
   if SetupComm(ii_comPort, 4096, 4096) = FALSE then 
            MessageBox("SETUPCOMM", "Handle = " + string(ii_comPort) + "~r~nError = " + string(GetLastError()))
      end if
 
   // Flush the Port's buffer
   if FlushFileBuffers(ii_comPort) = FALSE then 
            MessageBox("FLUSH", "Handle = " + string(ii_comPort) + "~r~nError = " + string(GetLastError()))
      end if
 
   // Purge the Port
   if PurgeComm(ii_comPort, PURGE_TXABORT + PURGE_RXABORT + PURGE_TXCLEAR + PURGE_RXCLEAR) = FALSE then 
            MessageBox("PURGECOMM", "Handle = " + string(ii_comPort) + "~r~nError = " + string(GetLastError()))
      end if
 
   // Setup Timeouts
      SetComTimeout(1500)
end if
 
return ii_comPort
end function
 
public function integer close ();boolean lb_return
int     li_return_cd = -1
 
lb_return = CloseHandle(ii_comPort)
 
if lb_return = false then
   messagebox("Close Failed","Com port id = " + string(ii_comPort))
else
      li_return_cd = 1
end if
 
return li_return_cd
end function
 
public function integer write (ref string as_buffer);long          ll_bytes_read = 0
long          ll_bytes_written = 0
boolean       lb_return
st_overlapped lst_overlapped
 
lst_overlapped.internal = 0
lst_overlapped.internalhigh = 0
lst_overlapped.offset = 0
lst_overlapped.offsethigh = 0
lst_overlapped.hevent = 0
 
lb_return = WriteFile(ii_comPort,as_buffer,len(as_buffer),ll_bytes_written,lst_overlapped)
 
if lb_return = FALSE then
      messagebox("WriteFailed","Handle = "+string(ii_comPort) + "~r~nError = "+string(getlasterror()))
end if
 
return 1
end function
 
public function long getcomtimeout ();return il_ComTimeout
 
end function
 
public subroutine setcomtimeout (long al_timeout);st_commtimeouts     str_commtimeouts
 
il_comTimeout = al_timeout
 
// set read timeout
str_commtimeouts.ReadIntervalTimeout      = al_timeout
str_commtimeouts.ReadTotalTimeoutConstant = al_timeout
      
str_commtimeouts.ReadTotalTimeoutMultiplier  = 0
str_commtimeouts.WriteTotalTimeoutMultiplier = 0
str_commtimeouts.WriteTotalTimeoutConstant   = 0
 
// Setup Timeouts
if SetCommTimeouts(ii_comPort, str_commtimeouts) = FALSE then
  MessageBox("SETCOMMTIMEOUTS", "Handle = " + string(ii_comPort) + "~r~nError = " + string(GetLastError()))
end if
 
return 
end subroutine
 
public function integer readcharacter (ref string as_readstring);string        ls_buffer
long          ll_bytes_read = 0
long          ll_bytes_written = 0
boolean       lb_return
st_overlapped lst_overlapped
 
ls_buffer = space(1)
 
lst_overlapped.internal = 0
lst_overlapped.internalhigh = 0
lst_overlapped.offset = 0
lst_overlapped.offsethigh = 0
lst_overlapped.hevent = 0
 
lb_return = ReadFile(ii_comPort,ls_buffer,1,ll_bytes_read,lst_overlapped)
 
if lb_return = FALSE then
      messagebox("Read Failed","Handle = "+string(ii_comPort) + "~r~nError = "+string(getlasterror()))
else
      ll_bytes_read = len(ls_buffer)
      if lb_return = true and len(ls_buffer) = 0 then
      setnull(ls_buffer)      
   end if
end if
as_readString = ls_buffer
 
return ll_bytes_read
end function
 
on n_cst_serialcom.create
call super::create
TriggerEvent( this, "constructor" )
end on
 
on n_cst_serialcom.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on

Open in new window

Avatar of joda1250

ASKER

Thank you for the assistance on this.
I tried to import your uo script but get an error message "illegal data type st_overlapped"  Do you have the export for this?  I assume it is a structure?

I do have the mscomm32.ocx on my PC, when I try to add an OLE object using it, I try CREATE FROM FILE and it does not give me the OLE properties I expect.  So I try to use INSERT CONTROL and get an error message "License file required"

I looked the links you give me above, some of them lead to dead ends and other one has the exported uo which gives me same error on import.

Once I do make communication, all I need to do is listen for data to come in through COM1 and read it byte by byte.

Thank you for your time.
I tried to register the mscomm32.ocx and got a successful message.  Still did not help the license issue.  Then I tried to unregister it and re register it.  No good still.

joda
Hi,

sorry abt the delayed reply... kinda lost the thread....

st_overlapped is a structure we need when writing to the communication ports. It is defined as follows:
$PBExportHeader$st_overlapped.srs
global type st_overlapped from structure
long Internal
long Internalhigh
long offset
long offsethigh
long hevent
end type


Please refer:
http://eric.aling.tripod.com/PB/tips/pbtip12.htm

Cheers,
Rosh
Rosh, Thank you for the help.

Now anther structure is needed.     st_DCB

Thanks,
John
Hi,

i dont see the above structure st_DCB in the code provided by me above.
Please refer the URL http://eric.aling.tripod.com/PB/tips/pbtip12.htm

I dont thing u need anything beyond the code provided there to achieve wat u want in ur original question.

Or,
provide the code ur using.wonder wat st_DCB is???

Cheers,
Rosh
Please see line 142 in the code of your first reply.  There it has this variable defined.  

st_DCB              str_DCB

When I attempt an import on the n_cst_serialcom.sru file, I need to have that strructure defined.
ASKER CERTIFIED SOLUTION
Avatar of diasroshan
diasroshan
Flag of Kuwait image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for the help Rosh.  Greatly appreciated.