问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C语言串口操作函数详解

创作时间:
作者:
@小白创作中心

C语言串口操作函数详解

引用
1
来源
1.
http://www.cdweb.net/article/dooccjj.html

串口通信是一种常见的设备间数据传输方式,在工业控制、嵌入式系统等领域有着广泛的应用。使用C语言进行串口操作,可以实现对串口设备的精确控制和数据交互。本文将详细介绍如何使用C语言实现串口通信,包括串口的打开、数据的发送和接收等核心功能。

如何用C语言控制计算机串口

基本方法是使用CreateFile来建立一个串口文件,然后用overlap的方式进行读写

#define SERAIL_PORT_BUF_MAX (1024*8)  
typedef HRESULT (*PFN_CMD_PARSE_DATA)(HANDLE hParseApp, LPCSTR szRspCmd, int nCmdLen);  
class CUsbSrvApp// : public CWinApp  
{  
public:  
CUsbSrvApp();  
~CUsbSrvApp();  
BOOL OnSendData(const char *szBuf, int nLen);// 发送数据  
int ComConnect(CString strPort); // 连接COM口  
HANDLE OpenComPort(CString strPort, int nBaudRate, int nDataBits, int nStopBits, int nParity, int nFlowCtrlType); // 打开串口  
void Close(); // 关闭串口  
HANDLE m_hCom;  
BOOL m_bConnected;  
OVERLAPPED m_OverlappedRead;  
OVERLAPPED m_OverlappedWrite;  
CWinThread *m_pThread;  
PFN_CMD_PARSE_DATA m_pRspCmdFunc; // 用来处理接受数据的CALLBACK  
HANDLE m_hParseApp;  
};  
CUsbSrvApp::CUsbSrvApp()  
{  
// TODO: add construction code here,  
// Place all significant initialization in InitInstance  
m_bConnected = false;  
m_hCom = NULL;  
m_pRspCmdFunc = NULL;  
}  
CUsbSrvApp::~CUsbSrvApp()  
{  
}  
//打开串口通信,并返回串口句柄  
HANDLE CUsbSrvApp::OpenComPort(CString strPortName,  
int nBaudRate,  
int nDataBits,  
int nStopBits,  
int nParity,  
int nFlowCtrlType)  
{  
DCB dcb;  
COMMTIMEOUTS CommTimeOuts ;  
COMMCONFIG ComConfig;  
HANDLE hComPort;  
CString strPort;  
strPort.Format("\\\\.\\%s",strPortName); // COM口的文件名应该是 \\.\COMXX  
//打开窗口其实就是创建一个文件  
hComPort = CreateFile(strPort,  
GENERIC_READ | GENERIC_WRITE,  
FILE_SHARE_READ | FILE_SHARE_WRITE,  
NULL,  
OPEN_EXISTING,  
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,  
NULL);  
if (INVALID_HANDLE_VALUE == hComPort)  
return INVALID_HANDLE_VALUE;  
// 设置一些COM口通讯参数和OVERLAP  
CommTimeOuts.ReadIntervalTimeout = -1;  
CommTimeOuts.ReadTotalTimeoutConstant = 0;  
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;  
CommTimeOuts.WriteTotalTimeoutConstant = 0;  
CommTimeOuts.WriteTotalTimeoutMultiplier = 0x1388;  
SetCommTimeouts( m_hCom, CommTimeOuts ) ;  
SetDefaultCommConfig(strPortName, ComConfig, sizeof(COMMCONFIG));  
GetCommState(m_hCom, dcb ) ;  
dcb.BaudRate = nBaudRate;  
dcb.ByteSize = nDataBits;  
dcb.StopBits = nStopBits;  
dcb.fParity = (NOPARITY != nParity);  
dcb.Parity = nParity;  
//set the receive char  
dcb.EvtChar = 0x0D;  
switch(nFlowCtrlType)  
{  
case 0: //no flow control  
break;  
case 1://HARD_FLOW_CTRL:  
dcb.fOutxCtsFlow = TRUE;  
dcb.fOutxDsrFlow = TRUE;  
dcb.fDtrControl = DTR_CONTROL_DISABLE;  
dcb.fDsrSensitivity = TRUE;  
dcb.fRtsControl = RTS_CONTROL_TOGGLE;  
break;  
case 2://SOFT_FLOW_CTRL:  
dcb.fOutX = TRUE;  
dcb.fInX = TRUE;  
break;  
}  
BuildCommDCB(_T("baud=115200 parity=N data=8 stop=1"),dcb);  
SetCommState(hComPort, dcb ) ;  
SetCommMask(hComPort, 0);  
SetCommMask(hComPort, EV_RXCHAR|EV_CTS|EV_DSR|EV_RLSD|EV_RING);  
SetupComm( hComPort, SERAIL_PORT_BUF_MAX,SERAIL_PORT_BUF_MAX) ;  
//clear read and write buffer  
PurgeComm( hComPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );  
return hComPort;  
}  
void CUsbSrvApp::Close()  
{  
if(m_bConnected)  
{  
m_bConnected = false;  
CloseHandle(m_hCom);  
m_hCom = NULL;  
}  
}  
// 这个线程是监视串口数据,一旦有数据则读取并调用CALLBACK通知客户端  
UINT ReceiveComData(LPVOID pParam)  
{  
CUsbSrvApp *pUsbSrv = (CUsbSrvApp *)pParam;  
HANDLE hComPort = pUsbSrv-m_hCom;  
DWORD dwEvtMask=0;  
DWORD dwErrorFlags;  
SetCommMask( hComPort, EV_RXCHAR);  
OVERLAPPED osRead;  
osRead.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);  
DWORD dwTransfer = 0;  
while(pUsbSrv-m_bConnected)  
{  
if( !WaitCommEvent( hComPort, dwEvtMask,osRead))  
{  
if( GetLastError()== ERROR_IO_PENDING)  
{  
WaitForSingleObject(osRead.hEvent, INFINITE);  
if(dwEvtMaskEV_RXCHAR==EV_RXCHAR)  
{  
COMSTAT ComStat={0} ;  
DWORD dwReadLen = 0;  
DWORD dwBytesRead = 0;  
DWORD dwTotalLen = 0;  
ClearCommError(hComPort, dwErrorFlags, ComStat );  
dwTotalLen = ComStat.cbInQue;  
dwReadLen = (SERAIL_PORT_BUF_MAX dwTotalLen)?dwTotalLen:SERAIL_PORT_BUF_MAX;  
BYTE *pBuf = new BYTE[dwTotalLen+1];  
memset(pBuf, 0 , dwTotalLen+1);  
DWORD nReadBufLen=0;  
while(dwTotalLen0)  
{  
if(FALSE == ReadFile( hComPort, pBuf+nReadBufLen,dwReadLen, dwBytesRead,pUsbSrv-m_OverlappedRead))  
{  
if(GetLastError() == ERROR_IO_PENDING)  
{  
GetOverlappedResult(hComPort,osRead, dwTransfer, TRUE );  
}  
break;  
}  
nReadBufLen +=dwBytesRead;  
dwTotalLen -=dwBytesRead;  
dwReadLen -= dwBytesRead;  
dwReadLen = (SERAIL_PORT_BUF_MAXdwReadLen)?dwReadLen:SERAIL_PORT_BUF_MAX;  
}  
if(pUsbSrv-m_pRspCmdFunc!=NULLnReadBufLen!=0)  
{  
pUsbSrv-m_pRspCmdFunc(pUsbSrv-m_hParseApp, (char*)pBuf,nReadBufLen);  
}  
delete pBuf;  
ClearCommError(hComPort, dwErrorFlags, ComStat );  
int len =0;//= m_retList.GetSize();  
}//endif if(dwEvtMaskEV_RXCHAR==EV_RXCHAR)  
}//endif if( GetLastError()== ERROR_IO_PENDING)  
}//endif if( !WaitCommEvent( hComPort, dwEvtMask,o))  
else  
{  
if(GetLastError() == ERROR_IO_PENDING) {  
GetOverlappedResult(hComPort, osRead, dwTransfer, TRUE ); // sleep thread  
}  
}  
Sleep(1);  
} //endwhile while(m_bConnected)  
return 0;  
}  
int CUsbSrvApp::ComConnect(CString strPort)  
{  
int nBaudRate = 115200;  
int nDataBits = 8;  
int nStopBits = 1;  
int nParity = 0;  
int nFlowCtrl = 1;  
if (NULL != m_hCom || m_bConnected)  
{  
return 0;  
}  
m_hCom = OpenComPort(strPort,nBaudRate,nDataBits,nStopBits,nParity,nFlowCtrl);  
if( INVALID_HANDLE_VALUE == m_hCom)  
{  
m_hCom = NULL;  
return 0;  
}  
memset( m_OverlappedRead, 0, sizeof( OVERLAPPED ) );  
memset( m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );  
m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );  
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );  
m_pThread = AfxBeginThread( ReceiveComData,(void*)this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED ,NULL );  
if( NULL == m_pThread )  
{  
CloseHandle( m_hCom );  
m_hCom = NULL;  
return FALSE;  
}  
else  
{  
m_bConnected = TRUE;  
m_pThread-ResumeThread( );  
}  
return TRUE;  
}  
int CUsbSrvApp::OnSendData(const char *szBuf, int nLen)  
{  
BOOL bWriteStat;  
BOOL bWrite = TRUE;  
DWORD dwBytesWrite = 0;  
DWORD dwBytesWritten = 0;  
int dwByteswrittenTotal = 0;  
if (NULL == m_hCom)  
return 0;  
int nSentTimes=0;  
while(dwByteswrittenTotalnLennSentTimes10)  
{  
nSentTimes++;  
dwBytesWrite = nLen-dwByteswrittenTotal;  
bWriteStat = WriteFile( m_hCom, szBuf+dwByteswrittenTotal, dwBytesWrite, dwBytesWritten, m_OverlappedWrite );  
if( !bWriteStat)  
{  
if ( GetLastError() == ERROR_IO_PENDING )  
{  
dwBytesWritten = 0;  
bWrite = FALSE;  
}  
}  
if (!bWrite)  
{  
bWrite = TRUE;  
bWriteStat = GetOverlappedResult(m_hCom, // Handle to COMM port  
m_OverlappedWrite, // Overlapped structure  
dwBytesWritten, // Stores number of bytes sent  
TRUE); // Wait flag  
//deal with the error code  
}  
dwByteswrittenTotal += dwBytesWritten;  
}  
if(dwByteswrittenTotalnLen)  
return 0;  
else  
return 1;  
}  

C语言中如何对串口进行操作

C语言会有操作串口的库函数的,按照串口库函数标识实现调用就可以了。

一个串口通信的C语言函数

PIC的还真没用过,不过从C的角度讲 buffer 在没有初始化的情况下貌似就被使用了,如果编译器使用固定地址分配给局部变量 buffer 就会出事了。把

while(buffer != 'P')  
{  
buffer = RCREG;  
}  

改为

do  
{  
buffer = RCREG;  
}  
while(buffer != 'P');  

可以避免这类BUG;但愿能有点帮助 :)

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号