C语言摘录文档格式.docx
《C语言摘录文档格式.docx》由会员分享,可在线阅读,更多相关《C语言摘录文档格式.docx(32页珍藏版)》请在冰豆网上搜索。
//可将转换成字符串格式后的串口数据存入此变量
9.
//读缓冲区数据并进行转换
10.
if(m_ctrlComm.GetCommEvent()==2)
//事件值为2表示接收缓冲区内有字符
11.
{
12.
variant_inp=m_ctrlComm.GetInput();
//读缓冲区
13.
safearray_inp=variant_inp;
//将VARIANT型变量转换为ColeSafeArray型变量
14.
len="
safearray"
_inp.GetOneDimSize();
//得到有效数据长度
15.
for(k=0;
k<
len;
k++)
16.
safearray_inp.GetElement(&
k,rxdata+k);
//转换为BYTE型数组
17.
//将数组转换为Cstring型变量
18.
19.
bt=*(char*)(rxdata+k);
//字符型
20.
strtemp.Format("
%c"
bt);
//将字符送入临时变量strtemp存放
21.
m_strRXData+=strtemp;
//加入接收编辑框对应字符串
22.
}
23.
24.
25.
//以下可根据需要处理接收到的数据
26.
....
27.}
由于用Mscomm控件的GetInput方法读到的串口缓冲区数据为VARIANT格式,需要用一个COleSafeArray类型来转换,具体步骤按上面的示例来就是了。
2、动态链接库dll读串口方法
不同的串口dll有不同的方法,应该根据其手册来,如VC串口通信技术网的VC串口通信技术资料集里的一个例子用到的串口dll-ThreadSerial.dll,它是通过查询成员变量m_LastIndex的值是否大于1来判断是否接串口缓冲区中数据的,VC串口通信技术资料集的一个例子串口调试助手EasySerialAssistant就是用的这个dll,
这个示例专门为读串口开了一个线程,在线程里不断地读m_LastIndex的值,如果大于代表串口缓冲区中有数据,然后将数据显示到显示区:
1.UINT
CEasySerialAssistantDlg:
ProDispThread(LPVOID
pParam)
CEasySerialAssistantDlg*
pParlPro=(CEasySerialAssistantDlg*)pParam;
pParlPro->
m_bThread=TRUE;
c="
"
d="
;
char
b[4];
while
(1)
{
Sleep
(1);
if(pParlPro->
m_LastIndex
>
0)
c.Format("
RX:
%d
t:
n:
%d"
pParlPro->
m_RecvCount,pParlPro->
m_nCurLen,pParlPro->
m_nRecvTimes);
(pParlPro->
GetDlgItem(IDC_STATIC_RX))->
SetWindowText(c);
m_bDispRecv
==
FALSE)
m_LastIndex=0;
}
else
CEdit
*pList
=(CEdit
*)(pParlPro->
GetDlgItem(IDC_EDIT_RX_DISP));
m_bAutoClearn
FALSE)
c=pParlPro->
m_StrBuf;
27.
28.
m_bHexDispMode
TRUE)
29.
30.
for(int
i=0;
i<
(int)pParlPro->
m_LastIndex;
i++)
31.
32.
sprintf(b,"
%2.2X"
m_RecvBuf[i]);
33.
c+="
34.
c+=b;
35.
36.
37.
38.
39.
40.
m_RecvBuf[pParlPro->
m_LastIndex+1]='
\0'
41.
d.Format("
%s"
m_RecvBuf);
42.
m_bAutoChangRow
43.
44.
d.Insert(c.GetLength(),"
\r\n"
);
45.
46.
c+=d;
47.
48.
49.
50.
m_StrBuf=c;
51.
52.
pList->
53.
54.
unsigned
int
nVScrollPos=pList->
GetLineCount();
55.
LineScroll(nVScrollPos);
56.
57.
58.
59.
60.
m_bThread=false;
//工作标志复位
61.
return
0;
62.}
4、串口类读串口方法
同样不同串口类有不同方法和接口,这里只说说最常用的串口类CSerialPort的读串口方法。
启动串口通信监测线程函数StartMonitoring(),串口初始化成功后,就可以调用BOOLStartMonitoring()启动串口监测线程。
线程启动成功,返回TRUE。
串口收到的字符会向主线程或父窗口发送WM_COMM_RXCHAR消息,我们需要在主线程或父窗口中手动映射这个消息,手动映射消息的方法属于VC基础性内容,就不在这里讲解了,本站VC串口通信技术资料集有很多CSerialPort类的应用实例,大家可以参考,以下本资料中一个实例 串口调试助手SComAssistant的串口接收源代码,OnCommunication函数是WM_COMM_RXCHAR消息的映射函数:
1.LONG
CSCOMMDlg:
OnCommunication(WPARAM
ch,
LPARAM
port)
2.{
if
(port
<
=
0
||
port
4)
-1;
rxdatacount++;
//接收的字节计数
strTemp;
strTemp.Format("
%ld"
rxdatacount);
strTemp="
+strTemp;
m_ctrlRXCOUNT.SetWindowText(strTemp);
//显示接收计数
if(m_bStopDispRXData)
//如果选择了“停止显示”接收数据,则返回
//注意,这种情况下,计数仍在继续,只是不显示
//若设置了“自动清空”,则达到50行后,自动清空接收编辑框中显示的数据
if((m_ctrlAutoClear.GetCheck())&
&
(m_ctrlReceiveData.GetLineCount()>
=50))
m_ReceiveData.Empty();
UpdateData(FALSE);
//如果没有“自动清空”,数据行达到400后,也自动清空
//因为数据过多,影响接收速度,显示是最费CPU时间的操作
if(m_ctrlReceiveData.GetLineCount()>
400)
m_ReceiveData="
***The
Length
of
the
Text
is
too
long,
Emptied
Automaticly!
!
***\r\n"
//如果选择了"
十六进制显示"
,则显示十六进制值
str;
if(m_ctrlHexReceieve.GetCheck())
str.Format("
%02X
ch);
//以下是将接收的字符加在字符串的最后,这里费时很多
//但考虑到数据需要保存成文件,所以没有用List
Control
nLen=m_ctrlReceiveData.GetWindowTextLength();
m_ctrlReceiveData.SetSel(nLen,
nLen);
m_ctrlReceiveData.ReplaceSel(str);
nLen+=str.GetLength();
m_ReceiveData+=str;
43.}
4、串口API如何读串口
以上各串口编程方法的实质都是调用了API的,只是被封装了而已,读串口的API函数是ReadFile,由于不知道何时串口收到数据,所以一般需要开一个线程不停地用ReadFile来读串口。
在用ReadFile读串口时,既可以同步执行,也可以重叠执行。
在同步执行时,函数直到操作完成后才返回。
这意味着同步执行时线程会被阻塞,从而导致效率下降。
在重叠执行时,即使操作还未完成,这个函数也会立即返回,费时的I/O操作在后台进行。
ReadFile函数是同步还是异步由CreateFile函数决定,如果在调用CreateFile创建句柄时指定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile对该句柄进行的操作就应该是重叠的;
如果未指定重叠标志,则读写操作应该是同步的。
ReadFile和WriteFile函数的同步或者异步应该和CreateFile函数相一致。
ReadFile函数只要在串口输入缓冲区中读入指定数量的字符,就算完成操作。
如果操作成功,这个函数返回TRUE。
需要注意的是,当ReadFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果。
例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING。
这说明重叠操作还未完成。
同步方式读写串口比较简单,下面先是同步方式读写串口的代码示例:
1.//同步读串口
2.char
str[100];
3.DWORD
wCount;
//读取的字节数
4.BOOL
bReadStat;
5.bReadStat=ReadFile(hCom,str,100,&
wCount,NULL);
6.if(!
bReadStat)
7.{
AfxMessageBox("
读串口失败!
FALSE;
10.}
11.return
TRUE;
13.//同步写串口
lpOutBuffer[100];
DWORD
dwBytesWrite=100;
COMSTAT
ComStat;
dwErrorFlags;
BOOL
bWriteStat;
ClearCommError(hCom,&
dwErrorFlags,&
ComStat);
bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,&
dwBytesWrite,NULL);
if(!
bWriteStat)
写串口失败!
PurgeComm(hCom,
PURGE_TXABORT|
PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
在重叠操作时,操作还未完成函数就返回。
重叠I/O非常灵活,它也可以实现阻塞(例如我们可以设置一定要读取到一个数据才能进行到下一步操作)。
有两种方法可以等待操作完成:
一种方法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED结构的hEvent成员;
另一种方法是调用GetOverlappedResult函数等待。
OVERLAPPED结构和GetOverlappedResult函数请查看MSDN,本站VC串口通信资料集中也有详细详述。
异步读串口的示例代码:
1.char
lpInBuffer[1024];
2.DWORD
dwBytesRead=1024;
3.COMSTAT
4.DWORD
5.OVERLAPPED
m_osRead;
6.memset(&
m_osRead,0,sizeof(OVERLAPPED));
7.m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
9.ClearCommError(hCom,&
10.dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
11.if(!
dwBytesRead)
12.return
13.BOOL
bReadStatus;
14.bReadStatus=ReadFile(hCom,lpInBuffer,
dwBytesRead,&
m_osRead);
17.if(!
bReadStatus)
//如果ReadFile函数返回FALSE
18.{
if(GetLastError()==ERROR_IO_PENDING)
//GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
WaitForSingleObject(m_osRead.hEvent,2000);
//使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟
//当串口读操作进行完毕后,m_osRead的hEvent事件会变为有信号
dwBytesRead;
30.}
31.PurgeComm(hCom,
33.return
对以上代码再作简要说明:
在使用ReadFile函数进行读操作前,应先使用ClearCommError函数清除错误。
ClearCommError函数的原型如下:
1.BOOL
ClearCommError(
2.
HANDLE
hFile,
//
串口句柄
LPDWORD
lpErrors,
指向接收错误码的变量
LPCOMSTAT
lpStat
指向通讯状态缓冲区
该函数获得通信错误并报告串口的当前状态,同时,该函数清除串口的错误标志以便继续输入、输出操作。
参数lpStat指向一个COMSTAT结构,该结构返回串口状态信息。
COMSTAT结构COMSTAT结构包含串口的信息,结构定义如下:
1.typedef
struct
_COMSTAT
cst
fCtsHold
1;
Tx
waiting
for
CTS
signal
fDsrHold
DSR
fRlsdHold
RLSD
DWO