串口操作---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;}
- 串口操作---C代码
- Visual C 串口操作
- c语言串口操作
- 串口通讯C代码
- 【C#】串口操作实用类
- 【C#】串口操作实用类
- 【C#】串口操作实用类
- 【C#】串口操作实用类
- 【C#】串口操作实用类
- 【C#】串口操作实用类
- 使用C语言操作串口
- C#---串口通信---位操作
- 【C#】串口操作实用类
- 串口Java/c++/C#代码
- 一个串口操作的C++代码
- Linux串口操作的一段代码
- silverlight 操作串口数据的代码
- windows串口通信操作和代码实现
- Hibernate注解配置 在Spring的配置文件里写法
- 日本语の汉字
- Hibernate 注解单向一对多配置
- 让android程序的屏幕分辨率大小可以支持平板电脑
- 敬语
- 串口操作---C代码
- 北大光华女的超强面经!
- linux网络通信命令集合
- 第3期 2009年6月 湖南人文科技学院学报 Journal of Hunan Institute of Humanities,Science and Technology No.3 Jun.2009
- 在ASP.NET中实现Url Rewriting
- JSP EL表达式<c:forEach> 页面获取hibernate联级对象数据
- sql server Blog
- 报错记录
- 我的2011:个人职业发展的三个里程碑