2010年8月30日星期一

串口通讯

WIN95界面下的VC++串口通讯程序在WIN32下是不建议对端口进行操作的,在WIN32中所有的设备都被看成是文件,串行口也不例外也是作为文件来进行处理的。这是我的一份关于串口编程的读书笔记,对于使 用VC进行编程的同行应该有一定的帮助。

1.打开串口:

  在Window 95下串行口作为文件处理,使用文件操作对串行口进行处理。使用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;
  DWORD ReadTotalTimeoutMultiplier;
  DWORD ReadTotalTimeoutConstant;
  DWORD WriteTotalTimeoutMultiplier;
  DWORD WriteTotalTimeoutConstant;
  } COMMTIMEOUTS,*LPCOMMTIMEOUTS;
  区间超时:(仅对从端口中读取数据有用)它指定在读取两个字符之间要经历的时间
  总超时: 当读或写特定的字节数需要的总时间超过某一阈值时,超时触发.
  超时公式:
  ReadTotalTimeout = (ReadTotalTimeoutMultiplier * bytes_to_read)
  + ReadToTaltimeoutConstant
  WriteTotalTimeout = (WriteTotalTimeoutMuliplier * bytes_to_write)
  + WritetoTotalTimeoutConstant
  NOTE:在设置超时时参数0为无限等待,既无超时
  参数MAXDWORD为立即返回
  超时设置:
  GetCommTimeouts(hComm,&timeouts);
  SetCommTimeouts(hComm,&timeouts);

10.查询方式读写数据

 
 例程:
  COMMTIMEOUTS to;
  DWORD ReadThread(LPDWORD lpdwParam)
  {
  BYTE inbuff[100];
  DWORD nBytesRead;
  if(!(cp.dwProvCapabilities&PCF_INTTIMEOUTS))
  return 1L;
  memset(&to,0,sizeof(to));
  to.ReadIntervalTimeout = MAXDWORD;
  SetCommTimeouts(hComm,&to);
  while(bReading)
  {
  if(!ReadFile(hComm,inbuff,100,&nBytesRead,NULL))
  locProcessCommError(GetLastError());
  else
  if(nBytesRead)
  locProcessBytes(inbuff,nBytesRead);
  }
  PurgeComm(hComm,PURGE_RXCLEAR);
  return 0L;
  }
  NOTE:
  PurgeComm()是一个清除函数,它可以中止任何未决的后台读或写,并且可以冲掉I/O缓冲区.
  BOOL PurgeComm(HANDLE hFile,DWORD dwFlags);
  dwFlages的有效值:
  PURGE_TXABORT: 中止后台写操作
  PRUGE_RXABORT: 中止后台读操作
  PRUGE_TXCLEAR: 清除发送缓冲区
  PRUGE_RXCLEAR: 清除接收缓冲区
  技巧:
  可通过ClearCommError()来确定接收缓区中处于等待的字节数。
  BOOL ClearCommError(
  HANDLE hFile, // handle to communications device
  LPDWORD lpErrors, // pointer to variable to receive error codes
  LPCOMSTAT lpStat // pointer to buffer for communications status
  );
  ClearCommError()将返回一个COMSTAT结构:
  typedef struct _COMSTAT { // cst
  DWORD fCtsHold : 1; // Tx waiting for CTS signal
  DWORD fDsrHold : 1; // Tx waiting for DSR signal
  DWORD fRlsdHold : 1; // Tx waiting for RLSD signal
  DWORD fXoffHold : 1; // Tx waiting, XOFF char rec`d
  DWORD fXoffSent : 1; // Tx waiting, XOFF char sent
  DWORD fEof : 1; // EOF character sent
  DWORD fTxim : 1; // character waiting for Tx
  DWORD fReserved : 25; // reserved
  DWORD cbInQue; // bytes in input buffer
  DWORD cbOutQue; // bytes in output buffer
  } COMSTAT, *LPCOMSTAT;
  其中的cbInQue和cbOutQue中即为缓冲区字节。

11.同步I/O读写数据

  COMMTIOMOUTS to;
  DWORD ReadThread(LPDWORD lpdwParam)
  {
  BYTE inbuff[100];
  DWORD nByteRead,dwErrorMask,nToRead;
  COMSTAT comstat;
  if(!cp.dwProvCapabilities&PCF_TOTALTIMEOUTS)
  return 1L;
  memset(&to,0,sizeof(to));
  to.ReadTotalTimeoutMultiplier = 5;
  to.ReadTotalTimeoutConstant = 50;
  SetCommTimeouts(hComm,&to);
  while(bReading)
  {
  ClearCommError(hComm,&dwErrorMask,&comstat);
  if(dwErrorMask)
  locProcessCommError(dwErrorMask);
  if(comstat.cbInQue >100)
  nToRead = 100;
  else
  nToRead = comstat.cbInQue;
  if(nToRead == 0)
  continue;
  if(!ReadFile(hComm,inbuff,nToRead,&nBytesRead,NULL))
  locProcessCommError(GetLastError());
  else
  if(nBytesRead)
  locProcessBytes(inbuff,nBytesRead);
  }
  return 0L;
  }

12.异步I/O读写数据

  当CreateFile()中的fdwAttrsAndFlags参数为FILE_FLAG_OVERLAPPEN时, 端口是为异步I/O打开的,此时可以在ReadFile的最后一个参数中指定一个OVERLAPPED结构,使数据的读操作在后台进行。WINDOWS 95包括了异步I/O的许多变种。
  typedef struct _OVERLAPPED {
  DWORD Internal;
  DWORD InternalHigh;
  DWORD Offset;
  DWORD OffsetHigh;
  HANDLE hEvent;
  } OVERLAPPED;
  对于串行口仅hEvent成员有效,其于成员必须为0。
  例程:
  COMMTIMEOUTS to;
  ...
  DWORD ReadThread((LPDWORD lpdwParam)
  {
  BYTE inbuff[100];
  DWORD nRytesRead,endtime,lrc;
  static OVERLAPPED o;
  if(!cp.dwProvCapabilities & PCF_TOTALTIMEOUTS)
  return 1L;
  memset(&to,0,sizeof(to));
  to.ReadTotalTimeoutMultiplier = 5;
  to.ReadTotalTimeoutConstant = 1000;
  SetCommTimeouts(hComm,&to);
  o.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  while(bReading)
  {
  if(!ReadFile(hComm,inbuff,10,&nBytesRead,&o))
  {
  nBytesRead = 0;
  if(lrc=GetLastError() == ERROR_IO_PENDING)
  {
  endtime = GetTickCount() + 1000;
  while(!GetOverlappedResult(hComm,&o,&nBytesRead,FALSE))
  if(GetTickCount() > endtime) break;
  }
  if(nBytesRead) locProcessBytes(inbuff,nBytesRead);
  }
  else
  {
  if(nBytesRead) locProcessBytes(inbuff,nBytesRead);
  ResetEvent(o.hEvent);
  }
  }
  PurgeComm(hComm,PURGE_RXCLEAR);
  return 0L;
  }
  这一例程是对一开始读缓冲区就读到所需的字节时的处理:
  while(bReading)
  {
  if(!ReadFile(hComm,inbuff,10,&nBytesRead,&o))
  {
  if((lrc=GetLastError()) ==ERROR_IO_PENDING)
  {
  if(GetOverlappedResult(hComm,&o,&nBytesRead,TRUE))
  {
  if(nBytesRead)
  locProcessBytesa(inbuff,nBytesRead);
  }
  else
  locProcessCommError(GetLastError());
  }
  else
  locProcessCommError(GetLastError));
  }
  else
  if(nBytesRead) locProcessBytes(inbuff,nBytesRead);
  ResetEvent(o.hEvent);
  }

