pccomprt.c
来自「HART协议编程例程」· C语言 代码 · 共 369 行
C
369 行
/* ================================================================= *
* *
* File Name: PcComPrt.c *
* Device: IBM PC compatible, Windows API32 *
* Author(s): Walter Borst (bow), Borst Automation *
* *
* Description *
* =========== *
* Functions to use the com port of a PC by access of the Windows *
* API. When a com port is opened a thread is started and handling *
* the communication events. *
* *
* Revision History *
* ================ *
* date: name: version: description: *
* jan-00 bow 00000 module created *
* *
* Functions *
* ========= *
* HANDLE OpenComPort(uiPort, // 1..8 *
* uiBaudrate, // 1200..56700 *
* ucDataBits, // 4..8 *
* ucParity, // 0-4 = no,odd,even,mark,space *
* ucStopBits // 0,1,2 = 1, 1.5, 2 *
* ); *
* - Opens a com port and starts a thread. *
* - Returns the com port handle. *
* *
* UINT CloseComPort(HANDLE //Handle returned by open *
* ); *
* - Closes a com port and ends the thread. Returns TRUE or FALSE. *
* *
* UINT WriteToCom(HANDLE, //Handle returned by open *
* pbyData, //Pointer to stream to be sent *
* uiLen //number of octets in stream *
* ); *
* - Writes data to the com port buffer and starts sending. *
* *
* Remarks *
* ======= *
* Program using this functions has to be linked with winmm.lib *
**********************************************************************/
/**********************************************************************
* The Standard Include *
**********************************************************************/
#define __PCCOMPRT_H__
#include "..\Common\PcComPrt.h"
/**********************************************************************
* Global variables and data objects *
**********************************************************************/
static typCOMPORTINFO m_strComPortInfo[MAXCOMPORT];
static UCHR m_ucLastChar;
static UCHR m_ucLastErr;
static UCHR m_ucDelayCycles = 0;
/**********************************************************************
* Functions *
**********************************************************************/
//******************
void PcComPrtInitialize(void)
//******************
{ //Initializes the internal data of the module
//Called when DLL is loaded
UCHR e;
for(e=0;e<MAXCOMPORT;e++)
{ m_strComPortInfo[e].ulConnected = FALSE;
m_strComPortInfo[e].iComIdx = 0;
m_strComPortInfo[e].ulLastTransitionTime = timeGetTime();
m_strComPortInfo[e].uiSendBufLen = 0;
m_strComPortInfo[e].uiCount = 0;
m_strComPortInfo[e].uiState = 0;
m_strComPortInfo[e].hComFileHandle = INVALID_HANDLE_VALUE;
m_strComPortInfo[e].hComThread = INVALID_HANDLE_VALUE;
m_strComPortInfo[e].ulThreadId = 0;
m_strComPortInfo[e].pAppCallBack = NULL;
m_strComPortInfo[e].uiThreadRepeat = FALSE;
m_strComPortInfo[e].uiThreadEnded = FALSE;
m_strComPortInfo[e].uiSISMstatus = SISM_IDLE;
}
}
//This is called by the hart initialization (lower layer)
/***********/
BOOL OpenComPort(
/***********/ UINT uiComPort,
UINT uiBaudrate,
UCHR ucDataBits,
UCHR ucParity,
UCHR ucStopBits
)
{ CHR szPort[15];
COMMTIMEOUTS strCommTimeOuts;
DCB dcb;
INT iComIdx = (INT) uiComPort-1;
if (uiComPort>MAXCOMPORT)
return FALSE;
else if (uiComPort < 1)
{
return FALSE;
}
else
{
wsprintf(szPort,"COM%d",uiComPort) ;
}
if (COMPORTINFO.hComFileHandle != INVALID_HANDLE_VALUE)
{
// Allready registered !!!
return FALSE; //Only one caller may use the com port
}
// open COMM device
COMPORTINFO.hComFileHandle =
CreateFile( szPort, GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attrs
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_OVERLAPPED, // overlapped I/O
NULL
);
if (COMPORTINFO.hComFileHandle == INVALID_HANDLE_VALUE)
return FALSE; //No success
// get any early notifications
SetCommMask(COMPORTINFO.hComFileHandle,EV_RXCHAR);
// setup device buffers
SetupComm(COMPORTINFO.hComFileHandle,256,256);
// purge any information in the buffer
PurgeComm(COMPORTINFO.hComFileHandle,
PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR
);
// set up for overlapped I/O
strCommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
strCommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
strCommTimeOuts.ReadTotalTimeoutConstant = 1000 ;
strCommTimeOuts.WriteTotalTimeoutMultiplier = 0 ;
strCommTimeOuts.WriteTotalTimeoutConstant = 1000 ;
SetCommTimeouts(COMPORTINFO.hComFileHandle,&strCommTimeOuts) ;
/******************************
* Set the com port parameter *
******************************/
GetCommState(COMPORTINFO.hComFileHandle,&dcb) ;
dcb.BaudRate = uiBaudrate;
dcb.ByteSize = ucDataBits;
dcb.Parity = ucParity;
dcb.StopBits = ucStopBits;
dcb.fBinary = TRUE;
dcb.fParity = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = (char) 0;
dcb.fAbortOnError = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
if (SetCommState(COMPORTINFO.hComFileHandle,&dcb)==FALSE)
return TRUE;
COMPORTINFO.ulConnected = TRUE;
COMPORTINFO.iComIdx = iComIdx;
//***************************************************
//* Start Thread to run the application state machine
//***************************************************
if (COMPORTINFO.uiThreadRepeat == FALSE)
{ COMPORTINFO.uiThreadRepeat = TRUE;
COMPORTINFO.hComThread =
CreateThread((LPSECURITY_ATTRIBUTES) NULL, //Security Flag
0, //Stack size = default
(LPTHREAD_START_ROUTINE) CommWatchProc,
//Start procedure
(LPVOID) &(COMPORTINFO), //Thread's data
0,
//THREAD_PRIORITY_TIME_CRITICAL, //Creation flags
&COMPORTINFO.ulThreadId
);
}
if (COMPORTINFO.hComThread == 0)
{
COMPORTINFO.uiThreadRepeat = FALSE;
CloseHandle(COMPORTINFO.hComFileHandle);
COMPORTINFO.hComFileHandle = INVALID_HANDLE_VALUE;
return FALSE; //Thread did not start
}
else
{
//Give thread highest priority possible
SetThreadPriority(COMPORTINFO.hComThread,
THREAD_PRIORITY_TIME_CRITICAL);
//Com port handshake and carrier control signals
EscapeCommFunction(COMPORTINFO.hComFileHandle,CLRRTS);
EscapeCommFunction(COMPORTINFO.hComFileHandle,SETDTR);
}
return TRUE;
} // end of OpenComPort()
/************/
VOID CloseComPort(INT iComPort)
/************/
{
INT iComIdx = iComPort - 1;
//End the thread
if (COMPORTINFO.uiThreadRepeat != FALSE)
{
COMPORTINFO.uiThreadRepeat = FALSE;
while (COMPORTINFO.uiThreadEnded == FALSE)
{ Sleep(10);
}
COMPORTINFO.uiThreadEnded = FALSE;
}
//Close the com port
if (COMPORTINFO.hComFileHandle != INVALID_HANDLE_VALUE)
CloseHandle(COMPORTINFO.hComFileHandle);
}
/**********/
VOID WriteToCom(
/**********/ INT iComPort,
BYTE* pbBuf,
UINT uiLen)
{
INT iComIdx = iComPort - 1;
DWORD dwLen;
UCHR e;
for (e=0;e<HRT_NO_PREAMBLES;e++)
COMPORTINFO.bySendBuf[e] = 0xff;
dwLen = uiLen;
memcpy(&COMPORTINFO.bySendBuf[HRT_NO_PREAMBLES],pbBuf,dwLen);
COMPORTINFO.uiSendBufLen = dwLen+HRT_NO_PREAMBLES;
COMPORTINFO.uiSISMstatus = SISM_TRANSMITTING;
}
/**********/
UCHR GetRcvChar(VOID)
/**********/
{
return m_ucLastChar;
}
/*********/
UCHR GetRcvErr(VOID)
/*********/
{
return m_ucLastErr;
}
//*************
static INT ReadCommBlock(LPSTR pParam, LPSTR lpszBlock)
//*************
// Copies received characters from the com port buffer
// to the user buffer (lpszBlock)
{
COMSTAT ComStat;
int fReadStat = FALSE;
DWORD dwErrorFlags = 0;
DWORD dwLength = 0;
// only try to read number of bytes in queue
ClearCommError(PCOMPORTINFO->hComFileHandle,&dwErrorFlags,&ComStat);
m_ucLastErr = 0;
if (dwErrorFlags)
{
if (dwErrorFlags & CE_FRAME)
m_ucLastErr |= HRT_ERR_FRAMING;
if (dwErrorFlags & CE_OVERRUN)
m_ucLastErr |= HRT_ERR_OVERRUN;
if (dwErrorFlags & CE_RXPARITY)
m_ucLastErr |= HRT_ERR_VERT_PARITY;
}
dwLength = min(MAXBLOCK,ComStat.cbInQue);
if (dwLength > 0)
{ fReadStat = ReadFile(PCOMPORTINFO->hComFileHandle,
lpszBlock,
dwLength,
&dwLength,
&(PCOMPORTINFO->osRead));
if (!fReadStat)
{ // I/O error
// not handled here but by the communication state machine
}
}
return ( dwLength ) ;
}
//#############
static DWORD WINAPI CommWatchProc(LPSTR pData)
//#############
// Thread for com port i/o handling
{
// COMSTAT ComStat;
DWORD dwEvtMask;
DWORD dwErrorFlags;
DWORD dwWritten;
OVERLAPPED os;
INT iLen;
BYTE abIn[MAXBLOCK+1];
typCOMPORTINFO* pParam = (typCOMPORTINFO*) pData;
INT e;
COMSTAT ComStat;
memset(&os,0,sizeof(OVERLAPPED));
// create I/O event used for overlapped read
os.hEvent = CreateEvent(NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL // no name
);
if (os.hEvent == NULL)
{ MessageBox( NULL, "Failed to create event for thread!", "COMPORT Error!",
MB_ICONEXCLAMATION | MB_OK ) ;
return (FALSE) ;
}
if (!SetCommMask(PCOMPORTINFO->hComFileHandle,
EV_RXCHAR | EV_TXEMPTY ))
return (FALSE);
// ### THE LOOP OF THE THREAD ###############################
while (PCOMPORTINFO->uiThreadRepeat)
{
if (PCOMPORTINFO->uiSISMstatus == SISM_TRANSMITTING)
{ //Transmit
COMPORT_START_SEND;
while(PCOMPORTINFO->uiSISMstatus == SISM_TRANSMITTING)
{ dwEvtMask = 0;
GetCommMask(PCOMPORTINFO->hComFileHandle,&dwEvtMask);
if ((dwEvtMask & EV_TXEMPTY) == EV_TXEMPTY)
{
COMPORT_TRANSMIT_DONE; //This will set .uiSISMstatus = SISM_IDLE
hrtTransmitDone(); //CALL THE HART DRIVER
//===============
}
Sleep(5);
}
}
else
{ iLen = ReadCommBlock((LPSTR) pParam,(LPSTR) abIn);
if (iLen)
{ //Receive
m_ucDelayCycles = (UCHR)(iLen - 1);
for (e=0;e<iLen;e++)
{
m_ucLastChar = abIn[e];
hrtGetChar(); //CALL THE HART DRIVER
//==========
}
}
else
{ //Do Cycle
if (!m_ucDelayCycles)
hrt5msCycle(); //CALL THE HART DRIVER
//===========
else
m_ucDelayCycles--;
Sleep(3); //Wait five ms before next action
}
}
} // while (uiThreadRepeat)
// get rid of event handle
CloseHandle(os.hEvent);
PCOMPORTINFO->uiThreadEnded = TRUE;
ExitThread(0);
return(0);
} // end of CommWatchProc()
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?