求助:那位大哥有串口编程的资料?

tobato 2001-11-11 11:03:21
那位大哥有串口编程的资料?
能不能给我Mail一份: towyf@ynmail.com
...全文
108 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
tobato 2001-11-13
  • 打赏
  • 举报
回复
thank all
coolfired 2001-11-11
  • 打赏
  • 举报
回复
在WIN32下是不建议对端口进行操作的,在WIN32中所有的设备都被看成是
文件,串行口也不例外也是作为文件来进行处理的。这是我的一份关于串
口编程的读书笔记,对于使用VC进行编程的同行应该有一定的帮助。

〈〈Windows 95 通讯编程〉〉 清华 ISBM 7-302-0270-1/TP.1398
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 在发送中清除中止

以上资料来源于http://202.114.245.75/mhsguru/mhsguru.asp(教科网内部资料)
coolfired 2001-11-11
  • 打赏
  • 举报
回复
---- 要完成串口通信, 在32位模式下, 一般说来有以下四种方法:

---- 1. 以文件方式打开串口:

---- 这里使用的是Win32 API 函数, 所以无论在BCB或VC下都可以实现. 具体的函数的
意义可以参考Win32 API 的帮助.这里有一个易于使用的BCB下的类, 可以方便的使用串
口.

---- 下面给出简要说明:

---- (1) 应用CreateFile() 来初始化串口


FhFileComm=CreateFile( FCommName.c_str(),
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
&lpSecurity,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_OVERLAPPED, // overlapped I/O
NULL );
if( FhFileComm == INVALID_HANDLE_VALUE)
return false;
(2) 应用WriteFile() 和 ReadFile() 从串口读写数据
bool MyComm::WriteBuffer(unsigned
char*buffer,unsigned long length)
{
return WriteFile(FhFileComm,buffer,
length,&length,&FgOverLapped);
}

bool MyComm::ReadBuffer(unsigned
char*buffer,unsigned long length)
{
return ReadFile(FhFileComm,buffer,
length,&length,&FgOverLapped);
}
相应的源文件为 UsageComm.cpp UsageComm.h

---- 2. 使用现成的控件:

---- 易于使用的是微软的MS Communication 控件, 它是做为一个 .ocx 提供的.

---- 在BCB 中可以用Import ActiveX Control 将它加入到BCB 中, 缺省是加载在
ActiveX 页中. 就可以作为一个普通的BCB 控件来使用了.(也有不少第三方提供的其它
硬件操作控件)

---- 3. 直接嵌入汇编法:

---- (该方法不能在NT下使用, 由于98的非完全保护, 下面的代码可以使用)利用BCB的
直接嵌入汇编功能, 可以在BCB中直接对串口操作.

---- 如下所示,在BCB中使用汇编代码如下

byte __fastcall ReadByte(WORD Address)
// eax :address

{
asm


mov DX,AX
in AL,DX
}
}

void __fastcall WriteByte
(unsigned char byte, WORD Address)
// EAX: BYTE EDX: ADDRESS
{
asm


out DX,AL
}
}

---- 这里必须用__fastcall 调用约定以使在调用该函数时用寄存器传递参数.

---- (用在BCB中的汇编指令代码in 和out必须用小写,(其余可以为大写)寄存器名称
大小写都可以)

---- 其它的如写多个字节,读多个字节, 同样可以实现.

---- 4. 最困难的要数用VxD来实现:
lhh2394 2001-11-11
  • 打赏
  • 举报