13.事件驱I/O读写:

  GetCommMask(hComm,&dwMask)
  Windows 95报告给应用程序的事件由此方法返回。
  SetCommMasl(hComm,&dwMask)
  添加或修改Windows 95所报告的事件列表。
  事件掩码如下:
  EV_BREAK 检测到输入为止
  EV_CTS CTS(清除发送)信号改变状态
  EV_DSR DSR(数据设置就绪)信号改变状态
  EV_ERR 发生了线路状态错误.
  线路状态错误为:
  CE_FRAME(帧错误)
  CE_OVERRUN(接收缓冲区超限)
  CE_RXPARITY(奇偶校验错误)
  EV_RING 检测到振铃
  EV_RLSD RLSD(接收线路信号检测)信号改变状态
  EV_EXCHAR 接收到一个字符,并放入输入缓冲区
  EV_RXFLAG 接收到事件字符(DCB成员的EvtChar成员),度放入输入缓冲区
  EV_TXEMPTY 输出缓冲区中最后一个字符发送出去
  在用SetCommMask指定了有用的事件后,应用程序可调用WaitCommEvent()来等待事件发生.
  BOOL WaitCommEvent(
  HANDLE hFile, // handle of communications device
  LPDWORD lpEvtMask, // address of variable for event that occurred
  LPOVERLAPPED lpOverlapped, // address of overlapped structure
  );
  此方法可以以同步或异步方式操作
  例程:
  COMMTIMEOUTS to;
  ...
  DWORD ReadTherad(LPDWORD lpdwParam)
  {
  BYTE binbuff[100];
  DWORD nBytesRead,dwEvent,dwError;
  COMSTAT cs;
  SetCommMask(hComm,EV_RXHAR);
  while(bReading)
  {
  if(WaitCommEvent(hComm,&dwEvent,NULL))
  {
  ClearCommError(hComm,&dwError,&cs);
  if((dwEvent&EV_RXCHAR)&&cs.cbInQue)
  {
  if(!ReadFile(hComm,inbuff,cs.cbInQue,&nBytesRead,NULL)
  locProcessCommError(GetLastError());
  }
  else
  {
  if(nByteRead)
  locProcessBytes(inbuff,nBytesRead);
  }
  else
  locProcessCommError(GetLastError());
  }
  PurgeComm(hComm,PURGE_RXCLEAR);
  return 0L;
  }
  NOTE: SetCommMask(hComm,0)可使WaitCommEvent()中止.
  可使用GetCommmodemStatus()方法,例程:
  if(cp.dwProvCapabilities&PCF_RTSCTS)
  {
  SetCommMask(hComm,EV_CTS);
  WaitCommEvent(hComm,&dwMask,NULL);
  if(dwMask&EV_CTS)
  {
  GetCommModemStatus(hComm,&dwStatus)
  if(dwStatus&MS_CTS_ON) /* CTS stransition OFF-ON */
  else /* CTS stransition ON-OFF */
  }
  }
  MS_CTS_ON CTS为ON
  MS_DSR_ON DSR为ON
  MS_RING_ON RING为ON
  MS_ELSD_ON RLSD为ON

14.错误

  当发生错误时应用方法ClearCommError(hComm,&dwErrorMask,&constat)得到错误掩码。
  CE_BREAK 中止条件
  CE_FRAME 帧错误
  CW_IOE 一般I/O错误,常伴有更为详细的错误标志
  CE_MODE 不支持请求的模式
  CE_OVERRUN 缓冲区超限下一个字符将丢失
  CE_RXOVER 接收缓冲区超限
  CE_RXPARITY 奇偶校验错误
  CE_TXFULL 发送缓冲区满
  CE_DNS 没有选择并行设备
  CE_PTO 并行设备发生超时
  CE_OOP 并行设备缺纸

15.控制命令

  EscapeCommFunction()可将硬件信号置ON或OFF,模拟XON或XOFF

  BOOL EscapeCommFunction(
  HANDLE hFile, // handle to communications device
  DWORD dwFunc // extended function to perform
  );
  dwFunc的有效值(可用'|'同时使用多个值)
  CLRDTR DTR置OFF
  CLRRTS RTS置OFF
  SETDTR STR置ON
  SETRTS TRS置ON
  SETXOFF 模拟XOFF字符的接收
  SETXON 模拟XON字符的接收
  SETBREAK 在发送中产生一个中止
  CLRBREAK 在发送中清除中止

串口通讯

在VC++中有两种方法可以进行串口通讯。一种是利用Microsoft公司提供的ActiveX控件 Microsoft Communications Control。另一种是直接用VC++访问串口。下面将简述这两种方法。

  一、Microsoft Communications Control

  Microsoft公司在WINDOWS中提供了一个串口通讯控件,用它,我们可以很简单的利用串口进行通讯。在使用它之前,应将控件加在应用程序的对话框上。然后再用ClassWizard 生成相应的对象。现在我们可以使用它了。

  该控件有很多自己的属性,你可以通过它的属性窗口来设置,也可以用程序设置。我推荐用程序设置,这样更灵活。

   SetCommPort:指定使用的串口。

   GetCommPort:得到当前使用的串口。

   SetSettings:指定串口的参数。一般设为默认参数"9600,N,8,1"。这样方便与其他串口进行通讯。

   GetSettings:取得串口参数。

   SetPortOpen:打开或关闭串口,当一个程序打开串口时,另外的程序将无法使用该串口。

   GetPortOpen:取得串口状态。

   GetInBufferCount:输入缓冲区中接受到的字符数。

   SetInPutLen:一次读取输入缓冲区的字符数。设置为0时,程序将读取缓冲区的全部字符。

   GetInPut:读取输入缓冲区。

   GetOutBufferCount:输出缓冲区中待发送的字符数。

   SetOutPut:写入输出缓冲区。

  一般而言,使用上述函数和属性就可以进行串口通讯了。以下是一个范例。

#define MESSAGELENGTH 100

class CMyDialog : public CDialog
{
protected:
VARIANT InBuffer;
VARIANT OutBuffer;
CMSComm m_Com;
public:
......
}

BOOL CMyDiaLog::OnInitDialog()
{
CDialog::OnInitDialog();
m_Com.SetCommPort(1);
if (!m_Com.GetPortOpen()) {
m_Com.SetSettings("57600,N,8,1");
m_Com.SetPortOpen(true);
m_Com.SetInBufferCount(0);
SetTimer(1,10,NULL);
InBuffer.bstrVal=new unsigned short[MESSAGELENGTH];
OutBuffer.bstrVal=new unsigned short[MESSAGELENGTH];
OutBuffer.vt=VT_BSTR;
}
return true;
}

void CMyDiaLog::OnTimer(UINT nIDEvent)
{
if (m_Com.GetInBufferCount()>=MESSAGELENGTH) {
InBuffer=m_Com.GetInput();
// handle the InBuffer.
// Fill the OutBuffer.
m_Com.SetOutput(OutBuffer);
}
CDialog::OnTimer(nIDEvent);
}



  用该控件传输的数据是UNICODE格式。关于UNICODE和ANSI的关系和转换请参看MSDN。

  关于该控件的其他详细资料请查看MSDN关于COMM CONTROL部分。

  二、直接用VC++访问串口。

  在VC++中,串口和磁盘文件可以统一的方式来简单读写。这两者几乎没有什么不同,只是在WINDOWS 9X下磁盘文件只能做同步访问,而串口只能做异步访问。

  CreateFile:用指定的方式打开指定的串口。通常的方式为

  m_hCom = CreateFile( "COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );

  m_hCom为文件句柄。GENERIC_READ | GENERIC_WRITE指定可以对串口进行读写操作。第三个参数0表示串口为独占打开。OPEN_EXISTING表示当指定串口不存在时,程序将返回失败。 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED则表示文件属性。当打开串口时,必须指定 FILE_FLAG_OVERLAPPED,它表示文件或设备不会维护访问指针,则在读写时,必须使用OVERLAPPED 结构指定访问的文件偏移量。

   ReadFile:读取串口数据。

   WriteFile:向串口写数据。

   CloseHandle:关闭串口。

  COMMTIMEOUTS:COMMTIMEOUTS主要用于串口超时参数设置。COMMTIMEOUTS结构如下:

typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout;
DWORD ReadTotalTimeoutMultiplier;
DWORD ReadTotalTimeoutConstant;
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutConstant;
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;


  ReadIntervalTimeout:两字符之间最大的延时,当读取串口数据时,一旦两个字符传输的时间差超过该时间,读取函数将返回现有的数据。设置为0表示该参数不起作用。

  ReadTotalTimeoutMultiplier:读取每字符间的超时。

  ReadTotalTimeoutConstant:一次读取串口数据的固定超时。所以在一次读取串口的操作中,其超时为ReadTotalTimeoutMultiplier乘以读取的字节数再加上 ReadTotalTimeoutConstant。将ReadIntervalTimeout设置为MAXDWORD,并将ReadTotalTimeoutMultiplier 和ReadTotalTimeoutConstant设置为0,表示读取操作将立即返回存放在输入缓冲区的字符。

  WriteTotalTimeoutMultiplier:写入每字符间的超时。

  WriteTotalTimeoutConstant:一次写入串口数据的固定超时。所以在一次写入串口的操作中,其超时为WriteTotalTimeoutMultiplier乘以写入的字节数再加上 WriteTotalTimeoutConstant。

  SetCommTimeouts函数可以设置某设备句柄的超时参数,要得到某设备句柄的超时参数可以用GetCommTimeouts函数。

  DCB:DCB结构主要用于串口参数设置。该结构太庞大,这里就不一一讲述了,有兴趣者可查看MSDN关于DCB的描述。其中下面两个是比较重要的属性。

  BaudRate:串口的通讯速度。一般设置为9600。

  ByteSize:字节位数。一般设置为8。

  DCB结构可以用SetCommState函数来设置,并可以用GetCommState来得到现有串口的属性。

  SetupComm:设置串口输入、输出缓冲区。

  OVERLAPPED:保存串口异步通讯的信息。具体结构如下:

typedef struct _OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED;


  Internal,InternalHigh是保留给系统使用的,用户不需要设置。

  Offset,OffsetHigh是读写串口的偏移量,一般设置OffsetHigh为NULL,可以支持2GB数据。

  hEvent读写事件,因为串口是异步通讯,操作可能被其他进程堵塞,程序可以通过检查该时间来得知是否读写完毕。事件将在读写完成后,自动设置为有效。

  通过以上这些函数和结构,我们就可以通过串口进行通讯了,现在我们具体看下面的实例:

BOOL CSerial::Open( int nPort, int nBaud )
{
if( m_bOpened ) return( TRUE );

char szPort[15];
DCB dcb;

wsprintf( szPort, "COM%d", nPort );
m_hComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if( m_hComDev == NULL ) return( FALSE );

memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );

COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts( m_hComDev, &CommTimeOuts );

m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );

dcb.DCBlength = sizeof( DCB );
GetCommState( m_hComDev, &dcb );
dcb.BaudRate = nBaud;
dcb.ByteSize = 8;
if( !SetCommState( m_hComDev, &dcb ) ||
!SetupComm( m_hComDev, 10000, 10000 ) ||
m_OverlappedRead.hEvent == NULL ||
m_OverlappedWrite.hEvent == NULL ){
DWORD dwError = GetLastError();
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hComDev );
return FALSE;
}

m_bOpened = TRUE;

return m_bOpened;

}

