📄 +=
字号:
建立程序:<BR>建立一个基于单文档的MFC应用程序SCPortTest,所有步骤保持缺省状态。</P>
<P align=left><BR>◆2. 添加类文件:<BR>将SerialPort.h
SerialPort.cpp两个类文件复制到工程文件夹中,用Project-Add to
Project-Files命令将上述两个文件加入工程。并在SCPortTestView.h中将头文件SerialPort.h说明:#include
"SerialPort.h"。</P>
<P align=left><BR>◆3. 人工增加串口消息响应函数:OnCommunication(WPARAM ch, LPARAM
port)<BR>首先在SCPortTestView.h中添加串口字符接收消息WM_COMM_RXCHAR(串口接收缓冲区内有一个字符)的响应函数声明:<BR>//{{AFX_MSG(CSCPortTestView)<BR>afx_msg
LONG OnCommunication(WPARAM ch, LPARAM
port);<BR>//}}AFX_MSG <BR>然后在SCPortTestView.cpp文件中进行WM_COMM_RXCHAR消息映射:<BR>BEGIN_MESSAGE_MAP(CSCPortTestView,
CView)<BR>//{{AFX_MSG_MAP(CSCPortTestView)<BR>ON_MESSAGE(WM_COMM_RXCHAR,
OnCommunication)<BR>//}}AFX_MSG_MAP<BR>END_MESSAGE_MAP()<BR>接着在SCPortTestView.cpp中加入函数的实现:<BR>LONG
CSCPortTestView::OnCommunication(WPARAM ch, LPARAM port)<BR>{ …..
}<BR>注意:由于这个串口类加入工程后,没有自动的消息映射机制,因此上述步骤均需要手工添加。</P>
<P align=left><BR>◆4
初始化串口<BR>在视创建时初始化串口,首先利用ClassWizardr按下图生成OnInitialUpdate()函数。</P>
<P align=left><BR><IMG border=0 height=369
src="简单而强大的多线程串口编程工具CserialPort类.files/serialport01.gif"
width=529></P>
<P
align=left><BR>接着在SerialPort.h文件中说明我们在程序中要用到的全局变量:<BR>保存两个串口接收数据: <BR>char
m_chChecksum; //用于COM1的校验和计算<BR>CString m_strRXhhCOM1;
//用于存放COM1接收的半BYTE校验字节hh<BR>CString m_strRXDataCOM1;
//COM1接收数据<BR>CString m_strRXDataCOM2; //COM2接收数据<BR>UINT
m_nRXErrorCOM1; //COM1接收数据错误帧数<BR>UINT m_nRXErrorCOM2;
//COM2接收数据错误帧数<BR>UINT m_nRXCounterCOM1; //COM1接收数据错误帧数<BR>UINT
m_nRXCounterCOM2;
//COM2接收数据错误帧数CString <BR><BR>再在SerialPort.h文件中说明串口类对象:CSerailPort
m_ComPort[2];
(public)。<BR>因为要初始化2个串口,所以这里用了数组。<BR>下面是初始化串口1和串口2:<BR>void
CSCPortTestView::OnInitialUpdate() <BR>{<BR>CView::OnInitialUpdate();<BR>//
TODO: Add your specialized code here and/or call the base
class<BR>m_chChecksum=0; //校验和置0<BR>m_nRXErrorCOM1=0;
//COM1接收数据错误帧数置0<BR>m_nRXErrorCOM2=0;
//COM2接收数据错误帧数置0<BR>m_nRXCounterCOM1=0;
//COM1接收数据错误帧数置0<BR>m_nRXCounterCOM2=0;
//COM2接收数据错误帧数置0<BR>m_strRXhhCOM1.Empty();
//清空半BYTE校验hh存储变量<BR>for(int i=0;i<2;i++)<BR>{<BR>if
(m_ComPort[i].InitPort(this,i+1,9600,'N',8,1,EV_RXFLAG |
EV_RXCHAR,512))<BR>//portnr=1(2),baud=960,parity='N',databits=8,stopsbits=1,<BR>//dwCommEvents=EV_RXCHAR|EV_RXFLAG,nBufferSize=512<BR>{<BR>m_ComPort[i].StartMonitoring();
//启动串口监视线程<BR>if(i==1) SetTimer(1,1000,NULL);
//设置定时器,1秒后发送数据<BR>}<BR>else<BR>{<BR>CString
str;<BR>str.Format("COM%d
没有发现,或被其它设备占用",i+1);<BR>AfxMessageBox(str);<BR>}<BR>}<BR>} <BR><BR>◆5
利用ClassWizard按下图生成CSCPortTestView 的时间消息WM_TIMER响应函数:</P>
<P align=left><IMG border=0 height=362
src="简单而强大的多线程串口编程工具CserialPort类.files/serialport02.gif"
width=534><BR>void CSCPortTestView::OnTimer(UINT
nIDEvent) <BR>{<BR>// TODO: Add your message handler code here
and/or call default<BR>int randdata=rand()%9000;
//产生9000以内的随机数<BR>CString
strSendData;<BR>strSendData.Format("%04d",randdata);<BR>SendString(strSendData,
2);
//串口2发送数据;<BR>CView::OnTimer(nIDEvent);<BR>}<BR><BR>上面用到的SendString()需按如下方式生成:<BR>在ClassView中单击鼠标右键,在环境菜单中选择Add
Member Function:</P>
<P align=left><IMG border=0 height=241
src="简单而强大的多线程串口编程工具CserialPort类.files/serialport03.gif"
width=486><BR><BR>void CSCPortTestView::SendString(CString &str,
int Port)<BR>{<BR>char checksum=0,cr=CR,lf=LF;<BR>char
c1,c2;<BR>for(int i=0;i<str.GetLength();i++)<BR>checksum =
checksum^str[i];<BR>c2=checksum & 0x0f; c1=((checksum >>
4) & 0x0f);<BR>if (c1 < 10) c1+= '0'; else c1 += 'A' -
10;<BR>if (c2 < 10) c2+= '0'; else c2 += 'A' - 10;<BR>CString
str1;<BR>str1='$'+str+"*"+c1+c2+cr+lf;<BR>m_ComPort[Port-1].WriteToPort((LPCTSTR)str1);<BR>}<BR>请注意上面函数中是如何生成校验码的,要切记的是发送的校验码生成方式和对方接收的校验检测方式要一致。</P>
<P align=left><BR><BR>◆6 在OnCommunication(WPARAM ch, LPARAM
port)函数中进行数据处理<BR>说明:WPARAM、 LPARAM 类型是多态数据类型(polymorphic data
type),在WIN32中为32位,支持多种数据类型,根据需要自动适应,这样程序有很强的适应性。在此我们可以分别理解为char和
integer
类型数据。<BR>每当串口接收缓冲区内有一个字符时,就会产生一个WM_COMM_RXCHAR消息,触发OnCommunication函数,这时我们就可以在函数中进行数据处理,所以这个消息就是整个程序的"发动机"。<BR>下面是根据本文最初提出的问题写出的处理函数:<BR>LONG
CSCPortTestView::OnCommunication(WPARAM ch, LPARAM
port)<BR>{<BR>static int count1=0,count2=0,count3=0;<BR>static char
c1,c2;<BR>static int flag;<BR>CString
strCheck="";<BR><BR>if(port==2) //COM2接收到数据 <BR>{<BR>CString
strtemp=(char)ch;<BR>if(strtemp=="Y")<BR>{<BR>m_nRXCounterCOM2++;<BR>CString
strtemp;<BR>strtemp.Format("COM2: NO.%06d",
m_nRXCounterCOM2);<BR>CDC* pDC=GetDC();
//准备数据显示<BR>pDC->TextOut(10,50,strtemp);//显示接收到的数据 <BR>ReleaseDC(pDC);<BR>}<BR>}<BR><BR>if(port==1)
//COM1接收到数据<BR>{<BR>m_strRXDataCOM1 +=
(char)ch;<BR>switch(ch)<BR>{<BR>case '$':<BR>m_chChecksum=0;
//开始计算CheckSum<BR>flag=0;<BR>break;<BR>case
'*':<BR>flag=2;<BR>c2=m_chChecksum & 0x0f; c1=((m_chChecksum
>> 4) & 0x0f);<BR>if (c1 < 10) c1+= '0'; else c1 += 'A'
- 10;<BR>if (c2 < 10) c2+= '0'; else c2 += 'A' -
10;<BR>break;<BR>case CR:<BR>break;<BR>case
LF:<BR>m_strRXDataCOM1.Empty();<BR>break;<BR>default:<BR>if(flag>0) <BR>{<BR>m_strRXhhCOM1
+= ch; //得到收到的校验值hh<BR>if(flag==1) <BR>{<BR>strCheck =
strCheck+c1+c2; //计算得到的校验值hh<BR>if(strCheck!=m_strRXhhCOM1)
//如果校验有错<BR>{<BR>m_strRXDataCOM1.Empty();<BR>m_nRXErrorCOM1++;
//串口1错误帧数加1<BR>}<BR>else<BR>{<BR>m_nRXCounterCOM1++;<BR>if(m_strRXDataCOM1.Left(1)=="$")
//接收数据的第一个字符是$吗?<BR>{<BR>char tbuf[6];<BR>char
*temp=(char*)((LPCTSTR)m_strRXDataCOM1);<BR>tbuf[0]=temp[1];
tbuf[1]=temp[2]; <BR>tbuf[2]=temp[3];
tbuf[3]=temp[4];<BR>tbuf[4]=0; //0表示字符串的结束,必要<BR>int
data=atoi(tbuf);<BR>CString
strDisplay1,strDisplay2;<BR>strDisplay1.Format("NO. %06d: The
reseived data is
%04d",m_nRXCounterCOM1,data);<BR>strDisplay2.Format("Error
Counter=%04d.",m_nRXErrorCOM1);<BR>CDC* pDC=GetDC();
//准备数据显示<BR>//int
nColor=pDC->SetTextColor(RGB(255,255,0));<BR>pDC->TextOut(10,10,strDisplay1);//显示接收到的数据 <BR>pDC->TextOut(30,30,strDisplay2);//显示错误帧数<BR>//pDC->SetTextColor(nColor);<BR>ReleaseDC(pDC);<BR>}<BR>CString
str1="Y";<BR>m_ComPort[0].WriteToPort((LPCTSTR)str1);//发送应答信号Y<BR>}<BR>m_strRXhhCOM1.Empty();<BR>}<BR>flag--;<BR>}<BR>else<BR>m_chChecksum
^= ch;<BR>break;<BR>}<BR><BR>}<BR>return
0;<BR>}<BR><BR><BR></P></TD></TR></TBODY></TABLE>
<TABLE border=0 cellPadding=1 cellSpacing=1 width=550>
<TBODY>
<TR>
<TD>
<DIV align=center>
<HR align=center color=#99cccc SIZE=2 width=500>
</DIV></TD></TR>
<TR>
<TD vAlign=top width=424>
<P align=center><IMG border=0 height=74
src="简单而强大的多线程串口编程工具CserialPort类.files/coffe.gif" width=57>
</P></TD></TR>
<TR>
<TD>
<DIV align=center>
<HR align=center color=#99cccc SIZE=2 width=500>
</DIV></TD></TR>
<TR>
<TD vAlign=top width=424></TD></TR></TBODY></TABLE> <BR></TD>
<TD align=right background=简单而强大的多线程串口编程工具CserialPort类.files/zhe.gif
height=443 rowSpan=2 vAlign=top width=10> </TD>
<TD align=middle bgColor=#cbe4e4 vAlign=top width=150>
<P align=center>
<SCRIPT language=JavaScript1.1
src="简单而强大的多线程串口编程工具CserialPort类.files/textclick"></SCRIPT>
</P></TD></TR>
<TR>
<TD align=middle bgColor=#cbe4e4 height=18 vAlign=top
width=150> </TD></TR></TBODY></TABLE>
<TABLE align=center border=0 cellPadding=0 cellSpacing=0 height=28 width=758>
<TBODY>
<TR>
<TD background=简单而强大的多线程串口编程工具CserialPort类.files/looker.gif height=16
vAlign=center>
<P
align=right>
<FONT color=#cc3300> </FONT> </P></TD></TR>
<TR>
<TD height=45>
<P align=center>啸峰工作室 龚建伟制作维护 转载本站内容 请注明作者 并说明来自 <A
href="http://roaringwind.best.163.com/">http://roaringwind.best.163.com/</A>
啸峰工作室
<P align=center>
<SCRIPT>var tc_user="roarscomm";var tc_class="2";</SCRIPT>
<SCRIPT src="简单而强大的多线程串口编程工具CserialPort类.files/stat.js"></SCRIPT>
</P>
<P align=center>
<SCRIPT language=JavaScript1.1
src="D:\download\简单而强大的多线程串口编程工具CserialPort类.files\textclick(1).3]"></SCRIPT>
</P></TD></TR></TBODY></TABLE>
<P align=center><A href="mailto:xiaofengstudio@sina.com"
title=您有任何建议或问题,请给我写信><IMG border=0 height=50
src="简单而强大的多线程串口编程工具CserialPort类.files/email3.gif" width=50></A>
</P></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -