重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
驱动函数不是直接调用的,而是通过通讯完成调用的。可以参考:
创新互联建站专注于企业成都全网营销、网站重做改版、和县网站定制设计、自适应品牌网站建设、成都h5网站建设、商城网站定制开发、集团公司官网建设、外贸网站制作、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为和县等各大城市提供网站开发制作服务。
BOOL WINAPI DeviceIoControl(
_In_ HANDLE hDevice,
_In_ DWORD dwIoControlCode,
_In_opt_ LPVOID lpInBuffer,
_In_ DWORD nInBufferSize,
_Out_opt_ LPVOID lpOutBuffer,
_In_ DWORD nOutBufferSize,
_Out_opt_ LPDWORD lpBytesReturned,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
#includewindows.h
#includestdio.h
int main()
{
HANDLE hComm;
hComm = CreateFile(“COM1”, // for COM1—COM9 only
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL);
if (hComm == INVALID_HANDLE_VALUE)
printf(“Error in opening serial port”);
else
printf(“opening serial port successful”);
char lpBuffer[] = 0x01;
DWORD dNoOFBytestoWrite; // No of bytes to write into the port
DWORD dNoOfBytesWritten = 0; // No of bytes written to the port
dNoOFBytestoWrite = sizeof(lpBuffer);
Status = WriteFile(hComm, // Handle to the Serial port
lpBuffer, // Data to be written to the port
dNoOFBytestoWrite, //No of bytes to write
dNoOfBytesWritten, //Bytes written
NULL);
CloseHandle(hComm);//Closing the Serial Port
return 0;
}
在linux后者在unix下,可以用C,但在windows下,就要用C++,调用windows的串口驱动。
狂晕中....给你linux代码,你就问windows,给你windows串口控制方式,你就问linux,I 服了 You。
区别很大,两个不同的操作系统,在应用串口上就有所不同,但大体上,还是有共同点,1、设置串口,2、打开串口,3、读写数据,4、异常处理,5、关闭串口
这一系列的控制逻辑都大体相同,只是在代码实现上有所不一样,毕竟两种操作系统内核结构就不一样,linux的串口设置属性是通过头文件#include termios.h的struct termios结构实现,而windows的串口属性是commprop结构设定,其他的读写串口,都有相应的读写文件函数,两种系统都是把串口当作一个设备文件来读写,所以这里就不难理解,为什么使用文件函数来处理串口。linux下可以使用标准C库函数来控制读写串口,windows下可以使用WINDOWS API函数来做串口读写,具体请参看《windows API 大全》以及下文给出的参考地址,也是有详细的说明
在PC机上实现COM口通信并不困难,可你得说清楚是什么操作系统,不同的操作系统,控制串口的区别是很大。
在Windows系统上操作串口可以使用三种方式:MSCOMM控件,WINDOWS API,第三方控件
WINDOWS API使用起来相对麻烦些,主要是在设置串口属性、查询读取方面及异常处理方面。这里简要说下控制串口步骤:
1.打开串口:
使用createfile()打开串口,createfile()将返回串口的句柄。
handle createfile(
lpctstr lpfilename, // pointer to name of the file
dword dwdesiredaccess, // access (read-write) mode
dword dwsharemode, // share mode
lpsecurity_attributes lpsecurityattributes, // pointer to security attributes
dword dwcreationdistribution, // how to create
dword dwflagsandattributes, // file attributes
handle htemplatefile // handle to file with attributes to copy
);
lpfilename: 指明串口制备,例:com1,com2
dwdesiredaccess: 指明串口存取方式,例:generic_read|generic_write
dwsharemode: 指明串口共享方式
lpsecurityattributes: 指明串口的安全属性结构,null为缺省安全属性
dwcreateiondistribution: 必须为open_existin
dwflagandattributes: 对串口唯一有意义的是file_flag_overlapped
htemplatefile: 必须为null
2.关闭串口:
closehandle(hcommdev);
3.设置缓冲区长度:
bool setupcomm(
handle hfile, // handle of communications device
dword dwinqueue, // size of input buffer
dword dwoutqueue // size of output buffer
);
4.commprop结构:
可使用getcommproperties()取得commprop结构,commprop结构中记载了系统支持的各项设置。
typedef struct _commprop { // cmmp
word wpacketlength; // packet size, in bytes
word wpacketversion; // packet version
dword dwservicemask; // services implemented
dword dwreserved1; // reserved
dword dwmaxtxqueue; // max tx bufsize, in bytes
dword dwmaxrxqueue; // max rx bufsize, in bytes
dword dwmaxbaud; // max baud rate, in bps
dword dwprovsubtype; // specific provider type
dword dwprovcapabilities; // capabilities supported
dword dwsettableparams; // changeable parameters
dword dwsettablebaud; // allowable baud rates
word wsettabledata; // allowable byte sizes
word wsettablestopparity; // stop bits/parity allowed
dword dwcurrenttxqueue; // tx buffer size, in bytes
dword dwcurrentrxqueue; // rx buffer size, in bytes
dword dwprovspec1; // provider-specific data
dword dwprovspec2; // provider-specific data
wchar wcprovchar[1]; // provider-specific data
} commprop;
dwmaxbaud:
baud_075 75 bps
baud_110 110 bps
baud_134_5 134.5 bps
baud_150 150 bps
baud_300 300 bps
baud_600 600 bps
baud_1200 1200 bps
baud_1800 1800 bps
baud_2400 2400 bps
baud_4800 4800 bps
baud_7200 7200 bps
baud_9600 9600 bps
baud_14400 14400 bps
baud_19200 19200 bps
baud_38400 38400 bps
baud_56k 56k bps
baud_57600 57600 bps
baud_115200 115200 bps
baud_128k 128k bps
baud_user programmable baud rates available
dwprovsubtype:
pst_fax 传真设备
pst_lat lat协议
pst_modem 调制解调器设备
pst_network_bridge 未指定的网桥
pst_parallelport 并口
pst_rs232 rs-232口
pst_rs422 rs-422口
pst_rs423 rs-432口
pst_rs449 rs-449口
pst_scanner 扫描仪设备
pst_tcpip_telnet tcp/ip telnet协议
pst_unspecified 未指定
pst_x25 x.25标准
dwprovcapabilities
pcf_16bitmode 支持特殊的16位模式
pcf_dtrdsr 支持dtr(数据终端就绪)/dsr(数据设备就绪)
pcf_inttimeouts 支持区间超时
pcf_parity_check 支持奇偶校验
pcf_rlsd 支持rlsd(接收线信号检测)
pcf_rtscts 支持rts(请求发送)/cts(清除发送)
pcf_setxchar 支持可设置的xon/xoff
pcf_specialchars 支持特殊字符
pcf_totaltimeouts 支持总(占用时间)超时
pcf_xonxoff 支持xon/xoff流控制
标准rs-232和window支持除pcf_16bitmode和pcf_specialchar外的所有功能
dwsettableparams
sp_baud 可配置波特率
sp_databits 可配置数据位个数
sp_handshaking 可配置握手(流控制)
sp_parity 可配置奇偶校验模式
sp_parity_check 可配置奇偶校验允许/禁止
sp_rlsd 可配置rlsd(接收信号检测)
sp_stopbits 可配置停止位个数
标准rs-232和window支持以上所有功能
wsettabledata
databits_5 5个数据位
databits_6 6个数据位
databits_7 7个数据位
databits_8 8个数据位
databits_16 16个数据位
databits_16x 通过串行硬件线路的特殊宽度路径
windows 95支持16的所有设置
5.dcb结构:
typedef struct _dcb {// dcb
dword dcblength; // sizeof(dcb)
dword baudrate; // current baud rate
指定当前的波特率
dword fbinary: 1; // binary mode, no eof check
指定是否允许二进制模式,
windows 95中必须为true
dword fparity: 1; // enable parity checking
指定奇偶校验是否允许
dword foutxctsflow:1; // cts output flow control
指定cts是否用于检测发送控制。
当为true是cts为off,发送将被挂起。
dword foutxdsrflow:1; // dsr output flow control
指定cts是否用于检测发送控制。
当为true是cts为off,发送将被挂起。
dword fdtrcontrol:2; // dtr flow control type
dtr_control_disable值将dtr置为off, dtr_control_enable值将dtr置为on, dtr_control_handshake允许dtr"握手",dword fdsrsensitivity:1; // dsr sensitivity 当该值为true时dsr为off时接收的字节被忽略
dword ftxcontinueonxoff:1; // xoff continues tx
指定当接收缓冲区已满,并且驱动程序已经发
送出xoffchar字符时发送是否停止。
true时,在接收缓冲区接收到缓冲区已满的字节xofflim且驱动程序已经发送出xoffchar字符中止接收字节之后,发送继续进行。
false时,在接收缓冲区接收到代表缓冲区已空的字节xonchar且驱动程序已经发送出恢复发送的xonchar之后,发送继续进行。
dword foutx: 1; // xon/xoff out flow control
true时,接收到xoffchar之后便停止发送
接收到xonchar之后将重新开始
dword finx: 1; // xon/xoff in flow control
true时,接收缓冲区接收到代表缓冲区满的xofflim之后,xoffchar发送出去
接收缓冲区接收到代表缓冲区空的xonlim之后,xonchar发送出去
dword ferrorchar: 1; // enable error replacement
该值为true且fparity为true时,用errorchar 成员指定的字符代替奇偶校验错误的接收字符
dword fnull: 1; // enable null stripping
true时,接收时去掉空(0值)字节
dword frtscontrol:2; // rts flow control
rts_control_disable时,rts置为off
rts_control_enable时, rts置为on
rts_control_handshake时,
当接收缓冲区小于半满时rts为on
当接收缓冲区超过四分之三满时rts为off
rts_control_toggle时,
当接收缓冲区仍有剩余字节时rts为on ,否则缺省为off
dword fabortonerror:1; // abort reads/writes on error
true时,有错误发生时中止读和写操作
dword fdummy2:17; // reserved
未使用
word wreserved; // not currently used
未使用,必须为0
word xonlim; // transmit xon threshold
指定在xon字符发送这前接收缓冲区中可允许的最小字节数
word xofflim; // transmit xoff threshold
指定在xoff字符发送这前接收缓冲区中可允许的最小字节数
byte bytesize; // number of bits/byte, 4-8
指定端口当前使用的数据位
byte parity; // 0-4=no,odd,even,mark,space
指定端口当前使用的奇偶校验方法,可能为:
evenparity,markparity,noparity,oddparity
byte stopbits; // 0,1,2 = 1, 1.5, 2
指定端口当前使用的停止位数,可能为:
onestopbit,one5stopbits,twostopbits
char xonchar; // tx and rx xon character
指定用于发送和接收字符xon的值
char xoffchar; // tx and rx xoff character
指定用于发送和接收字符xoff值
char errorchar; // error replacement character
本字符用来代替接收到的奇偶校验发生错误时的值
char eofchar; // end of input character
当没有使用二进制模式时,本字符可用来指示数据的结束
char evtchar; // received event character
当接收到此字符时,会产生一个事件
word wreserved1; // reserved; do not use 未使用
} dcb;
6.改变端口设置
使用如下的两个方法
bool getcommstate(hcomm,dcb);
bool setcommstate(hcomm,dcb);
7.改变普通设置
buildcommdcb(szsettings,dcb);
szsettings的格式:baud parity data stop
例: "baud=96 parity=n data=8 stop=1"
简写:"96;,n,8,1"
szsettings 的有效值
baud:
11 or 110 = 110 bps
15 or 150 = 150 bps
30 or 300 = 300 bps
60 or 600 = 600 bps
12 or 1200 = 1200 bps
24 or 2400 = 2400 bps
48 or 4800 = 4800 bps
96 or 9600 = 9600 bps
19 or 19200= 19200bps
parity:
n=none
e=even
o=odd
m=mark
s=space
data:
5,6,7,8
stopbit
1,1.5,2
8.commconfig结构:
typedef struct _comm_config {
dword dwsize;
word wversion;
word wreserved;
dcb dcb;
dword dwprovidersubtype;
dword dwprovideroffset;
dword dwprovidersize;
wchar wcproviderdata[1];
} commconfig, *lpcommconfig;
可方便的使用bool commconfigdialog(
lptstr lpszname,
hwnd hwnd,
lpcommconfig lpcc);
来设置串行口。
9.超时设置:
可通过commtimeouts结构设置超时,
typedef struct _commtimeouts {
dword readintervaltimeout;
原文参考《VC实现串口通信例程》 作者:阮帮秋
下次记得把问题一次提出来。即便是帮你找资料,也方便一些。
基本方法是使用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;
}