int CSerial::InBufferCount( void )
{

if( !m_bOpened || m_hComDev == NULL ) return( 0 );

DWORD dwErrorFlags;
COMSTAT ComStat;

ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );

return (int)ComStat.cbInQue;

}

DWORD CSerial::ReadData( void *buffer, DWORD dwBytesRead)
{

if( !m_bOpened || m_hComDev == NULL ) return 0;

BOOL bReadStatus;
DWORD dwErrorFlags;
COMSTAT ComStat;

ClearCommError( m_hComDev, &dwErrorFlags, &ComStat );
if( !ComStat.cbInQue ) return 0;

dwBytesRead = min(dwBytesRead,(DWORD) ComStat.cbInQue);

bReadStatus = ReadFile( m_hComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus ){
if( GetLastError() == ERROR_IO_PENDING ){
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
return dwBytesRead;
}
return 0;
}

return dwBytesRead;

}

DWORD CSerial::SendData( const char *buffer, DWORD dwBytesWritten)
{

if( !m_bOpened || m_hComDev == NULL ) return( 0 );

BOOL bWriteStat;

bWriteStat = WriteFile( m_hComDev, buffer, dwBytesWritten, &dwBytesWritten, &m_OverlappedWrite );
if( !bWriteStat){
if ( GetLastError() == ERROR_IO_PENDING ) {
WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 );
return dwBytesWritten;
}
return 0;
}
return dwBytesWritten;

}

