API函数操作COM口

来源:互联网 发布:java导出excel表格poi 编辑:程序博客网 时间:2024/06/05 16:50


一 summary

在Dos环境下,用户可以直接对通信设备编程,可以通过查询中断的方式使用通信设备。但是Windows不提倡应用程序直接控制硬件,而是通过Windows所提供的设备驱动程序来进行数据传递。

在Windows环境中,通信支持中断功能,当通信设备接收到一个输入字符的时候就产生一个硬件中断,该中断暂停应用程序的执行,并把接收到的字符存入到一个叫接收数据队列的内存缓冲区中。而待发数据也先存入到一个叫发送数据队列的内存缓冲区中,再由Windows系统负责在后台进行发送。因此,在Windows下接收和发送数据的关键就是如何从接收队列取数据和如何向发送数据队列发数据。Windows提供了相应的API函数来实现这些功能。
  
在Win32环境下,把串口看作由文件系统访问的设备。使用标准的CreateFile()函数打开端口,再使用ReadFile()和WriteFile()函数读写数据,就如同端口只是一个文件对象一样。对于串行通信,Win 32提供了相应的文件I/O函数与通信函数,使用这些函数,可以编制出符合不同需要的通信程序。

二 访问串口的步骤:

1 打开串口,取得控制权

2 配置串口

3 传输数据

4 关闭串口


三 代码

void __fastcall TCOMThread::RS232Open(AnsiString PortNo,int BaudRate)
{
    AnsiString InstruStringRS232;

    InstruStringRS232 = "\\\\.\\" + PortNo;
    hComm = CreateFile(InstruStringRS232.c_str(),GENERIC_READ | GENERIC_WRITE,0, NULL, OPEN_EXISTING, 0, 0);
    PurgeComm(hComm,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
    GetCommState(hComm,&dcb);
    dcb.BaudRate = BaudRate;
    dcb.ByteSize = 8;
    dcb.Parity = NOPARITY;
    dcb.StopBits = ONESTOPBIT;
    dcb.fOutxCtsFlow=0;
    dcb.fOutxDsrFlow=0;

    if ( !SetCommState(hComm, &dcb) )
    {
        COMStatus = 0;
        CloseHandle(hComm);
     }
    else
     {
        COMStatus = 1;
     }

}


AnsiString __fastcall TCOMThread::RS232ReadCommand()
{
    char bufferchar[8192]={0};
    AnsiString  ReStr;
    DWORD nBytesRead,dwEvent,dwError;
    COMSTAT cs;

    EscapeCommFunction(hComm,CLRRTS);
    ClearCommError(hComm,&dwError,&cs);
    ReadFile(hComm,bufferchar,cs.cbInQue,&nBytesRead,NULL);

    bufferchar[cs.cbInQue]='\0';
    ReStr = AnsiString(bufferchar);
    return ReStr;
}

void __fastcall TCOMThread::WriteRS232(AnsiString InStr)
{
    //TODO: Add your source code here
    unsigned long lrc,BS;
    String Temp;
    char *SendData;

    Temp=InStr+'\r';
    SendData=Temp.c_str();
    BS=Temp.Length();

    EscapeCommFunction(hComm,SETRTS);
    PurgeComm(hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
    WriteFile(hComm,SendData,BS, &lrc,NULL); // 癳戈
}

void __fastcall TCOMThread::WriteRS232Esc()
{
     //TODO: Add your source code here
     unsigned long lrc,BS;
     char SendData[20];
     SendData[0] = 27;
     SendData[1] = 13;

     BS=2;
     PurgeComm(hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
     WriteFile(hComm,SendData,BS, &lrc,NULL); // 癳戈
}


调用GetCommState函数可以获得串口的配置,该函数把当前配置填充到一个DCB结构中。要修改串口配置,应该先修改串口的DCB结构,然后调用SetCommState函数用指定的DCB结构来设置串口。


在使用ReadFile 函数进行读操作前,应先使用ClearCommError函数清除错误。

在读写串口之前,还要用PurgeComm()函数清空缓冲区,该函数原型:
BOOL PurgeComm( HANDLE hFile, //串口句柄

DWORD dwFlags // 需要完成的操作 );
参数dwFlags指定要完成的操作,可以是下列值的组合:
PURGE_TXABORT 中断所有写操作并立即返回,即使写操作还没有完成。

PURGE_RXABORT 中断所有读操作并立即返回,即使读操作还没有完成。

PURGE_TXCLEAR 清除输出缓冲区

PURGE_RXCLEAR 清除输入缓冲区


ReadFile和WriteFile函数是同步还是异步由CreateFile函数决定,如果在调用CreateFile创建句柄时指定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile和WriteFile对该句柄进行的操作就应该是重叠的;如果未指定重叠标志,则读写操作应该是同步的。


当ReadFile和WriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果。