回复
我这有杂志2001年《单片机与嵌入式系统应用》两本,原价8元/本。一本是用ActiveX 方法;另一本用Win32 API 方法。可以原价+邮费卖给你。
 面试的时候,设计模式会经常被问到。其实我们在写代码中或多或少会用到一些模式,面试官问你设计模式的问题,更多是看你有没有总结过。如果一直都是在那垒代码,你当然会认为这是个很难的问题。所以我们需要总结一下设计模式。   1. SINGLETON 单例模式   单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。     俺有6个漂亮的老婆,她们的老公都是我,我就是我们家里的老公Sigleton,她们只要说道“老公”,都是指的同一个人,那就是我(刚才做了个梦啦,哪有这么好的事)。   2. FACTORY METHOD 工厂方法模式   工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。     请MM去麦当劳吃汉堡,不同的MM有不同的口味,要每个都记住是一件烦人的事情,我一般采用Factory Method模式,带着MM到服务员那儿,说“要一个汉堡”,具体要什么样的汉堡呢,让MM直接跟服务员说就行了。   3. FACTORY 工厂模式   工厂模式:客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。     追MM少不了请吃饭了,麦当劳的ji翅和肯德基的ji翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个ji翅”就行了。麦当劳和肯德基就是生产ji翅的Factory。   4. BUILDER 建造模式   建造模式:将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。     MM超级爱听的就是“我爱你”这句话了,见到不同地方的MM,要能够用她们的方言跟她说这句话哦,我有一个多种语言翻译机,上面每种语言都有一个按键,见到MM我只要按对应的键,它就能够用相应的语言说出“我爱你”这句话了,国外的MM也可以轻松搞掂,这就是我的“我爱你”builder。(这一定比美军在伊拉克用的翻译机好卖)   5. PROTOTYPE 原型模式   原型模式允许动态的增加或减少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。     跟MM用QQ聊天,一定要说些深情的话语了,我搜集了好多肉麻的情话,需要时只要copy出来放到QQ里面就行了,这就是我的情话prototype了。 原型模式:通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。   6. ADAPTER 适配器模式   适配器(变压器)模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。     在朋友聚会上碰到了一个美女Sarah,从拉斯维加斯来的,可我不会说粤语,她不会说普通话,只好求助于我的朋友kent了,他作为我和Sarah之间的Adapter,让我和Sarah可以相互交谈了(也不知道他会不会耍我)。   7. BRIDGE 桥梁模式   桥梁模式:将抽象化与实现化脱耦,使得二者可以独立的变化,也就是说将他们之间的强关联变成弱关联,也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以独立的变化。     早上碰到MM,要说早上好,晚上碰到MM,要说晚上好;碰到MM穿了件新衣服,要说你的衣服好漂亮哦,碰到MM新做的发型,要说你的头发好漂亮哦。不要问我“早上碰到MM新做了个发型怎么说”这种问题,自己用BRIDGE组合一下不就行了。   8. COMPOSITE 合成模式   合成模式:合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。     Mary今天过生日。“我过生日,你要送我一件礼物。”“嗯,好吧,去商店,你自己挑。”“这件T恤挺漂亮,买,这条裙子好看,买,这个包也不错,买。”“喂,买了三件了呀,我只答应送一件礼物的哦。”“什么呀,T恤加裙子加包包,正好配成一套呀,小姐,麻烦你包起来。”“……”,MM都会用Composite模式了,你会了没有?   9. DECORATOR 装饰模式   装饰模式:装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性。动态给一个对象增加功能,这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。     Mary过完轮到Sarly过生日,还是不要叫她自己挑了,不然这个月伙食费肯定玩完,拿出我去年在华山顶上照的照片,在背面写上“较好的的礼物,就是爱你的Fita”,再到街上礼品店买了个像框(卖礼品的MM也很漂亮哦),再找隔壁搞美术设计的Mike设计了一个漂亮的盒子装起来……,我们都是Decorator,最终都在修饰我这个人呀,怎么样,看懂了吗?   10. FACADE 门面(外观)模式   门面模式:外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。每一个子系统只有一个门面类,而且此门面类只有一个实例,也就是说它是一个单例模式。但整个系统可以有多个门面类。     我有一个专业的Nikon相机,我就喜欢自己手动调光圈、快门,这样照出来的照片才专业,但MM可不懂这些,教了半天也不会。幸好相机有Facade设计模式,把相机调整到自动档,只要对准目标按快门就行了,一切由相机自动调整,这样MM也可以用这个相机给我拍张照片了。   11. FLYWEIGHT 享元模式   享元模式:FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部,不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态,它们是相互独立的。将可以共享的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象,而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。     每天跟MM发短信,手指都累死了,最近买了个新手机,可以把一些常用的句子存在手机里,要用的时候,直接拿出来,在前面加上MM的名字就可以发送了,再不用一个字一个字敲了。共享的句子就是Flyweight,MM的名字就是提取出来的外部特征,根据上下文情况使用。   12. PROXY 代理模式   代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入。     跟MM在网上聊天,一开头总是“hi,你好”,“你从哪儿来呀?”“你多大了?”“身高多少呀?”这些话,真烦人,写个程序做为我的Proxy吧,凡是接收到这些话都设置好了自己的回答,接收到其他的话时再通知我回答,怎么样,酷吧。   13. CHAIN OF RESPONSIBLEITY 责任链模式   责任链模式:在责任链模式中,很多对象由每一个对象对其下家的引用而接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。客户并不知道链上的哪一个对象最终处理这个请求,系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择:承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。     晚上去上英语课,为了好开溜坐到了然后一排,哇,前面坐了好几个漂亮的MM哎,找张纸条,写上“Hi,可以做我的女朋友吗?如果不愿意请向前传”,纸条就一个接一个的传上去了,糟糕,传到第一排的MM把纸条传给老师了,听说是个老一手女呀,快跑!   14. COMMAND 命令模式   命令模式:命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。命令模式允许请求的一方和发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否执行,何时被执行以及是怎么被执行的。系统支持命令的撤消。     俺有一个MM家里管得特别严,没法见面,只好借助于她弟弟在我们俩之间传送信息,她对我有什么指示,就写一张纸条让她弟弟带给我。这不,她弟弟又传送过来一个COMMAND,为了感谢他,我请他吃了碗杂酱面,哪知道他说:“我同时给我姐姐三个男朋友送COMMAND,就数你最小气,才请我吃面。”   15. INTERPRETER 解释器模式   解释器模式:给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。解释器模式将描述怎样在有了一个简单的文法后,使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何解释器对象能够解释的任何组合。在解释器模式中需要定义一个代表文法的命令类的等级结构,也就是一系列的组合规则。每一个命令对象都有一个解释方法,代表对命令对象的解释。命令对象的等级结构中的对象的任何排列组合都是一个语言。     俺有一个《泡MM真经》,上面有各种泡MM的攻略,比如说去吃西餐的步骤、去看电影的方法等等,跟MM约会时,只要做一个Interpreter,照着上面的脚本执行就可以了。   16. ITERATOR 迭代子模式   迭代子模式:迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中,从而与聚集本身隔开。迭代子模式简化了聚集的界面。每一个聚集对象都可以有一个或一个以上的迭代子对象,每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。     我爱上了Mary,不顾一切的向她求婚。Mary:“想要我跟你结婚,得答应我的条件” 我:“什么条件我都答应,你说吧” Mary:“我看上了那个一克拉的钻石” 我:“我买,我买,还有吗?” Mary:“我看上了湖边的那栋别墅” 我:“我买,我买,还有吗?” Mary:“我看上那辆法拉利跑车” 我脑袋嗡的一声,坐在椅子上,一咬牙:“我买,我买,还有吗?” ……   17. MEDIATOR 调停者模式   调停者模式:调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用。调停者模式将对象的行为和协作抽象化,把对象在小尺度的行为上与其他对象的相互作用分开处理。     四个MM打麻将,相互之间谁应该给谁多少钱算不清楚了,幸亏当时我在旁边,按照各自的筹码数算钱,赚了钱的从我这里拿,赔了钱的也付给我,一切就OK啦,俺得到了四个MM的电话。   18. MEMENTO 备忘录模式   备忘录模式:备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。     同时跟几个MM聊天时,一定要记清楚刚才跟MM说了些什么话,不然MM发现了会不高兴的哦,幸亏我有个备忘录,刚才与哪个MM说了什么话我都拷贝一份放到备忘录里面保存,这样可以随时察看以前的记录啦。   19. OBSERVER 观察者模式   观察者模式:观察者模式定义了一种一队多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。     想知道咱们公司**MM情报吗?加入公司的MM情报邮件组就行了,tom负责搜集情报,他发现的新情报不用一个一个通知我们,直接发布给邮件组,我们作为订阅者(观察者)就可以及时收到情报啦。   20. STATE 状态模式   状态模式:状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。     跟MM交往时,一定要注意她的状态哦,在不同的状态时她的行为会有不同,比如你约她今天晚上去看电影,对你没兴趣的MM就会说“有事情啦”,对你不讨厌但还没喜欢上的MM就会说“好啊,不过可以带上我同事么?”,已经喜欢上你的MM就会说“几点钟?看完电影再去泡吧怎么样?”,当然你看电影过程中表现良好的话,也可以把MM的状态从不讨厌不喜欢变成喜欢哦。   21. STRATEGY 策略模式   策略模式:策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。策略模把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开来,算法的增减,修改都不会影响到环境和客户端。     跟不同类型的MM约会,要用不同的策略,有的请电影比较好,有的则去吃小吃效果不错,有的去海边浪漫最合适,单目的都是为了得到MM的芳心,我的追MM锦囊中有好多Strategy哦。   22. TEMPLATE METHOD 模板模式   模板方法模式:模板方法模式准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个珠峰逻辑框架,而将逻辑的细节留给具体的子类去实现。     看过《如何说服女生上床》这部经典文章吗?女生从认识到上床的不变的步骤分为巧遇、打破僵局、展开追求、接吻、前戏、动手、爱抚、进去八大步骤(Template method),但每个步骤针对不同的情况,都有不一样的做法,这就要看你随机应变啦(具体实现)。   23. VISITOR 访问者模式   访问者模式:访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问者模式使得增加新的操作变的很容易,就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。当使用访问者模式时,要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。     情人节到了,要给每个MM送一束鲜花和一张卡片,可是每个MM送的花都要针对她个人的特点,每张卡片也要根据个人的特点来挑,我一个人哪搞得清楚,还是找花店老板和礼品店老板做一下Visitor,让花店老板根据MM的特点选一束花,让礼品店老板也根据每个人特点选一张卡,这样就轻松多了。 

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