笑话-6Park

1.装修房子,施工队太不负责,于是男友跟他们吵起来,我见状赶忙跑过来劝架。
男友:正好你来了,快靠墙站直喽——看见了吗,这才叫平!你那墙上贴的砖也敢叫平?!!
施工队:……

3.办公室里,导师咆哮道:“现在的大学生也太没素质了,上我电脑里拷毛片居然用剪切!!!”


8.GG(紧张地):你对俺们寝室老大有感觉吗?
mm(局促地):没有……
GG:那……你对老二有感觉吗?
mm
:这个…是有…还是没有啊?
GG
:这有没有你自己心里还不清楚嘛?
mm
:哦~那没有!
GG
(长长地舒了一口气):那你对我有感觉吗?
mm
:没有!
GG:这个……可以有~
mm:这个——真没有!

15.一mm大清早4、5点钟就出去锻炼,那时天刚蒙蒙亮,四处还静悄悄……
突然,对面跑来一壮男,见到mm就凶巴巴地问:“站住!干嘛去?”
要不说清华学生脑子快呢~mm怕是遇到歹人,不想被劫财,遂可怜巴巴道:“去借钱……”
“借钱去干嘛?”壮男依然凶巴巴地问。
mm
又怕被劫色,曰:“得了性病没钱治……”

18.老三和新交的女友开房回来对老二炫耀道:“我马子比你马子至少漂亮20倍!”
老二反击道:“漂亮能顶饭吃啊?你那中专学历的骚货能跟我研究生出身的才女比吗?”
这时一旁的老大慢悠悠地转过头来一脸茫然道:“那又怎样,难道你日她的大脑吗?”


25.QQ上,MM发来消息:给我举几个大器晚成的例子,我论文要用!
偶:黄忠六十跟刘备,德川家康七十打天下,姜子牙八十为丞相,佘太君百岁挂帅,孙悟空五百多岁西天取经,白素贞一千多岁下山谈恋爱!~

30.张艺谋:想不想来参演我执导的奥运会开幕式?
mm:背景我不当!
张:绝对给镜头!
mm:没看见脸镜头就切过去的我不干!
张:让你出场绝对超过一小时!
mm:站着不动的我不来!
张:保证让你蹦蹦跳跳!
mm:这么好?行,那我答应了!
潜规则后,mm在运动员入场式的欢迎啦啦队里跳了两个小时,回来后哭成泪人……(水木社区)

32.外屋一女同事打电话进来,说她电脑有问题:打字的时候光标经常无缘无故地往前跑。来到她座位旁让她演示一下,于是她在电脑前打了会字。突然,光标真的就一直往前跑了!偶低头一看,狂晕——原来是胸部太大压到键盘的空格键了……

33.我姓高,女友姓郭,我说以后咱们的孩子就叫“高压郭(锅)”好了!
女友问何故,答曰:既给孩子起了名字,又表明了父母的姓氏,两全其美也~
女友大囧!

34.中午下课,我跟班里一恐龙mm合打一把花雨伞去食堂。
也许是细雨生情,她脚步突然停下来,深情地望着我,“你……做我的王子好吗?”
看着她凄惨的面相,我着实不忍心打碎她那颗心,但为了以后的幸福,我必须拒绝。
于是,我装出一副很傻很天真的表情问她道:“那——以后我就得管你叫你母后喽?”

35. 这个暑假,辅导员组织我们留校的同学一起出去旅游。我们来到一个风景秀丽的地方,晚上就在山上的宾馆住下了,因为912女,男生是单数,所以我要求自己一个房间。山上的宾馆的确爽,阳台外面就是大自然,而且这里没有“家禽”服务。房间床头柜上有两盒TT,很精致,我实在是闲的慌,半夜坐在阳台上吹TT 玩,直到都吹破了才去睡觉。
中午把房卡交给辅导员,退房后大家正要走,大厅前台那台该死的对讲机传来了打扫卫生的大妈的声音,“217房间消费TT两盒,repeat,217房间消费TT两盒!”
我当时就炸了:怎么宾馆的TT还收费啊??全班同学则用各种眼神瞅我,当时囧的我死的心都有了!
倒是辅导员很平静,主动付了钱。上车时,辅导员悄悄问我:“哪找的?这荒山野岭的~两盒啊,厉害!厉害!”
我真是一肚子委屈倒不出来!回去的车上,收到同班女生的短信:听说你一晚上两盒??

36.马上要到终点站了,这时站在我身后的那个mm捅了捅我,问:“同学,你下吗?”
我心想:到终点都得下啊,她怎么会问我这样的问题,难道这就是传说中的搭讪?
正想入非非呢,就听mm满脸痛苦地解释道:“哥,你踩住我脚了……”


9.去医院想做个环切手术,结果到了那里才发现护士MM竟然是我高中同学!一阵尴尬的寒暄后,她让我脱裤子,犹豫了半天,她不耐烦道:“快点快点,你说你个老爷们的害羞个什么,要知道我摸过的这东西比你拿过的方便筷子还要多!”

40.和几个好朋友一起参加个宴会,在骑车回学校的路上,一对小夫妻说起他们以前的一件糗事。
那时两个人还没正式在一起。一天夜里,两个人在学校里游荡,都憋的不行了,但附近没有洗手间,眼看四周没人,于是就轮流在路旁的草坪上解决了……
此时A君便调侃那个女生道:“那你是不是看到地上有一条长长的黑杠?”
B
君接着开玩笑说:“你是看到那条黑杠才决定和他在一起的吧?”
众人爆笑。这时那个女生也花枝乱颤地接道:“是啊,只可惜当时数学没学好,忘记乘sin(alpha)了~”
41.
腾讯公司到某大学来招聘,HR:请问你经常使用我们公司的产品吗?
mm
:是的。
HR
:那能把你的QQ打开吗?
mm
:可以。
HR
:我靠!连一个太阳都没混上,你怎么能说经常使用我们公司的产品呢!!
mm:%¥@#@**~×#@!@#¥%……

42.mm相机落出租车后座上了,好心的司机赶忙向要进校门的mm喊道:“妹妹,你相机!”
mm脸一红,扭过头来反驳道:“你TMD才像鸭呢!”
司机一生气,走了。这时mm突然惊悟,冲着车开走的方向边追边喊:“师傅,我相机~~!师傅,我相机~~~!”


