﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-C++学习之旅</title><link>http://www.cppblog.com/asdjy123/</link><description>每天进步一小步</description><language>zh-cn</language><lastBuildDate>Sat, 04 Apr 2026 20:29:50 GMT</lastBuildDate><pubDate>Sat, 04 Apr 2026 20:29:50 GMT</pubDate><ttl>60</ttl><item><title>最常见的20种VC++编译错误信息</title><link>http://www.cppblog.com/asdjy123/archive/2012/09/12/190395.html</link><dc:creator>梦的飞翔</dc:creator><author>梦的飞翔</author><pubDate>Wed, 12 Sep 2012 07:34:00 GMT</pubDate><guid>http://www.cppblog.com/asdjy123/archive/2012/09/12/190395.html</guid><wfw:comment>http://www.cppblog.com/asdjy123/comments/190395.html</wfw:comment><comments>http://www.cppblog.com/asdjy123/archive/2012/09/12/190395.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/asdjy123/comments/commentRss/190395.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/asdjy123/services/trackbacks/190395.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 1、<strong>fatal error C1010: unexpected end of file while looking for precompiled header directive。</strong><br />　　　寻找预编译头文件路径时遇到了不该遇到的文件尾。（一般是没有#include "stdafx.h"） <br /><br />　　2、<strong>fatal error C1083: Cannot open include file: 'R&#8230;&#8230;.h': No such file or directory</strong><br />　　　　不能打开包含文件&#8220;R&#8230;&#8230;.h&#8221;：没有这样的文件或目录。<br /><br />　　3、<strong>error C2011: 'C&#8230;&#8230;': 'class' type redefinition</strong><br />　　　　类&#8220;C&#8230;&#8230;&#8221;重定义。<br /><br />　　4、<strong>error C2018: unknown character '0xa3'</strong><br />　　　　不认识的字符'0xa3'。（一般是汉字或中文标点符号）<br /><br />　　5、error C2057: expected constant expression<br />　　　　希望是常量表达式。（一般出现在switch语句的case分支中）<br /><br />　　6、<strong>error C2065: 'IDD_MYDIALOG' : undeclared identifier</strong><br />　　　　&#8220;IDD_MYDIALOG&#8221;：未声明过的标识符。<br /><br />　　7、<strong>error C2082: redefinition of formal parameter 'bReset'</strong><br />　　　　函数参数&#8220;bReset&#8221;在函数体中重定义。<br /><br />　　8、<strong>error C2143: syntax error: missing ':' before '{' </strong><br />　　　　句法错误：&#8220;{&#8221;前缺少&#8220;；&#8221;。<br /><br />　　9、<strong>error C2146: syntax error : missing ';' before identifier 'dc'</strong><br />　　　　句法错误：在&#8220;dc&#8221;前丢了&#8220;；&#8221;。<br /><br />　　10、<strong>error C2196: case value '69' already used</strong><br />　　　　值69已经用过。（一般出现在switch语句的case分支中）<br /><br />　　11、<strong>error C2509: 'OnTimer' : member function not declared in 'CHelloView'</strong><br />　　　　成员函数&#8220;OnTimer&#8221;没有在&#8220;CHelloView&#8221;中声明。<br /><br />　　12、<strong>error C2511: 'reset': overloaded member function 'void (int)' not found in 'B'</strong><br />　　　　重载的函数&#8220;void reset(int)&#8221;在类&#8220;B&#8221;中找不到。<br /><br />　　13、<strong>error C2555: 'B::f1': overriding virtual function differs from 'A::f1' only by return type or calling convention</strong><br />　　　　类B对类A中同名函数f1的重载仅根据返回值或调用约定上的区别。<br /><br />　　14、<strong>error C2660: 'SetTimer' : function does not take 2 parameters</strong><br />　　　　&#8220;SetTimer&#8221;函数不传递2个参数。<br /><br />　　15、<strong>warning C4035: 'f&#8230;&#8230;': no return value</strong><br />　　　　&#8220;f&#8230;&#8230;&#8221;的return语句没有返回值。<br /><br />　　16、<strong>warning C4553: '= =' : operator has no effect; did you intend '='?</strong><br />　　　　没有效果的运算符&#8220;= =&#8221;；是否改为&#8220;=&#8221;？<br /><br />　　17、warning C4700: local variable 'bReset' used without having been initialized<br />　　　　局部变量&#8220;bReset&#8221;没有初始化就使用。<br /><br />　　18、<strong>error C4716: 'CMyApp::InitInstance' : must return a value</strong><br />　　　　&#8220;CMyApp::InitInstance&#8221;函数必须返回一个值。<br /><br />　　19、<strong>LINK : fatal error LNK1168: cannot open Debug/P1.exe for writing</strong><br />　　　　连接错误：不能打开P1.exe文件，以改写内容。（一般是P1.Exe还在运行，未关闭）<br /><br />　　20、<strong>error LNK2001: unresolved external symbol "public: virtual _ _thiscall C&#8230;&#8230;::~C&#8230;&#8230;(void)" </strong><br />　　　　连接时发现没有实现的外部符号（变量、函数等）。<br /><img src ="http://www.cppblog.com/asdjy123/aggbug/190395.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/asdjy123/" target="_blank">梦的飞翔</a> 2012-09-12 15:34 <a href="http://www.cppblog.com/asdjy123/archive/2012/09/12/190395.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>不用CerialPort写串口简单通信</title><link>http://www.cppblog.com/asdjy123/archive/2012/09/10/190103.html</link><dc:creator>梦的飞翔</dc:creator><author>梦的飞翔</author><pubDate>Mon, 10 Sep 2012 06:23:00 GMT</pubDate><guid>http://www.cppblog.com/asdjy123/archive/2012/09/10/190103.html</guid><wfw:comment>http://www.cppblog.com/asdjy123/comments/190103.html</wfw:comment><comments>http://www.cppblog.com/asdjy123/archive/2012/09/10/190103.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/asdjy123/comments/commentRss/190103.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/asdjy123/services/trackbacks/190103.html</trackback:ping><description><![CDATA[没用过cserialPort
自己常用这样
创建线程监听吧
贴下代码给你参考
//初始化打开IO端口
void CgameDlg::init_io_com()
{
//打开串口，设置串口
hCom=CreateFile(
TEXT("COM1"),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
//检测打开串口操作是否成功
//若成功则建立线程监听端口
if(hCom!=INVALID_HANDLE_VALUE)
{
SetupComm( hCom,1024,1024) ; //设置输入、输出缓冲区的大小
COMMTIMEOUTS CommTimeOuts ; //定义超时结构，并填写该结构
CommTimeOuts.ReadIntervalTimeout=MAXDWORD; //把间隔超时设为最大，把总超时设为0将导致ReadFile立即返回并完成操作   
  CommTimeOuts.ReadTotalTimeoutMultiplier=0; //读时间系数   
CommTimeOuts.ReadTotalTimeoutConstant=0; //读时间常量   
CommTimeOuts.WriteTotalTimeoutMultiplier=1000;//总超时=时间系数*要求读/写的字符数+时间常量   
CommTimeOuts.WriteTotalTimeoutConstant=2000; //设置写超时以指定WriteComm成员函数中的
SetCommTimeouts( hCom, &CommTimeOuts ) ;//设置读写操作所允许的超时

DCB dcb ; // 定义数据控制块结构
GetCommState(hCom, &dcb ) ; //读串口原来的参数设置
dcb.BaudRate =115200;   
dcb.ByteSize =8;   
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT ;
dcb.fBinary = TRUE ;
dcb.fParity = FALSE;

SetCommState(hCom, &dcb ) ; //串口参数配置

PurgeComm( hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR| PURGE_RXCLEAR ); //清干净输入、输出缓冲区

hCommWatchThread=CreateThread(   
NULL, //安全属性
0, //初始化线程栈的大小，缺省为与主线程大小相同
CommWatchProc, //线程的全局函数
AfxGetMainWnd()->m_hWnd, //此处传入了主框架的句柄
0,   
NULL   
);
}
//若不成功则提示用户打开端口出错
else
{
AfxMessageBox(L"IO板连接串口被占用或不存在");
}
}
//监听函数
//初始化IO板子的监听
DWORD WINAPI CommWatchProc(LPVOID lpParameter)
{
//定义存储监听到的数据的数组
DWORD dwEvtMask=0;
while(true)
{
SetCommMask(hCom, EV_RXCHAR|EV_TXEMPTY );//有哪些串口事件需要监视？
WaitCommEvent(hCom, &dwEvtMask,0); // 等待串口通信事件的发
Sleep(20);
memset(&lpInBuffer,'\0',sizeof(lpInBuffer));
cBytes=ReadPort(hCom,lpInBuffer);
if(cBytes>0)
{
::PostMessage((HWND)lpParameter,WM_RECVDATA1,0,0);
}
}
return 0;
}
//读取端口的函数
int ReadPort(HANDLE hCom,char buffer[1000])
{

  DWORD dwBytesRead=1000;
BOOL bReadStatus;
DWORD dwErrorFlags;
COMSTAT ComStat;
  OVERLAPPED m_osRead;
memset(&m_osRead,0,sizeof(OVERLAPPED));
  m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

ClearCommError(hCom,&dwErrorFlags,&ComStat);
if(!ComStat.cbInQue)
{
return 0;
}
dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
bReadStatus=ReadFile(hCom, buffer,dwBytesRead,
&dwBytesRead,&m_osRead);
if(!bReadStatus) //如果ReadFile函数返回FALSE
{
if(GetLastError()==ERROR_IO_PENDING)
{
GetOverlappedResult(hCom,&m_osRead,&dwBytesRead,TRUE);
  // GetOverlappedResult函数的最后一个参数设为TRUE，
  //函数会一直等待，直到读操作完成或由于错误而返回。
return dwBytesRead;
}
return 0;
}
return dwBytesRead;
}
//写串口的函数
int WritePort(HANDLE hCom,char buffer[],DWORD len)
{
  DWORD dwBytesWritten=len;
  OVERLAPPED m_osWrite;
BOOL bWriteStat;
memset(&m_osWrite,0,sizeof(OVERLAPPED));
  m_osWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

bWriteStat=WriteFile(hCom,buffer,dwBytesWritten,
&dwBytesWritten,&m_osWrite);
if(!bWriteStat)
{
if(GetLastError()==ERROR_IO_PENDING)
{
WaitForSingleObject(m_osWrite.hEvent,1000);
return dwBytesWritten;
}
return 0;
}
return dwBytesWritten;
}<img src ="http://www.cppblog.com/asdjy123/aggbug/190103.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/asdjy123/" target="_blank">梦的飞翔</a> 2012-09-10 14:23 <a href="http://www.cppblog.com/asdjy123/archive/2012/09/10/190103.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2410串口通信编程的总结</title><link>http://www.cppblog.com/asdjy123/archive/2012/09/06/189704.html</link><dc:creator>梦的飞翔</dc:creator><author>梦的飞翔</author><pubDate>Thu, 06 Sep 2012 06:44:00 GMT</pubDate><guid>http://www.cppblog.com/asdjy123/archive/2012/09/06/189704.html</guid><wfw:comment>http://www.cppblog.com/asdjy123/comments/189704.html</wfw:comment><comments>http://www.cppblog.com/asdjy123/archive/2012/09/06/189704.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/asdjy123/comments/commentRss/189704.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/asdjy123/services/trackbacks/189704.html</trackback:ping><description><![CDATA[<h3 class="title pre fs1"><span class="tcnt">串口通讯基础及S3C2410 UART控制器</span>&nbsp;&nbsp;<span class="bgc0 fc07 fw0 fs0"></span></h3>
<p style="line-height: 20px" class="tdep clearfix nbw-act fc06"><span class="pleft"><span class="blogsep">2007-04-12 20:33:57</span><span class="blogsep">|&nbsp;&nbsp;分类：</span> <a class="fc03 m2a" title="默认分类" href="http://vinson.ye.blog.163.com/blog/#m=0&amp;t=1&amp;c=fks_084064082094088071082094074064084082089064093085086">默认分类</a> <span id="$_blogTagTitle" class="blogsep phide">|&nbsp;&nbsp;标签：</span><span id="$_blogTagInfo" class="fc03 phide"></span> </span><span class="pright fc07 ztag"><span class="blogsep">|</span><span id="$_fontswitch" class="zihao fc03" __1346913741723__="ev_5291146463">字号<span id="$_fontsTypes" class="zihaoshow phide"><span class="zihaoc bdc0"><span class="stag" __1346913741723__="ev_7717310048" index="0" __tabkey__="true"></span><span class="fc04 stag" __1346913741723__="ev_4950428465" index="1" __tabkey__="true">大</span><span class="fc04 stag selected js-fcurrent fc05" __1346913741723__="ev_4349135601" index="2" __tabkey__="true">中</span><span class="fc04 stag" __1346913741723__="ev_6681597752" index="3" __tabkey__="true">小</span></span></span></span></span><span id="$_blog_subscribe" class="pright pnt fc03" __1346913741723__="ev_8550149267"><span class="iblock icn0 icn0-919">&nbsp;</span><a class="m2a">订阅</a></span> </p>
<div></div>
<div class="nbw-blog-start"></div>
<div class="bct fc05 fc11 nbw-blog ztag js-fs2" align="center" __1346913741723__="ev_8065776405">
<table cellspacing="0" cellpadding="0" width="90%" align="center" height="49">
<tbody>
<tr>
<td valign="middle">
<div align="center">
<p align="left">数据通信的基本方式可分为并行通信与串行通信两种：<br />并行通信：是指利用多条数据传输线将一个资料的各位同时传送。它的特点是传输速度快，适用于短距离通信，但要求通讯速率较高的应用场合。<br />串行通信：是指利用一条传输线将资料一位位地顺序传送。特点是通信线路简单，利用简单的线缆就可实现通信，降低成本，适用于远距离通信，但传输速度慢的应用场合。<br /><strong>一、异步通信及其协议</strong><br />异步通信以一个字符为传输单位，通信中两个字符间的时间间隔是不固定的，然而在同一个字符中的两个相邻位代码间的时间间隔是固定的。<br />通信协议（通信规程）：是指通信双方约定的一些规则。在使用异步串口传送一个字符的信息时，对资料格式有如下约定：规定有空闲位、起始位、资料位、奇偶校验位、停止位。<br />异步通讯的时序，如图5-1。<br /><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/14.jpg" width="519" height="80" __1346913741723__="ev_1608412731" /><br />其中各位的意义如下：<br /><strong>起始位</strong>：先发出一个逻辑&#8221;0&#8221;信号，表示传输字符的开始。<br /><strong>资料位</strong>：紧接着起始位之后。资料位的个数可以是4、5、6、7、8等，构成一个字符。通常采用ASCII码。从最低位开始传送，靠时钟定位。<br /><strong>奇偶校验位</strong>：资料位加上这一位后，使得&#8220;1&#8221;的位数应为偶数(偶校验)或奇数(奇校验)，以此来校验资料传送的正确性。<br /><strong>停止位</strong>：它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。<br /><strong>空闲位</strong>：处于逻辑&#8220;1&#8221;状态，表示当前线路上没有资料传送。<br /><strong>波特率</strong>：是衡量资料传送速率的指针。表示每秒钟传送的二进制位数。例如资料传送速率为120字符/秒，而每一个字符为10位，则其传送的波特率为10&#215;120＝1200字符/秒＝1200波特。<br />注：异步通信是按字符传输的，接收设备在收到起始信号之后只要在一个字符的传输时间内能和发送设备保持同步就能正确接收。下一个字符起始位的到来又使同步重新校准（依靠检测起始位来实现发送与接收方的时钟自同步的。<strong>二、资料传送方式</strong><br />根据资料传送方向的不同有以下三种方式。如图5-2所示。<br /><img style="width: 520px; height: 56px" alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/15.jpg" width="536" height="58" __1346913741723__="ev_3274256287" />&nbsp;</p></div></td></tr>
<tr>
<td valign="middle">
<table border="0" cellspacing="1" cellpadding="1" width="97%" align="center">
<tbody>
<tr>
<td width="32%">（1）单工方式</td>
<td width="30%">（2）半双工方式</td>
<td width="38%">（3）全双工方式</td></tr></tbody></table></td></tr>
<tr>
<td valign="middle">
<div align="center">图5-2 资料传送方式</div></td></tr>
<tr>
<td valign="middle">1、单工方式<br />资料始终是从A设备发向B设备。<br />2、 半双工方式<br />资料能从A设备传送到B设备，也能从B设备传送到A设备。在任何时候资料都不能同时在两个方向上传送，即每次只能有一个设备发送，另一个设备接收。但是通讯双方依照一定的通讯协议来轮流地进行发送和接收。<br />3、 全双工方式<br />允许通信双方同时进行发送和接收。这时，A设备在发送的同时也可以接收，B设备亦同。全双工方式相当于把两个方向相反的单工方式组合在一起，因此它需要两条数据传输线。在计算机串行通讯中主要使用半双工和全双工方式。<br /><strong>三、信号传输方式</strong><br />1、基带传输方式<br />在传输线路上直接传输不加调制的二进制信号，如图所示。它要求传送线的频带较宽，传输的数字信号是矩形波。<br />基带传输方式仅适宜于近距离和速度较低的通信。<br /><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/16.jpg" width="261" height="95" __1346913741723__="ev_7107815042" /><br />2、频带传输方式<br />传输经过调制的模拟信号<br />在长距离通信时，发送方要用调制器把数字信号转换成模拟信号，接收方则用解调器将接收到的模拟信号再转换成数字信号，这就是信号的调制解调。<br />实现调制和解调任务的装置称为调制解调器(MODEM)。采用频带传输时，通信双方各接一个调制解调器，将数字信号寄载在模拟信号(载波)上加以传输。因此，这种传输方式也称为载波传输方式。这时的通信线路可以是电话交换网，也可以是专用线。<br />常用的调制方式有三种：<br />调幅、调频和调相，分别如下图所示。<br /><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/17.jpg" width="376" height="256" __1346913741723__="ev_6516403917" />&nbsp;</td></tr></tbody></table>
<table cellspacing="0" cellpadding="0" width="90%" align="center" height="49">
<tbody>
<tr>
<td valign="middle">&nbsp;</td></tr>
<tr>
<td valign="top"><strong>四、串行接口标准</strong><br />串行接口标准：指的是计算机或终端(资料终端设备DTE)的串行接口电路与调制解调器MODEM等(数据通信设备DCE)之间的连接标准。<br /><strong>RS-232C标准</strong><br />RS-232C是一种标准接口，D型插座，采用25芯引脚或9芯引脚的连接器，如图5-5所示。</td></tr>
<tr>
<td valign="top">
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/18.jpg" width="330" height="243" __1346913741723__="ev_8664815553" /></div></td></tr>
<tr>
<td valign="top">
<div align="center"><br />图5-5</div></td></tr>
<tr>
<td valign="top">微型计算机之间的串行通信就是按照RS-232C标准设计的接口电路实现的。如果使用一根电话线进行通信，那幺计算机和MODEM之间的联机就是根据RS-232C标准连接的。其连接及通信原理如图5-6所示<br /></td></tr>
<tr>
<td valign="top">
<div align="center"><img style="width: 520px; height: 108px" alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/19.jpg" width="522" height="109" __1346913741723__="ev_5627162537" /></div></td></tr>
<tr>
<td valign="top">
<div align="center"><br />图5-6</div></td></tr>
<tr>
<td valign="top">
<p align="left"><strong>RS232信号定义</strong><br />RS-232C标准规定接口有25根联机。只有以下9个信号经常使用.<br />引脚和功能分别如下：<br />1. TXD（第2脚）：发送资料线，输出。发送资料到MODEM。<br />2. RXD（第3脚）：接收资料线，输入。接收资料到计算机或终端。<br />3.（第4脚）：请求发送，输出。计算机通过此引脚通知MODEM，要求发送资料。<br />4. （第5脚）：允许发送，输入。发出 作为对的回答，计算机才可以进行发送资料。<br />5.（第6脚）：资料装置就绪(即MODEM准备好)，输入。表示调制解调器可以使用，该信号有时直接接到电源上，这样当设备连通时即有效。<br />6.CD（第8脚）：载波检测(接收线信号测定器)，输入。表示MODEM已与电话线路连接好。<br />7. 如果通信线路是交换电话的一部分，则至少还需如下两个信号：<br />8.RI（第22脚）：振铃指示，输入。MODEM若接到交换台送来的振铃呼叫信号，就发出该信号来通知计算机或终端。<br />9. （第20脚）：资料终端就绪，输出。计算机收到RI信号以后，就发出信号到MODEM作为回答，以控制它的转换设备，建立通信链路。<br />10. GND（第7脚）：信号地<br />逻辑电平<br />RS-232C标准采用EIA电平，规定：<br />&#8220;1&#8221;的逻辑电平在-3V~-15v之间<br />&#8220;0&#8221;的逻辑电平在+3V~+15V之间。<br />由于EIA电平与TTL电平完全不同，必须进行相应的电平转换，MCl488完成TTL电平到EIA电平的转换，MCl489完成EIA电平到ITL电平的转换。还有MAX232可以同时完成TTL-&gt;EIA和EIA-&gt;TTL的电平转换。</p>
<p align="left">除了RS-232C标准以外，还有一些其它的通用的异步串行接口标准，如：</p>
<p align="left"><strong>RS-423A标准</strong><br />为了克服RS-232C的缺点，提高传送速率，增加通信距离，又考虑到与RS-232C的兼容性，美国电子工业协会在1987年提出了RS-423A标准。该标准的主要优点是在接收端采用了差分输入。而差分输入对共模干扰信号有较高的抑制作用，这样就提高了通信的可靠性。RS-423A用-6v表示逻辑&#8220;1&#8221;，用+6v表示逻辑&#8220;0&#8221;，可以直接与RS-232C相接。采用RS-423A标准以获得比RS-232C更佳的通信效果。图5-7是RS423A的连接示意图。</p></td></tr>
<tr>
<td valign="top">
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/20.gif" width="194" height="72" __1346913741723__="ev_9423647027" /></div></td></tr>
<tr>
<td valign="top">
<div align="center">图5-7</div></td></tr>
<tr>
<td valign="top"><strong>RS-422A标准</strong><br />RS-422A总线采用平衡输出的发送器，差分输入的接收器。如图5-8所示。</td></tr>
<tr>
<td valign="top">
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/21.gif" width="219" height="95" __1346913741723__="ev_8937062378" /></div></td></tr>
<tr>
<td valign="top">
<div align="center">图5-8</div></td></tr></tbody></table>
<table cellspacing="0" cellpadding="0" width="90%" align="center">
<tbody>
<tr>
<td valign="middle">&nbsp;</td></tr>
<tr>
<td valign="top">RS-422A的输出信号线间的电压为&#177;2v，接收器的识别电压为&#177;0.2v。共模范围&#177;25v。在高速传送信号时，应该考虑到通信线路的阻抗匹配，一般在接收端加终端电阻以吸收掉反射波。电阻网络也应该是平衡的，如图5-9所示。</td></tr>
<tr>
<td valign="top">
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/22.gif" width="253" height="74" __1346913741723__="ev_9228820271" /></div></td></tr>
<tr>
<td valign="top">
<div align="center">图5-9 为RS-422A平衡输出差分输示意图</div></td></tr>
<tr>
<td valign="top"><strong>RS-485标准</strong><br />RS-485适用于收发双方共享一对线进行通信，也适用于多个点之间共享一对线路进行总线方式联网，但通信只能是半双工的，线路如图5-10所示。</td></tr>
<tr>
<td valign="top">
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/23.gif" width="259" height="148" __1346913741723__="ev_6469830661" /></div></td></tr>
<tr>
<td valign="top">
<div align="center">图5-10</div></td></tr>
<tr>
<td valign="top"><br />典型的RS232到RS422/485转换芯片有：MAX481/483/485/487/488/489/490/491，SN75175/176/184等等，它们均只需单一+5v电源供电即可工作（芯片内部采用电荷泵方式升压）。具体使用方法可查阅有关技术手册。<br /><strong>五、<strong>S3C2410</strong>内置的<strong>UART</strong>控制器</strong><br /><strong>S3C2410</strong>内部具有3个独立的<strong>UART</strong>控制器，每个控制器都可以工作在Interrupt（中断）模式或DMA（直接内存访问）模式，也就是说<strong>UART</strong>控制器可以CPU与<strong>UART</strong>控制器传送资料的时候产生中断或DMA请求。并且每个<strong>UART</strong>均具有16字节的FIFO（先入先出寄存器），支持的最高波特率可达到230.4Kbps<br />图5-11是<strong>S3C2410</strong>内部<strong>UART</strong>控制器的结构图</td></tr>
<tr>
<td valign="top">
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/24.gif" width="473" height="433" __1346913741723__="ev_6645027794" /></div></td></tr>
<tr>
<td valign="top">
<div align="center"><br />图5-11</div></td></tr>
<tr>
<td valign="top"><strong><br /><strong>UART</strong>的操作</strong><br /><strong>UART</strong>的操作分为以下几个部分，分别是：资料发送、资料接收、产生中断、产生波特率、Loopback模式、红外模式以及自动流控模式。<br /><strong>资料发送</strong><br />发送的资料帧格式是可以编程设置的。它包含了起始位、5~8个资料位、可选的奇偶校验位以及1~2位停止位。这些都是通过<strong>UART</strong>的控制寄存器ULCONn 来设置的。<br /><strong>资料接收</strong><br />同发送一样，接收的资料帧格式也是可以进行编程设置的。此外，还具备了检测溢出出错、奇偶校验出错、帧出错等出错检测，并且每种错误都可以置相应的错误标志。<br /></td></tr></tbody></table><strong>自动流控模式<br />S3C2410</strong>的<strong>UART</strong>0和<strong>UART</strong>1都可以通过各自的nRTS和nCTS信号来实现自动流控。<br />在自动流控（AFC）模式下nRTS取决于接收端的状态，而nCTS控制了发送断的操作。具体地说：只有当nCTS有效时（表明接收方的FIFO已经准备就绪来接收资料了），<strong>UART</strong>才会将FIFO中的资料发送出去。在<strong>UART</strong>接收资料之前，只要当接收FIFO有至少2-byte空余的时候，nRTS就会被置为有效。图5-12是<strong>UART</strong>自动流控模式的连接方式 
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/25.gif" width="516" height="200" __1346913741723__="ev_6615157375" /></div>
<div align="center">图5-12</div><strong>中断/DMA请求产生</strong><br /><strong>S3C2410</strong>的每个<strong>UART</strong>都有7种状态，分别是：溢出覆盖（Overrun）错误、奇偶校验错误、帧出错、断线错误、接收就绪、发送缓冲空闲、发送移位器空闲。它们在<strong>UART</strong>状态寄存器UTRSTATn / UERSTATn 中有相应的标志位。 
<p><strong>波特率发生器</strong><br />每个<strong>UART</strong>控制器都有各自的波特率发生器来产生发送和接收资料所用的序列时钟，波特率发生器的时钟源可以CPU内部的系统时钟，也可以从CPU的UCLK 管脚由外部取得时钟信号，并且可以通过 UCONn选择各自的时钟源。<br />波特率产生的具体计算方法如下：<br />当选择CPU内部时钟时：<br />UBRDIVn=(int)(PCLK/(bps*16))-1,bps为所需要的波特率值，PCLK为CPU内部外设总线（APB）的工作时钟。<br />当需要得到更精确的波特率时，可以选择由 UCLK引入的外部时钟来生成。<br />UBRDIVn=(int)(UCLK/(bps*16))-1<br /><strong>LoopBack操作模式</strong><br /><strong>S3C2410</strong> CPU的<strong>UART</strong>提供了一种测试模式，也就是这里所说的LoopBack模式。在设计系统的具体应用时，为了判断通讯故障是由于外部的数据链路上的问题，还是CPU内驱动程序或CPU本身的问题，这就需要采用LoopBack模式来进行测试。在LoopBack模式中，资料发送端TXD在<strong>UART</strong>内部就从逻辑上与接收端RXD连在一起，并可以来验证资料的收发是否正常。<br /><strong><strong>UART</strong>控制寄存器</strong><br />下面将针对<strong>UART</strong>的各个控制寄存器逐一进行讲解，以期对<strong>UART</strong>的操作和设置能有更进一步的了解。</p>
<p>ULCONn （<strong>UART</strong> Line ControlRegister）见图5-13</p>
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/26.gif" width="515" height="290" __1346913741723__="ev_7116328237" /></div>
<div align="center">图5-13</div>
<div align="left">Word Length ：资料位长度<br />Number of Stop Bit ：停止位数<br />Parity Mode ：奇偶校验位类型<br />Infra-Red Mode ：<strong>UART</strong>/红外模式选择（当以<strong>UART</strong>模式工作时，需设为&#8220;0&#8221;） 
<p>UCONn （<strong>UART</strong> ControlRegister）见图5-14<br />Receive Mode：选择接收模式。如果是采用DMA模式的话，还需要指定说使用的DMA信道。<br />Transmit Mode ：同上。<br />Send Break Signal ：选择是否在传1帧资料中途发送Break信号。<br />Loopback Mode ：选择是否将<strong>UART</strong>置于Loopback测试模式。<br />Rx Error Status Interrupt Enable：选择是否使能当发生接收异常时，是否产生接收错误中断。<br />Rx Time Out Enable ：是否使能接收超时中断。<br />Rx Interrupt Type ：选择接收中断类型。<br />选择0：Pulse（脉冲式/边沿式中断。非FIFO模式时，一旦接收缓冲区中有资料，即产生一个中断；为FIFO模式时，一旦当FIFO中的资料达到一定的触发水平后，即产生一个中断）</p></div>
<table>
<tbody>
<tr>
<td></td></tr>
<tr>
<td valign="top">&nbsp;</td></tr>
<tr>
<td></td></tr>
<tr>
<td valign="top">&nbsp;</td></tr>
<tr>
<td></td></tr>
<tr>
<td valign="top">&nbsp;</td></tr>
<tr>
<td></td></tr>
<tr>
<td valign="top">&nbsp;</td></tr>
<tr>
<td></td></tr>
<tr>
<td valign="top">&nbsp;</td></tr>
<tr>
<td></td></tr>
<tr>
<td valign="top">&nbsp;</td></tr>
<tbody>
<tr>
<td valign="middle">&nbsp;</td></tr>
<tr>
<td valign="top">选择1：Level（电平模式中断。非FIFO模式时，只要接收缓冲区中有资料，即产生中断；为FIFO模式时，只要FIFO中的资料达到触发水平后，即产生中断）<br />Tx Interrupt Type ：类同于Rx Interrupt Type<br />Clock Selection ：选择<strong>UART</strong>波特率发生器的时钟源。</td></tr>
<tr>
<td valign="top">
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/514.gif" width="516" height="588" __1346913741723__="ev_7580477442" /></div></td></tr>
<tr>
<td valign="top">
<div align="center">图5-14</div></td></tr>
<tr>
<td valign="top">UFCONn （<strong>UART</strong> FIFOConrtol Register）见图5-15<br />FIFO Enable ：FIFO使能选择。<br />Rx FIFO Reset：选择当复位接收FIFO时是否自动清除FIFO中的内容。<br />Tx FIFO Reset：选择当复位发送FIFO时是否自动清除FIFO中的内容。<br />Rx FIFO Trigger Level ：选择接收FIFO的触发水平。<br />Tx FIFO Trigger Level ：选择发送FIFO的触发水平。</td></tr>
<tr>
<td valign="top">
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/515.gif" width="516" height="195" __1346913741723__="ev_3550302840" /></div></td></tr>
<tr>
<td valign="top">
<div align="center">图5-15</div></td></tr>
<tr>
<td valign="top">UMCONn （<strong>UART</strong> ModemControl Register）见图5-16<br />Request to Send ：如果在AFC模式下，该位将由<strong>UART</strong>控制器自动设置；否则的话就必须由用户的软件来控制。<br />Auto Flow Control ：选择是否使能自动流控（AFC）。</td></tr>
<tr>
<td valign="top">
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/516.gif" width="516" height="141" __1346913741723__="ev_5487075658" /></div></td></tr>
<tr>
<td valign="top">
<div align="center">图5-16</div></td></tr>
<tr>
<td valign="top">UTRSTATn （<strong>UART</strong> TX/RXStatus Register）见图5-17<br />Receive buffer data ready :当接收缓冲寄存器从<strong>UART</strong>接收端口接收到有效资料时将自动置&#8220;1&#8221;。反之为&#8220;0&#8221;则表示缓冲器中没有资料。<br />Transmit buffer empty：当发送缓冲寄存器中为空，自动置&#8220;1&#8221;；反之表明缓冲器中正有资料等待发送。<br />Transmitter empty：当发送缓冲器中已经没有有效资料时，自动置&#8220;1&#8221;；反之表明尚有资料未发送。</td></tr>
<tr>
<td valign="top">
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/517.gif" width="516" height="318" __1346913741723__="ev_9865503755" /></div></td></tr>
<tr>
<td valign="top">
<div align="center">图5-17</div></td></tr>
<tr>
<td valign="top">UERSTATn （<strong>UART</strong> ErrorStatus Register）见图5-18<br />Overrun Error ：为&#8220;1&#8221;，表明发生Overrun错误。<br />Frame Error ：为&#8220;1&#8221;。表明发生Frame（帧）错误。</td></tr>
<tr>
<td valign="top"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/518.gif" width="516" height="185" __1346913741723__="ev_1230309226" /></td></tr>
<tr>
<td valign="top">
<div align="center">图5-18</div></td></tr>
<tr>
<td valign="top">UFSTATn　：（<strong>UART</strong>　FIFOStatus Register）见图5-19<br />Rx FIFO Count :接收FIFO中当前存放的字节数。<br />　Tx FIFO Count :发送FIFO中当前存放的字节数。<br />　Rx FIFO Full :为&#8220;1&#8220;表明接收FIFO已满。<br />　Tx FIFO Full :为&#8220;1&#8220;表明发送FIFO已满。</td></tr>
<tr>
<td valign="top">
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/519.gif" width="515" height="178" __1346913741723__="ev_1256090957" /></div></td></tr>
<tr>
<td valign="top">
<div align="center"><br />图5-19</div></td></tr>
<tr>
<td valign="top">UMSTATn　：（<strong>UART</strong>　FIFOStatus Register）见图5-20<br />Clear to Send ：为&#8220;0&#8221;表示CTS无效；为&#8220;1&#8221;表示CTS有效。<br />Delta CTS：指示自从上次CPU访问该位后，nCTS的状态有无发生改变。<br />为&#8220;0&#8221;则说明不曾改变；反之表明nCTS信号已经变化了。</td></tr>
<tr>
<td valign="top">
<div align="center"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/520.gif" width="516" height="149" __1346913741723__="ev_9744407557" /></div></td></tr>
<tr>
<td valign="top">
<div align="center"><br />图5-20</div></td></tr>
<tr>
<td valign="top">
<p>UTXHn 和 URXHn 分别是<strong>UART</strong>发送和接收资料寄存器<br />这两个寄存器存放着发送和接收的资料，当然只有一个字节８位资料。需要注意的是在发生溢出错误的时候，接收的资料必须要被读出来，否则会引发下次溢出错误</p>
<p>UBRDIVn ：（<strong>UART</strong> Baud Rate DivisorRegister）见图5-21</p></td></tr>
<tr>
<td valign="top"><img alt="" src="http://www.dz863.com/myimg/uploadimg/20060101/521.gif" width="516" height="50" __1346913741723__="ev_8497692060" /></td></tr>
<tr>
<td valign="top">
<div align="center">图5-21</div></td></tr>
<tr>
<td valign="top">关于<strong>UART</strong>波特率的计算方法，在前面的内容中已经有详细的阐述，此处不做多余说明。 
<p><strong>小结</strong>：读写状态寄存器UTRSTAT以及错误状态寄存UERSTAT，可以反映芯片目前的读写状态以及错误类型。FIFO状态寄存器UFSTAT 和MODEM 状态寄存器UMSTAT，通过前者可以读出目前FIFO是否满以及其中的字节数；通过后者可以读出目前MODEM 的CTS状态</p></td></tr></tbody></table></div><img src ="http://www.cppblog.com/asdjy123/aggbug/189704.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/asdjy123/" target="_blank">梦的飞翔</a> 2012-09-06 14:44 <a href="http://www.cppblog.com/asdjy123/archive/2012/09/06/189704.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++学习之路1--简单而强大的多线程串口编程工具CserialPort类（附VC基于MFC单文档协议通讯源程序及详细编程步骤）</title><link>http://www.cppblog.com/asdjy123/archive/2012/09/06/189692.html</link><dc:creator>梦的飞翔</dc:creator><author>梦的飞翔</author><pubDate>Thu, 06 Sep 2012 05:53:00 GMT</pubDate><guid>http://www.cppblog.com/asdjy123/archive/2012/09/06/189692.html</guid><wfw:comment>http://www.cppblog.com/asdjy123/comments/189692.html</wfw:comment><comments>http://www.cppblog.com/asdjy123/archive/2012/09/06/189692.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/asdjy123/comments/commentRss/189692.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/asdjy123/services/trackbacks/189692.html</trackback:ping><description><![CDATA[<table style="width: 666px; height: 4868px" border="0" cellspacing="1" cellpadding="0" width="666">
<tbody>
<tr>
<td style="padding-bottom: 0.75pt; padding-left: 0.75pt; width: 407.25pt; padding-right: 0.75pt; padding-top: 0.75pt" width="543">
<h1><span style="font-family: 黑体; color: #006666">简单而强大的多线程串口编程工具CserialPort类（附VC基于MFC单文档协议通讯源程序及详细编程步骤）</span><span style="color: #006666"></span></h1>
<p align="center"><span style="color: #006666">作者：龚建伟&nbsp; 2001.11.09（任意转载，请注明来自啸峰工作室及网址）</span></p>
<p align="center"><span style="color: #006666">　</span></p></td></tr>
<tr>
<td style="padding-bottom: 0.75pt; padding-left: 0.75pt; width: 407.25pt; padding-right: 0.75pt; padding-top: 0.75pt" width="543">
<p align="center"></p></td></tr>
<tr>
<td style="padding-bottom: 0.75pt; padding-left: 0.75pt; width: 100%; padding-right: 0.75pt; padding-top: 0.75pt" valign="top" width="100%">
<p><span style="color: #006666"><br /><br />&nbsp;&nbsp;&nbsp; 老有人觉得MSComm通讯控件很土，更有人大声疾呼：忘了它吧。确实当我们对串口编程有了一定的了解后，应该用API函数写一个属于自己的串口程序，由于编程者对程序了解，对程序修改自如。但我一直没有停止过用MSComm通讯控件，那么简单的东西，对付简单的任务完全可以，但当我们需要在程序中用多个串口，而且还要做很多复杂的处理，那么最好不用MSComm通讯控件，如果这时你还不愿意自己编写底层，就用这个类：CserialPort类。<br /><br />这是Remon Spekreijse写的一个串口类， 地址在：&nbsp; </span></p>
<p><span style="color: #006666">&nbsp;<a href="http://codeguru.earthweb.com/network/serialport.shtml" target="_blank">http://codeguru.earthweb.com/network/serialport.shtml</a><br /><br />类作者Remon Spekreijse已作了一个基于对话框的同时检测4个串口示例的程序，在上面的网址和我主页的串口源码下载页也可以找到。我在这儿主要介绍如何将这个类应用到VC中基于文档的程序中。为了加深对串口数据处理的了解，我们利用这个类解决如下问题： </span></p>
<p><span style="color: #006666"><br /><strong>问题：</strong></span></p>
<p><span style="color: #006666"><br />串口2（COM2）每隔1秒向串口1（COM1）发送的NEMA格式的报文：串头为$，串尾为＊，中间为一个xxxx的整数（ 比如2345,不足4位则前面以0代替代），最后是hh校验，规定hh为xxxx四个数的半BYTE校验和,最后加上回车&lt;CR&gt;与换行&lt;LF&gt;。整个数据包为$xxxx*hh&lt;CR&gt;&lt;LF&gt;。<br />串口1收到上述报文后，校验正确后，将发来的数据显示在视窗中，并记下发来的正确帧数和错误帧数，若正确，还向串口2发送Y，串口2收到Y后将收到的Y的计数显示在视窗中。<br />测试方法：<br />将三线制串口线联接上同一台计算机的两个串口，编好程序后就可测试。如果没有两个串口的微机，自己改改程序。<br /><br />好了，你可以先下载源程序： <a href="http://www.gjwtech.com/download/scporttest.zip">scporttest.zip（大小：49KB，VC6，WIN9X/2000，SerialPort.h SerialPort.cpp是两个类文件）</a><br /><br /><strong>编程步骤：</strong></span></p>
<p><span style="color: #006666"><br />&#9670;1. 建立程序：<br />建立一个基于单文档的MFC应用程序SCPortTest，所有步骤保持缺省状态。</span></p>
<p><span style="color: #006666"><br />&#9670;2. 添加类文件：<br />将SerialPort.h SerialPort.cpp两个类文件复制到工程文件夹中，用Project-Add to Project-Files命令将上述两个文件加入工程。并在SCPortTestView.h中将头文件SerialPort.h说明：#include "SerialPort.h"。</span></p>
<p><span style="color: #006666"><br />&#9670;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&nbsp;<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 />{ &#8230;.. }<br />注意：由于这个串口类加入工程后，没有自动的消息映射机制，因此上述步骤均需要手工添加。</span></p>
<p><span style="color: #006666"><br />&#9670;4 初始化串口<br />在视创建时初始化串口，首先利用ClassWizardr按下图生成OnInitialUpdate()函数。</span></p>
<p><span style="color: #006666"><br /></span></p>
<p><span style="color: #006666"><br />接着在SerialPort.h文件中说明我们在程序中要用到的全局变量：<br />保存两个串口接收数据：&nbsp;<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&nbsp;<br /><br />再在SerialPort.h文件中说明串口类对象：CSerailPort m_ComPort[2]; （public）。<br />因为要初始化2个串口，所以这里用了数组。<br />下面是初始化串口1和串口2：<br />void CSCPortTestView::OnInitialUpdate()&nbsp;<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&lt;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 />}&nbsp;<br /><br />&#9670;5 利用ClassWizard按下图生成CSCPortTestView 的时间消息WM_TIMER响应函数：</span></p>
<p><span style="color: #006666"><br />void CSCPortTestView::OnTimer(UINT nIDEvent)&nbsp;<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:</span></p>
<p><span style="color: #006666"><br /><br />void CSCPortTestView::SendString(CString &amp;str, int Port)<br />{<br />char checksum=0,cr=CR,lf=LF;<br />char c1,c2;<br />for(int i=0;i&lt;str.GetLength();i++)<br />checksum = checksum^str[i];<br />c2=checksum &amp; 0x0f; c1=((checksum &gt;&gt; 4) &amp; 0x0f);<br />if (c1 &lt; 10) c1+= '0'; else c1 += 'A' - 10;<br />if (c2 &lt; 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 />请注意上面函数中是如何生成校验码的，要切记的是发送的校验码生成方式和对方接收的校验检测方式要一致。</span></p>
<p style="margin-bottom: 12pt"><span style="color: #006666"><br /><br />&#9670;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接收到数据&nbsp;<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-&gt;TextOut(10,50,strtemp);//显示接收到的数据&nbsp;<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 &amp; 0x0f; c1=((m_chChecksum &gt;&gt; 4) &amp; 0x0f);<br />if (c1 &lt; 10) c1+= '0'; else c1 += 'A' - 10;<br />if (c2 &lt; 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&gt;0)&nbsp;<br />{<br />m_strRXhhCOM1 += ch; //得到收到的校验值hh<br />if(flag==1)&nbsp;<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];&nbsp;<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-&gt;SetTextColor(RGB(255,255,0));<br />pDC-&gt;TextOut(10,10,strDisplay1);//显示接收到的数据&nbsp;<br />pDC-&gt;TextOut(30,30,strDisplay2);//显示错误帧数<br />//pDC-&gt;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 /></span></p></td></tr></tbody></table><img src ="http://www.cppblog.com/asdjy123/aggbug/189692.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/asdjy123/" target="_blank">梦的飞翔</a> 2012-09-06 13:53 <a href="http://www.cppblog.com/asdjy123/archive/2012/09/06/189692.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>stdafx.h、stdafx.cpp是干什么用的 </title><link>http://www.cppblog.com/asdjy123/archive/2012/09/06/189657.html</link><dc:creator>梦的飞翔</dc:creator><author>梦的飞翔</author><pubDate>Thu, 06 Sep 2012 02:59:00 GMT</pubDate><guid>http://www.cppblog.com/asdjy123/archive/2012/09/06/189657.html</guid><wfw:comment>http://www.cppblog.com/asdjy123/comments/189657.html</wfw:comment><comments>http://www.cppblog.com/asdjy123/archive/2012/09/06/189657.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/asdjy123/comments/commentRss/189657.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/asdjy123/services/trackbacks/189657.html</trackback:ping><description><![CDATA[<table style="word-wrap: break-word; table-layout: fixed" border="0" cellspacing="0" cellpadding="0" width="87%">
<tbody>
<tr>
<td class="gray14">stdafx.h、stdafx.cpp是干什么用的？为什么我的每一个cpp文件都必须包含stdafx.h？ <br /><br />&nbsp;&nbsp;&nbsp;&nbsp;Windows和MFC的include文件都非常大，即使有一个快速的处理程序，编译程序也要花费相当长的时间来完成工作。由于每个.CPP文件都包含相同的include文件，为每个.CPP文件都重复处理这些文件就显得很傻了。 <br />&nbsp;&nbsp;&nbsp;&nbsp;为避免这种浪费，AppWizard和Visual&nbsp;C++编译程序一起进行工作，如下所示： <br />&nbsp;&nbsp;&nbsp;&nbsp;&#9678;AppWizard建立了文件stdafx.h，该文件包含了所有当前工程文件需要的MFC&nbsp;include文件。且这一文件可以随被选择的选项而变化。 <br />&nbsp;&nbsp;&nbsp;&nbsp;&#9678;AppWizard然后就建立stdafx.cpp。这个文件通常都是一样的。 <br />&nbsp;&nbsp;&nbsp;&nbsp;&#9678;然后AppWizard就建立起工程文件，这样第一个被编译的文件就是stdafx.cpp。 <br />&nbsp;&nbsp;&nbsp;&nbsp;&#9678;当Visual&nbsp;C++编译stdafx.cpp文件时，它将结果保存在一个名为stdafx.pch的文件里。&nbsp;(扩展名pch表示预编译头文件。) <br />&nbsp;&nbsp;&nbsp;&nbsp;&#9678;当Visual&nbsp;C++编译随后的每个.cpp文件时，它阅读并使用它刚生成的.pch文件。&nbsp;Visual&nbsp;C++不再分析Windows&nbsp;include文件，除非你又编缉了stdafx.cpp或stdafx.h。 <br />&nbsp;&nbsp;&nbsp;&nbsp;这个技术很精巧，你不这么认为吗？(还要说一句，Microsoft并非是首先采用这种技术的公司，Borland才是。)&nbsp;在这个过程中你必须遵守以下规则： <br />&nbsp;&nbsp;&nbsp;&nbsp;&#9678;你编写的任何.cpp文件都必须首先包含stdafx.h。 <br />&nbsp;&nbsp;&nbsp;&nbsp;&#9678;如果你有工程文件里的大多数.cpp文件需要.h文件，顺便将它们加在stdafx.h&nbsp;(后部)上，然后预编译stdafx.cpp。 <br />&nbsp;&nbsp;&nbsp;&nbsp;&#9678;由于.pch文件具有大量的符号信息，它是你的工程文件里最大的文件。 <br />如果你的磁盘空间有限，你就希望能将这个你从没使用过的工程文件中的.pch文件删除。执行程序时并不需要它们，且随着工程文件的重新建立，它们也自动地重新建立。</td></tr></tbody></table><img src ="http://www.cppblog.com/asdjy123/aggbug/189657.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/asdjy123/" target="_blank">梦的飞翔</a> 2012-09-06 10:59 <a href="http://www.cppblog.com/asdjy123/archive/2012/09/06/189657.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>