串口操作---C代码

来源:互联网 发布:软件项目管理 编辑:程序博客网 时间:2024/05/21 21:36

com.h

#ifndef __COM_H__#define __COM_H__#ifdef __cplusplusextern "C" {#endif //打开串口int OpenComPort(int port, int userBaudRate);//打开串口//关闭串口void CloseComPort(void);//关闭串口int ReadComBlock(unsigned char *buf,int maxLen);void _DoRxTx(void *args);int ReadComBuf(unsigned char *buf, int maxLen);//读串口int WriteComBuf(unsigned char *buf, int maxLen);//写串口int WriteComByte(unsigned char byte);//往串口写一个字节int ReadComByte(unsigned char byte);//从串口读取一个字节void resetComPort(void);//重置串口void resetRTS(void);//resetRTS_sub(150,20);int ReceiveMessage(unsigned char *pBuf, int maxlen, int time);//带时间的接收操作void resetRTSLowHigh(int Low,int High);//CTS高低电平操作void SetRTSControlEnable(bool enable);//CTS操作:enable=true:上拉,false:下拉#ifdef __cplusplus}#endif #endif

com.c:

/******************************************************************************** FileName    :com.cpp* Author        :   * Description   :   * Create Data   :   2005-6-28 9:09* modify History:   *******************************************************************************///#include <windowsx.h>//#include <commctrl.h>//#include <tchar.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#include "com.h"//#include "common.h"//#include "Debug.h"#include <windows.h>#include <process.h>#define DelayXmsSleep//#define EB_PrintfDebug_Printf#define COM_OVERTIME5// 此延时控制Uart_ReadBuf中每次读串口的延时:步长为10ms#define IS_OVERLAPPED_IO    (TRUE)#define MAX_BLOCK_SIZE (0x20000)   // 缓冲区最大128Kbytes#define MAX_Uart_SIZE (4096)   // 缓冲区最大128KbytesHANDLE idComDev;OVERLAPPED osWrite,osRead;volatile int isConnected=FALSE;volatile int txEmpty=TRUE;unsigned char rxBuf[MAX_Uart_SIZE+1];unsigned char RoundBuf[MAX_BLOCK_SIZE];struct {intEnable;// 允许接收int Ok;// 接收成功intOff1;// 缓冲区当前有效数据 开始偏移intOff2;// 缓冲区当前有效数据 末尾偏移unsigned intCnt;// 缓冲区当前有效数据 计数器=Off2-Off1}rxFlag;//打开串口int OpenComPort(int port, int userBaudRate)//port=0,1,2,3{    //TCHAR *textCom[]={TEXT("COM1"),TEXT("COM2"),TEXT("COM3"),TEXT("COM4"),TEXT("COM5"),TEXT("COM6"),TEXT("COM7"),TEXT("COM8"),TEXT("COM9"),TEXT("\\\\.\\COM10"),TEXT("\\\\.\\COM11"),TEXT("\\\\.\\COM12")};    TCHAR textCom[255][14];    int i;     DCB dcb;    COMMTIMEOUTS commTimeOuts;        for(i=0;i<255;i++)    {swprintf(textCom[i],14,L"\\\\.\\COM%d",i);}    if(isConnected)// 若重复打开时先关闭    {CloseComPort();/*Debug_Printf("\n[OK:Already Opened. Close first!]");*/    }//====================================================    osRead.Offset=0;    osRead.OffsetHigh=0;    osWrite.Offset=0;    osWrite.OffsetHigh=0;    osRead.hEvent = CreateEvent(NULL,TRUE/*bManualReset*/,FALSE,NULL);//manual reset event object should be used. //So, system can make the event objecte nonsignalled.//osRead.hEvent & osWrite.hEvent may be used to check the completion of // WriteFile() & ReadFile(). But, the DNW doesn't use this feature.    if(osRead.hEvent==NULL)    {/*Debug_Printf("\n[ERROR:CreateEvent for osRead.]");*/return FALSE;    }    osWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);    if(osWrite.hEvent==NULL)    {/*Debug_Printf("\n[ERROR:CreateEvent for osWrite.]");*/return FALSE;    }    //====================================================    idComDev=CreateFile(textCom[port],GENERIC_READ|GENERIC_WRITE,0, //exclusive access/*FILE_SHARE_READ|FILE_SHARE_WRITE,*/ NULL,OPEN_EXISTING,#if IS_OVERLAPPED_IOFILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,#else/*FILE_ATTRIBUTE_NORMAL,*/ 0,#endifNULL);    if(idComDev==INVALID_HANDLE_VALUE)    {/*Debug_Printf("\n[ERROR:CreateFile for opening COM port.]" );*/return FALSE;    }    SetCommMask(idComDev,EV_RXCHAR);    SetupComm(idComDev,MAX_Uart_SIZE,MAX_Uart_SIZE);    PurgeComm(idComDev,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);        commTimeOuts.ReadIntervalTimeout=0xffffffff;    commTimeOuts.ReadTotalTimeoutMultiplier=0;    commTimeOuts.ReadTotalTimeoutConstant=1000;    commTimeOuts.WriteTotalTimeoutMultiplier=0;    commTimeOuts.WriteTotalTimeoutConstant=1000;    SetCommTimeouts(idComDev,&commTimeOuts);//====================================================    dcb.DCBlength=sizeof(DCB);    GetCommState(idComDev,&dcb);    dcb.fBinary=TRUE;    dcb.fParity=FALSE;    dcb.BaudRate=userBaudRate; //CBR_115200;    dcb.ByteSize=8;    dcb.Parity=0;    dcb.StopBits=0;    dcb.fDtrControl=DTR_CONTROL_ENABLE;//DTR_CONTROL_DISABLE;    //2009-9-4 9:36:26   zzt    dcb.fRtsControl=RTS_CONTROL_DISABLE;    dcb.fOutxCtsFlow=0;    dcb.fOutxDsrFlow=0;        if(SetCommState(idComDev,&dcb)==TRUE)    {isConnected=TRUE;_beginthread( (void (*)(void *))_DoRxTx,0x2000,(void *)0);rxFlag.Off1=0;rxFlag.Off2=0;rxFlag.Cnt=0;rxFlag.Enable=1;// 允许串口接收/*Debug_Printf("\n[OK:OpenComPort port=%d baud=%d.]", port, userBaudRate);*/return TRUE;    }    else    {isConnected=FALSE;CloseHandle(idComDev);return FALSE;    }}void resetComPort(void){    rxFlag.Off1=0;    rxFlag.Off2=0;    rxFlag.Cnt=0;    rxFlag.Enable=1;// 允许串口接收    rxFlag.Ok=0;// 允许串口接收    }   static void resetRTS_sub(int Low,int High){DCB dcb;   //====================================================    dcb.DCBlength=sizeof(DCB);        GetCommState(idComDev,&dcb);    dcb.fRtsControl=RTS_CONTROL_ENABLE;    SetCommState(idComDev,&dcb);    DelayXms(Low);    GetCommState(idComDev,&dcb);    dcb.fRtsControl=RTS_CONTROL_DISABLE;    SetCommState(idComDev,&dcb);DelayXms(High); }void SetRTSControlEnable(bool enable){DCB dcb;dcb.DCBlength=sizeof(DCB);GetCommState(idComDev,&dcb);if(true ==enable){ dcb.fRtsControl=RTS_CONTROL_ENABLE;}else{dcb.fRtsControl=RTS_CONTROL_DISABLE;}SetCommState(idComDev,&dcb);}void resetRTS(void){resetRTS_sub(150,20);}void resetRTSLowHigh(int Low,int High){return resetRTS_sub(Low,High);}//关闭串口void CloseComPort(void){    if(isConnected)    {isConnected=FALSE;SetCommMask(idComDev,0);//disable event notification and wait for thread to haltEscapeCommFunction(idComDev,CLRDTR);PurgeComm(idComDev,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);CloseHandle(idComDev);        CloseHandle(osRead.hEvent);CloseHandle(osWrite.hEvent);    }        Sleep(100);     //wait until CloseComPort() effective.    //If not, OpenComPort()::CreateFile(...) will fail.}//读取串口块int ReadComBlock(unsigned char *buf,int maxLen){    BOOL fReadStat;    COMSTAT comStat;    DWORD dwErrorFlags;    DWORD dwLength;    ClearCommError(idComDev,&dwErrorFlags,&comStat);    dwLength=min((DWORD)maxLen,comStat.cbInQue);    if(dwLength>0)    {#if IS_OVERLAPPED_IOfReadStat=ReadFile(idComDev,buf,dwLength,&dwLength,&osRead);if(!fReadStat)   //Apr.28.2003:GetOverlappedResult() may be needed.{//By experiment, fReadStat was always TRUE,of course, and the following was never executed./*Debug_Printf("\n[RX_RD_WAIT]\n" ); */if(GetLastError()==ERROR_IO_PENDING){GetOverlappedResult(idComDev,&osRead,&dwLength,TRUE); }else{/*Debug_Printf("[RXERR]" );*/}}#elsefReadStat=ReadFile(idComDev,buf,dwLength,&dwLength,NULL);if(!fReadStat){Debug_Printf("[RXERR]" );}#endif    }    return dwLength;}void _DoRxTx(void *args){    OVERLAPPED os;    DWORD dwEvtMask;    int nLength;    BOOL fStat;    DWORD temp;        int i;    memset(&os,0,sizeof(OVERLAPPED));    os.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);    if(os.hEvent==NULL)    {/*EB_Printf("[ERROR:DoRxTx os.hEvent]\n");*/_endthread();    }    if(!SetCommMask(idComDev,EV_RXCHAR|EV_TXEMPTY|EV_ERR))    {/*EB_Printf("[ERROR:SetCommMask()]\n");*/CloseHandle(os.hEvent);_endthread();    }    while(isConnected)    {dwEvtMask=0;#if IS_OVERLAPPED_IOfStat=WaitCommEvent(idComDev,&dwEvtMask,&os);   //Apr.28.2003: fStat should be checked for the cpu time saving. if(!fStat)   //Apr.28.2003:GetOverlappedResult() is needed.  {//By experiment. Only when there was no signalled event, the following was executed.//EB_Printf("\n[WaitCommEvent=false]\n"); if(GetLastError()==ERROR_IO_PENDING){GetOverlappedResult(idComDev,&os,&temp,TRUE); }else{/*EB_Printf("[RXTX_THREAD_ERR]" );*/}}#elseWaitCommEvent(idComDev,&dwEvtMask,NULL);  //wait until any event is occurred.#endifif( (dwEvtMask & EV_TXEMPTY) == EV_TXEMPTY )txEmpty=TRUE;if((dwEvtMask & EV_RXCHAR) == EV_RXCHAR){if(rxFlag.Enable) {do{   //Apr.28.2003:The caveat on MSDN,"Serial Communications in Win32" recommends while();if( nLength=ReadComBlock(rxBuf,MAX_Uart_SIZE) ){//    if(nLength>=MAX_BLOCK_SIZE /*for debug*/)//    {//EB_Printf("\n[ERROR1:nLength>MAX]\n");//                rxFlag.Off1=0;//                rxFlag.Off2=0;//                rxFlag.Cnt=0;//    }//    else{rxFlag.Ok=0;for(i=0; i<nLength; i++){if(rxFlag.Cnt >= MAX_BLOCK_SIZE) {/*EB_Printf("\n[ERROR2:nLength>MAX]\n");*/rxFlag.Off1=0;rxFlag.Off2=0;rxFlag.Cnt=0;}rxFlag.Cnt++;RoundBuf[rxFlag.Off2++] = rxBuf[i];rxFlag.Off2 %= MAX_BLOCK_SIZE;}rxFlag.Ok=1;}}}while(nLength);  }}// Clear OVERRUN condition.// If OVERRUN error is occurred,the tx/rx will be locked.if(dwEvtMask & EV_ERR){COMSTAT comStat;DWORD dwErrorFlags;ClearCommError(idComDev,&dwErrorFlags,&comStat);//EB_Printf("[DBG:EV_ERR=%x]\n",dwErrorFlags);}    }    CloseHandle(os.hEvent);    _endthread();}//读取串口缓冲区int ReadComBuf(unsigned char *buf, int maxLen){unsigned int time=0;unsigned int i, len;if(!rxFlag.Enable)return 0;while(rxFlag.Cnt < (unsigned int)maxLen){//delay 50msSleep(10);if( time++ >= COM_OVERTIME )break;}if(0==rxFlag.Ok)return 0;len =(rxFlag.Cnt > (unsigned int)maxLen)? maxLen:rxFlag.Cnt;for(i=0; i<len; i++){*(buf+i)= RoundBuf[rxFlag.Off1++];rxFlag.Cnt--;rxFlag.Off1 %= MAX_BLOCK_SIZE;}return len;}//写串口缓冲区int WriteComBuf(unsigned char *buf, int maxLen){    void *txBlk;    DWORD txBlkSize;    DWORD temp;    while(txEmpty==FALSE);    txBlk=buf;    txBlkSize=maxLen;    //Debug_Printf("[OK:WriteComBuf len=%d.]\n", maxLen);//for(temp=0; temp<maxLen; temp++) {//Debug_Printf(" %02x", *(buf+temp));//}    //txEmpty=FALSE; why needed??? this line should be removed.#if IS_OVERLAPPED_IO    WriteFile(idComDev,txBlk,txBlkSize,&temp,&osWrite);#else    WriteFile(idComDev,txBlk,txBlkSize,&temp,NULL);#endif    while(txEmpty==FALSE);    return TRUE;}//往串口写一个字节int WriteComByte(unsigned char byte){return WriteComBuf(&byte, 1);}//从串口读取一个字节int ReadComByte(unsigned char byte){return ReadComBuf(&byte, 1);}/******************************************************************************** Fuc Name      :   PC_DelayXms* Input         :   num--延时的毫秒数* Return        :   void* Description   :   PC延时程序,毫秒级*******************************************************************************/#include <sys/timeb.h>#include <time.h>void PC_DelayXms(int num){LARGE_INTEGER  litmp; LONGLONG       QPart1,QPart2;double         dfMinus, dfFreq, dfTim; QueryPerformanceFrequency(&litmp); dfFreq = (double)litmp.QuadPart; // 获得计数器的时钟频率QueryPerformanceCounter(&litmp); QPart1 = litmp.QuadPart; // 获得初始值do{QueryPerformanceCounter(&litmp); QPart2 = litmp.QuadPart;// 获得中止值 dfMinus = (double)(QPart2-QPart1); dfTim = dfMinus / dfFreq; // 获得对应的时间值,单位为秒    }while(dfTim<(0.001*num));}int ReceiveMessage(unsigned char *pBuf, int maxlen, int time){int ret =0;DWORD  startTime;int nLen;startTime=GetTickCount();int len =0;while(1){//timeoutif(GetTickCount() -startTime >time)return 0;len =ReadComBuf(pBuf,maxlen-1);if(len){*(pBuf +len) ='\0';return len;}else{Sleep(1);}}return 0;}



原创粉丝点击