44.mm
问主持人:你主持一次婚礼要多少钱?
主持人:不一定。嗯,一般来说,新郎越帅,收费越高~
mm
听后很腼腆地掏出10块钱递过去,主持人回头看了看新郎,然后很从容地找了她95……

45.师弟:师兄师兄,赶快赶快,外面来了很多考艺的mm,咱们一起出去饱饱眼福!
师兄头也不抬:不去不去,没看我正在努力吗?等将来毕业找个好工作,老子就天天到夜总会去泡她们!

46.宿舍一哥们看**走火入魔了。这天,一同学从家带来几袋水果,偶嘴馋,边抢边说:“哇~这香蕉好大,偶要偶要!”
那哥们瞥了一眼,冷冷道:“欧美特大号~”
偶无语,转过头又说:“哇,这雪梨也好大呀,偶要偶要!”
那哥们又冷冷道:“是的,38D的!”

47. 寝室一兄弟又失恋了,这次是被刺激到了!哭了半宿,然后出去买回两瓶烈酒,精神恍惚地在电脑前自斟自饮道:“为什么世界上有这么多无聊的女人?难道只有武藤兰才称得上是女人花?嗯,也只有真正的女人才能写出这么好的诗句了——桃花开罢蜜桃鲜,观音蹙眉嗔坐莲;菊花幽窄香津溢,又拍片换酒钱……”(水木社区)

48.中午在家睡醒后吃了俩桔子,吃完手指上黄黄的,也没洗手就直接去了学校。下午聊天,有个同学说:“你丫怎么那么恶心,拉完屎粘手指头上了也不擦干净喽!”我说那不是屎,是中午吃桔子搞的,说完还唆了唆手指。没过两天惨了——全北京都知道我们学校里有个拉屎用手指头擦屁股,等干了不时地唆了唆手指还说有桔子味的同学……

49.妖艳女:能让个座儿吗?我是个孕妇。
清华男:哦,那你坐~
妖艳女:谢谢!
清华男:冒昧问一句,你怀孕几个月了?瞅你这身段也不像……
妖艳女:哦…嗯…大概有50分钟吧……

50. 班上有个mm属卦仙级的,算命非常准,班上好多人都找她算。今天上课时我半开玩笑半认真地问她,我喜欢上了班里某某某该怎么办,她埋头不语。这不啃声一下子勾起我好奇,隧继续问,怎么才能把她追到手。她依然不语。于是又问要是能和她白头偕老以后的生活会是怎样?她还是不说话!她的沉默让我觉得好无趣,于是转移注意力开始听课。谁知下课后,mm突然扔下一张纸给我,我打开一瞧,见上面画了一盘象棋残局,还附有棋谱:
红帅五平四,黑炮42
红车一进二,黑炮29
红后兵平五,黑车19
红帅五进一,黑卒45
红帅四平五,黑方退车
进入互相牵制状态,和棋。

我猜想这其中必藏有什么深意,但苦思冥想始终没参透其中的奥秘……

51.大学生竞选村官,村主任就让他整个既能普及英语又能宣传治安政策的节目。为了在金融危机下能有份工作,大学生是绞尽脑汁,冥思苦想了一个晚上。第二天一大早,就听村头炮竹声声,锣鼓喧天,村主任跑来一看,就瞧见大学生边敲鼓边领村民RAP道:
don
t dont dont dont
don
t dont dont dont
don
t dont dont dont抢!~


53.
我认识一修鞋的,他常在东城出没,所以很多年后他有个绰号“东鞋”。后来,东鞋吸毒了……~>.<~

56. 我大学一女同学移民美国,刚到时她就在自己家后院里种上了韭菜。这天正准备割了包饺子,邻居见状却赶忙报警,说她虐童,给孩子草吃!于是pol.ice叔叔风驰电掣地赶来,我同学解释了好几个小时,最后万般无奈,她盛了一盘韭菜鸡蛋虾仁馅的饺子给pol.ice吃才把事情摆平……

57.昨天科长接到一个自称是他广东同学的电话。
(老套路)“你猜我是谁呀……对,我在河北呢,明天办完事去看看你。

今早科长又接到那人的电话,“昨晚我找小姐出事了,你在河北有关系吗?”
骗子正准备提汇款呢,科长却抢先说道:“你等会来电话,我帮你问问。”
十分钟后科长打回去,“我找到朋友了,他在河北专门负责扫黄,你的事能花钱摆平,不过你得先给我卡上打两万!”
不一会,骗子发来短信:@#%……&

58.现在的金融危机太离谱了!刚才面试后,等过会再打电话过去问点事,结果没想到连面试官都给裁掉了!

59. 学校读报栏里贴了一则新闻,说哈尔滨某大学两名女生晚上回宿舍时被**,在这里警示我校女生不要回去太晚,后续报道是学校为息事宁人,将二人保送到北大。结果没想到当晚巡逻车就看到N个穿着暴露、深夜还徘徊在校园阴暗处的女生,pol.ice叔叔费解地问其中一个为什么这么晚还不回去,只见那女生杏目圆睁,怒气冲冲地说道:“你管得着吗?考不上还不许被保送嘛!”


61.QQ
上帮mm搞定一件小事。
mm:qqq
我:qqqq

mm:‘qqqq’什么意思?

我:那‘qqq’什么意思?
mm:thank u...

我:…… 


63.甲:你女朋友小丽还好么?
乙(得意洋洋):她早就不是我女朋友了!
甲:你早该这样啦!以前我就听说她跟咱们班好几个男生有染,想当年我还和她有过一腿呢~
乙(欲哭状):她……她现在是我老婆……

64.和老婆聊起我以前一个最好的朋友。
我:他很厉害的,体力超级棒,还想过要骑自行车去西藏呢~
老婆:那后来呢?
我:后来?后来他有女朋友了……

65.老同学聚会,都是男生,其中A君新婚不久,于是大家纷纷打趣他。
尚同mm马拉松式恋爱+同居的B君:你可不一样啦,现在是有证驾驶了,不过千万要小心,别“搞”出人命来~
其他人:你丫无证驾驶更要小心,搞出人命来更加不可收拾!
独身的C君:我说还是走路好得多,买车要钱不说,养车更是麻烦得不得了!
这时D君刚从卫生间回来,听C君话后赶紧同意其观点:就是就是,买什么车嘛,大街上出租车那么多,要用的话伸手打一辆不就行了?
沉默两秒钟后,众人哄堂大笑。
D君莫名其妙,无辜状对A说:大家什么意思啊?要是真有什么急事我蹭一下你车总该可以吧?


67.
倒桩考试,考评员从屋里冲出来挥动拳头冲我吼道:“不及格!!!撞倒七个,你TMD怎么学的!”
“我承认我驾驶技术差,可你也不要太夸张好不好!一共六个竿,哪来的七个?”
“那不——教练也在那儿躺着么!”

68.坐火车回家,旁边是一腼腆的PPMM,于是我热心搭讪道:“你好,你哪个大学的?”
“哦,你好,我是××医科大学的。”
哈哈,成功搭讪!于是附和道:“哇,原来你是白衣天使啊,那我以后看病就去找你喽~”
看得出MM是强挤出一丝笑容,不太情愿地应道:“好……”
为进一步打开话匣子,我继续问:“那你学的是医学的哪个专业啊?”
MM
如坐针毡,犹豫了一会回道:“法医……”


70.带gf回寝室,见屋里没人,于是就~*^_^*
刚完事,就有人敲门,我暗自庆幸这人没早点来,要不就坏了我们的好心情。
一开门发现竟然是隔壁的W X男,“快,把你刚才看的片传给我!”
“我没看啊……”
“噢~你没看吗?那刚才谁放的那么大声?”
71.
今天天气很好,我想出去买本《男人装》看。走到报亭时,发现这期杂志改版了。
报亭大妈忙借机向我推销,“这本杂志卖得贼火,现在都改半月刊了,不过上半月的A版卖光了,你就买B版吧。”
于是我高兴地拿了一本《男人装B》溜达着走回了家~

73.我和A君去吃学校附近的一家自助,等吃的差不多了,自助餐店的老板出现在A君面前,只见他掏出一张VIP金卡陪笑道:“先生,这是隔壁饭店的VIP卡,以后请你去隔壁用餐吧~”

74. 我刚进家门,就发现桌子上放着一张百元大钞。平时老妈也不给什么零花钱,难道这次发慈悲了?想到这儿,我心中不禁一喜。当我拿起钞票时,发现底下还压着一张纸条,拿起来一看,上面写着:今天是你外婆生日,在家等我,我们一起去给外婆祝寿。注意——那一百块钱不是给你的,是为了引起你的注意,看到后请把它放回原处!

75.中午修箱子的时候发现锤子坏了,于是吃过晚饭出去散步时打算把它丢掉。
走到离垃圾桶56米处,突然我心血来潮地想把锤子直接扔进去。
谁知准头太次,一下子把旁边一住户的花盆给打碎了!结果被老头训了10分钟,赔了10块钱才算了事。
刚要走,就听身后那老头又来一句:“小年轻的,别以为扔个锤子自己就是山丘之王了!~”

76. 我一信道的哥们神经了,他老婆没办法,只好把他送到精神病院。治了半年,有所好转,出院后老哥又改研究易经,结果半年后又神经了,他老婆哭成泪人……后经几位朋友指点,说某大寺院有位高僧,如果能请他来作法,肯定会把他的病治好。他老婆咬牙花重金还真把那位高僧请来了——结果高僧一进门看到我哥们,二话没说,上来就给丫跪地磕头,连声叫师傅,说找了六十多年了可算找到师傅了!他老婆当时就吐血了……

77.大学那会儿,大家都不重视政治课,所以平时很多人都不来听。我一哥们就是,不过考试那天他倒早早地来到教室,找个好座位坐下后就和旁边一小伙拉关系道:“哥们儿,呆会儿就靠你了,借我抄下啊~”那人没理他。
过一会儿铃响了,那个人站起来开始发卷……

78. 高中时,学校是封闭式管理的,平时我们出去玩只能翻墙,但只有一位同学是直接从大门走出去的。他个儿不高,有点胖,喜欢穿西装,络腮胡也不刮,每次出去的时候保安都问他:“跟老师谈得怎么样?”只见他一拍大腿,满脸哭丧像骂道:“我这个娃儿操心的很,一天到晚就晓得打架!来,给根烟抽消消气儿~”

79. 一个小偷趁人不备,溜进清华研究所里。可自打他进来,实验室里就有人,于是他躲在角落里等待着下班时刻的到来。终于熬到下班了,没想到这拨走了,又来了一拨做实验的。他想:既然这么不容易进来,总不能空手回去,还是等等吧,总不会晚上还有人吧?可没想到晚饭后,又来了一批学生挑灯夜战做实验!他坚持着,等到夜深人静的后半夜,还有人在那里做实验……
也不知熬过了多久,小偷终于从研究所里逃出来。在回家的路上,他遇到一同行,同行就问他这几天去哪儿了。说完后,同行羡慕不已,忙问收获如何。
小偷:那破地方,什么都没有!
同伙:那你呆那么久?
小偷无限郁闷,苦笑着回答道:“别说,我学会提取质粒了~”(注:提取质粒是研究所最常做的一项工作)

80.今天中午碰到一位卖摄影器材的老头。“这堆器材不错,怎么不要了?”我问。
老头抬头扫了俺一眼,点支烟慢慢道来:“其实照相分四种境界——”“噢?”俺心中一震,赶忙把耳朵支起来。
“这第一种境界”,老头说:“是手中有相机,心中没相机。所以只出糖水,还自以为得意。”靠,这不是说俺嘛?看来碰到高手啦,赶紧坐近点听。
“这第二种境界”,老头继续说道:“是手中有相机,心中有相机。边拍边想,总不满意。”俺点头称是。
“这第三种境界,是手中无相机,心中有相机。无论河山大川,美女人文,都了然于胸;知道哪儿满意,哪儿不满意,全琢磨得头头是道。”听得俺茅塞顿开!
“这第四种境界,也是最高境界”,老头顿了顿道:“是手中无相机,心中无相机。”说完,拿眼角瞥了俺一眼,看俺直犯迷糊,老头突然正色道:“有漂亮的风景就好好地看,有漂亮的模特就好好地干,还拍个屁照啊!”
说完把烟头一丢,扬长而去,只剩下俺一人在那里发呆……
81.
坐飞机一般我都买靠窗的座,今儿上飞机,见一mm赫然坐在我的位置上。
于是我走上前很绅士地问道:“请问你是36A的吗?”
孰料,mm竟然红着脸应道:“我…我是36B的……”
我成吉思汗啊,“妹妹…我想…我想你误会了,我是说我的座儿是靠窗36A的!”

82.我:你说我和这个上海MM能成吗?
寝室兄弟:要我说没戏!
我:Why?
寝室兄弟:你知道上海女人和塔利班男人有什么共同点么?
我:???
寝室兄弟:那就是都不放过美国男人!


84.
相亲,跟一mm在茶馆里相对而坐。在了解过双方的工作、教育、家庭、爱好后,交谈陷入困境,于是开始扯些社会话题。
我:你是如何看待房市的?
mm(愣了下,然后低头沉默了一会儿):还是…还是不要过于频繁比较好……(水木社区)

85.几个复旦的MM相约到交大游玩。突然,她们看见一只熟睡的小猫,特别可爱,于是打算拍下来。
结果刚掏出相机,就被旁边一交大gg喝止。
MM
:怎么,给猫照像也违反校规啊?
gg
:不是,不是。你们不知道,这只猫的眼睛颜色不一样:一个蓝,一个黄,不信我弄醒了给你们看!

87.GG:你知道吗?80%的女孩在洗澡时会SY,其他20%在洗澡时会唱歌,你猜她们唱的是什么?
mm:嗯……不知道。
GG(坏坏地笑):看来——你是那80%的~

88.我有个哥们属腼腆型的,还口吃,但人家就是点儿正,找的女朋友是咱复旦某系的系花。
这天毕业典礼上,我又遇见他,于是关心地问他和他女友现在怎样了。
但见他牙根紧咬,当着众人面愤然道:“我…我…我上了这个小骚…骚货……”
当着这么多人讲这样的话,未免也太OPEN了吧???
这时就听他又说:“的当!!”

89.一个和我关系特铁的女生心情不好,于是拉我出去陪她吃饭。
吃到一半时,她点了一瓶啤酒,然后问我:“能陪我喝点酒吗?今天我心情糟透了!”
我犹豫着,“那个,对不起,我不会喝啊。”
“噢,我也不太会喝,而且喝一瓶就醉,一醉就乱亲人,唉~”说完很幽怨地看了我一眼。  
我思索了一下,然后回头喊:“服务员,再来四瓶啤酒!!”

90.大学毕业若干年后,与高中同学偶聚。
酒过三旬,甲同学喝高了,他把老班长拉到身边:“说实话,班长,这几年我有个心病一直放不下——你还记得高三时借我5毛钱饭票到现在我都没还吗?”
班长:“啊?什么时候的事?我怎么不记得了。哎,就为5毛钱饭票还留下心理阴影,至于吗?
甲掏出5毛钱接着说:“我知道你不会向我要利息的,但不管怎样,这5毛钱我得还你,你就满足我这个心愿吧!”
班长:“唉呀呀, 这可不行!”
推辞再三,再三推辞,甲同学执意将钱塞进老班长兜里,老班长又推辞半天,没办法,只好收下。
班长:“来来来,喝酒!这种小事你竟然记了这么多年,难得兄弟情谊呀~你放心,待会儿我查查本子,把你的帐给消喽!”
91.
去邮局存话费,我前面那个mm的背影很是诱人,左摇右晃从侧面偷看,的确是个看起来非常清纯可爱的小美女。遂趁其报号存话费的时候偷偷记下她的手机号码。晚上回去无聊,于是给mm发短信:妹妹你好,交个朋友咋样?
——你是?
——今天存话费排你后面的那个帅哥*^_^*
——哦,不好意思,昨晚XX时间太长,今早起不来了,是我女朋友去帮我存的话费!
——&*%*&&*……* ※…%)#◎#

92.今天,我高高兴兴地拿着我的MBA结业证书去一家公司面试。当老总傲慢地提出一个薪资水平并问我是不是觉得很受宠若惊时,我一把薅住他的衣领将他拖到窗边,然后狠狠地指着楼下我的车说道:“你说!你给我的薪水能养得起我的车么!!”

93. 几个老同学在学校附近的川菜馆聚会。席间,我们要了一道叫重庆辣子鸡的菜,大家拿筷子在里面翻啊翻,找啊找,发现除了漫山遍野的红辣椒,鸡肉几乎没有!这时,一同学说:“你们知道这道菜的别名为什么叫‘红灯区’吗?”众人皆好奇,问其缘由,只见那同学嘿嘿笑道:“找鸡啊!”


95.
又是新生报道的季节,下晚自习回来,老大问我今年女生质量如何?
我(哭丧脸):咱们系的女生排队报道——猜一句常用英文!
老大(想了下):猜不出啊……
我(叹口气):long time no C......

96.毕业前,老生都在校园里摆摊卖书,期望着卖点钱买酒喝,故吆喝声引得不少同学驻足翻看。
甲用纸圈成个大喇叭喊道:买教材送青年文摘啦!
乙干脆借个扩音喇叭喊道:买教材送读者啦!
却见丙拉着自己女朋友的手喊道:买教材送女友啦!
结果丙摊前立刻围满了同学,正当大家准备一探究竟,就听丙又吆喝道:多买多送,送完女友,送知音送爱人啦!!

97.初中时,宿舍一兄弟总爱把零钱放到裤兜里,所以每次回来换裤子,钢崩都洒一地。
一天,他喜欢上班里一女孩,于是写了情书一封装进裤兜里。下晚自习时,他走到女孩身旁,从兜里掏出情书迅速塞到女孩手里,然后跑了。
次日晚,该兄回宿舍后一脸郁闷相,问之,说女孩回信拒绝了。原来那天他裤兜里有一块钱,掏情书时没看到,夹到里面一块送出去了,女孩在回信中把这一块钱又夹回来了,信中还说:我不是那种人!


99.
我骑着一辆破电瓶车 (右边反光镜没了,就剩下那根铁竿了),在等完一个红灯后一加速,就听旁边那个女孩喊“抢劫”!等我反应过来才发现,原来是她的包包勾到我反光镜杆上了。等MM赶上来,是劈头盖脸给我好一顿臭骂,然后拿着包走了。这时,一围观的哥们过来拍拍我的肩膀安慰道:“兄弟,算你运气好——昨天绿灯时我摩托车以70 迈的速度冲过这里,结果把一过路女孩的小背心吊带、胸罩带给一下子扯飞了……”--

100.A:你昨天没带手纸是怎么解决的?
B
:我从楼梯扶手上直接滑下来的……
A:嗯,好主意~

异日,A没带手纸,从楼梯扶手上滑下来就哭了……
A
:你怎么不告诉我昨天你滑的就是这个!还拉稀!!
B:……

A:这个楼梯你昨晚没滑过吧?
B
:没有,绝对没有!
A:好极了~

滑下来后A还是哭了……
A
:你怎么不告诉我这个扶手上有钉子……
B:我又没滑过我怎么知道

101 我宿舍一哥们口吐狂言说自己是战斗机中的傻逼,另外一个想占个便宜,立马接到,我是傻逼中的战斗机!

1

1. 单位祝词,一位领导说:“祝大家身体愉快……”憋住,没词了。

2 .宿舍老四下床找了半天拖鞋,没有,问大家:为什么我的拖鞋哪里去了?

3 .我有次去买羊肉串

伸出4个手指对老板说“来3根羊肉串”

老板蒙了“几根?”

我又伸出3个手指说“4根”……

4.本人姓朱,管理单位机房。有次有人打我手机:“鸡科长,你在猪房吗?”当时狂骂那家伙一顿

5.爸妈吵架,我爸气的说了句:”我给你滚出去!”

6.刚上大学,军训,连长不知道是哪里的口音,喊口令——“向左钻!”“向右钻!”

7. 大学时候,听见一个女生点菜:师傅,炒一盘酸辣土豆丝,不要放土豆!

8.当年找工作时,主考官问我哪年毕业的。

我本来是要说2000年的,结果一激动说:“两千年前。。。”

更瀑布汗的是,主考官竟然噢了一声,说:“孔子的学生吧。”

9.一次文艺晚会,主持人上台报幕:下面请欣赏:新疆歌舞,掀起你的头盖骨!毛骨悚然!!!!!

10.老虎不发猫,你当我是病危呀!

11.我:那是我们物理老师。。。

同学:教什么的阿?

我:化学。。。

12.上学的时候有一天一个电话找我,同学接完递给我说:“你妈找你。”

我一边接过电话一便随口说到:“男的女的”

大家狂笑 我被笑了4年

13.有一次寝室里同学的老妈打电话过来,我习惯说“他不在”,但是这一次我想说的的是“已经出去了”.结果说出来是:“他已经…不在了”

14.gg递给我一根冰糕,我咬一口大叫:“烫死我了!”

15.和我姐姐去李宁买鞋,我姐一开口:“小姐,这鞋多少钱一斤?”

16.上学时周末回家,晚饭后烟瘾犯了,打算借口去散步。在门口换鞋时,老爸问我干吗去?我随口说了句:“去散个烟!”结果老爸从我身上搜出一包555,狠狠K了我一顿。

17.老师留下作业,我不会做就抄别人的,然后去办公室交作业,看见老师说:“我抄完了!”

18.我们单位早上上班有车子接送的,因为车子不大,有一次,一mm上车后没座位,坐我旁边的一男同事忙站起来,热情的和她打招呼说到:“某某,你坐我屁股上吧!” 我当时一直狂笑到下车~!

19.大学时候,一同学和我争论问题,一时处于下风,情急中一拍桌子起身大叫:你胡说,我又不是不傻!

20.小时候冰棍雪糕的一般都是推着自行车叫卖,有一次,在屋子里听一阿姨喊:新来的雪糕,热乎的。(估计阿姨以前是卖油饼油条的)

21.有一天去同学家吃饭,喝了点酒,她爸爸忽然进来了,本来是想喊叔叔的,结果说错了,说:“爸,来座!”~~寒!大帮同学笑得要死

22.一次ktv,点歌,一mm大声喊:给我点一首周截棍的“双杰伦”......

23.以前考试老师发卷子,后边的女生多拿了一张,高呼“老师,我有了,我有了”结果坐他旁边的男生说道“是我的,是我的”全班爆寒~~~

24. 朋友小孩半岁了,打电话去关心,寒暄了两句后,来了一句:你的小孩现在是吃人奶还是你的奶

25.有一天傍晚,碰到个熟人,开口就说:“早啊“...

26.晚上,一室友进屋大声宣布: “今天我看午夜版的美国凶铃了!

27. 由于一次出差机会,要去某地的中国银行维修设备,从宾馆出来做上出租车后对女司机说:“去中国银行、顺便找一家五金店买把刀”汗!当时我的意思是买把螺丝刀,我没注意到我说错了,这时那个女司机一直看着我非常委屈的说:“大哥我要下班了,你重新打辆车吧”。当时我就非常生气,恶狠狠的说:“你要下班了在宾馆泊什么车呀!?”女司机看了看我快要崩溃的说:“大哥那买完刀我不要车钱了你再找辆吧”晕!!!这才知道我说错了,赶紧解释了半天,现在想一想都感觉对不住人家女司机。

28.政治老师有一次讲课的时候说:“下面我举个比方”,然后觉得不对,又说:“打个例子”

29.初中的时候,老师叫翻译Who is this man ?

一同学翻译:这是谁的男人?全班大笑,老师无语

30.政治课时谈到中日政治问题,扯阿扯说到日本武士剖腹自杀。

老师介绍说:“日本武士死前都剖腹产的~~~”

31.大学时期,我一同学刚买了手机,办了移动卡,打1860人工台询问,一时激动:请问你们的地感动带业务。。。,从免提中我们竟然听到话务员小姐客气的说:我们的地感动带业务。。。全宿舍暴笑

32. 我老公特别瘦,有次我急了就说道“老公,看你瘦的象猪似的!”

33.播音稿原文:两歹徒打伤我110干警后逃窜

播音员读成:两歹徒打伤我一百一十名干警后逃窜

(黄飞鸿转世??!)

34.我们一个同事,他去考驾照时,对考官说了一句经典的话:

报告仪表,,考官正常~~~~~~

35. 记得有一次,和一姐们儿去KFC,排队的时候我听她口中念念有词,一个鸡腿汉堡,一对鸡翅......,好不容易轮到她了,一开口就笑翻了所有人,她本想说“小姐,来个鸡腿汉堡”,可话到口中竟成了“小腿,来个汉堡”

36.MM告诉我肯德基新出的“骨肉相连”(肉串有脆骨),要我带她去吃,那几天北京巨热无比,我昏昏沉沉,到了餐厅,我对微笑的肯德基小姐来了句:请给我两个“血肉模糊”,谢谢!.............

无地自容-_-!

37.一男生看到舅舅:“买舅啊,二菜!”

舅舅:“这孩子,这么大话了,连人都不会说!”

38.一个很腼腆的男同学去食堂打早饭,窗口里那师傅问他:“要点儿什么?”他低着头说:“我要……我要……一个包子和一个包子。”那师傅盯了他半天,问:“你要什么呢?再说一遍!”“我要一个包子和一个包子……哦。不!一个包子和一个面包!”

39.英语课,老师:“good morningteacher!”

学生:“good morning,student!”

全班哄堂大笑。

40.一个同学往他的朋友家打电话,对方的爷爷接的,那同学不知道在想什么,张嘴就是:“爷爷,我是奶奶……”突然觉得不对,哐一下就把电话挂了……

41.一哥们,一次他约心仪已久的女孩,准备对她表白。两个呆坐良久,他才鼓起勇气对女孩说:“你有没有男朋友?”女孩羞涩地答道:“还没有”,他狂喜:“那你可不可以当我的男朋友?”

42. 妻子责备地问:你连你奶奶的名字都不知道?

丈夫受屈地答:我咋知道,我死时奶奶才七岁。

妻惊讶:什么?

丈夫忙改口:不不,是奶奶七岁时我才死!