找回密码
 免费扫扫注册

扫一扫,访问微社区

QQ登录

只需一步,快速开始

点击进入授权页面

只需一步,快速开始

上位机MFC串口通讯视频教程与源代码

[ 复制链接 ]
上位机MFC串口通讯视频教程与源代码

上位机MFC串口通讯视频教程与源代码

上位机MFC串口通讯视频教程与源代码

上位机MFC串口通讯视频教程与源代码

上位机MFC串口通讯视频教程与源代码

上位机MFC串口通讯视频教程与源代码

上位机MFC串口通讯视频教程与源代码

上位机MFC串口通讯视频教程与源代码

上位机MFC串口通讯视频教程与源代码




01 作者介绍:
           陈贵发
           Grief Chen
           机电一体化专业,07年毕业后一直从事自动化行业。
           刚毕业从自动化设备维修,组装,调试,到接触器系统设计,
           PLC程序,C++上位机程序系统设计,再到视觉程序设计,一步步走来。
           大大小小项目设计无数。也深知从事工控的心酸与不易。
           当今社会牛人都创业,人人都分享,作者也录制与分享工控视频与项目源代码程序,
           发布于 工控编程吧,让大家在工控学习上少走弯路,项目开发上缩短时间。
02 教程介绍:

           串口通讯在工业领域中是极为常用的通讯方式,不管是PLC,触摸屏还是其他智能仪表,
           都支持串口通讯控制。教程中的使用的串口集成类适合RS232串口,RS485并口,并在众多项目中稳定
           运行。部分项目源代码已发布于论坛:
           三菱电阻测量仪MCP T700通讯源代码与视频讲解         
          三菱PLC串口通讯方法源代码与手册
          三菱电阻测量仪MCP T700通讯源代码与视频讲解
          三菱电阻测量仪SM7110 SM7120项目源代码
          honeywell霍尼韦尔扫描枪3310G串口通讯源代码与驱动手册配置工具
          教程结合串口类在一简单项目中的使用(扫描枪串口控制扫码),一步步讲解串口通讯的流程与
           具体操作,还分析关键代码段,使您知其然与所以然,在以后自己项目中使用此集成类畅通无阻。
           视频教程附有源代码,可在项目中直接使用,视频拟分10个部分:
             0.串口类创建并添加串口参数等全局数据类型
            1.串口类成员变量添加与其初始化函数的实现
            2.串口类事件监控函数的实现
            3.串口类事件处理与日志生成函数的实现
            4.串口类串口参数设置与串口开关函数的实现
             5.串口类数据收发与串口复位函数的实现
            6.串口类的使用之连接断开下位机
            7.串口类的使用之数据收发与出错处理
              8.串口类的使用之串口设置界面编写
             9.额外功能之获取当前系统全部串口号


03 适合谁看:
            对串口RS232或并口RS485感兴趣的朋友。
            自己项目需要编写代码通过RS232或RS485控制的朋友。
            有一定C++基础的朋友。刚入门可学习我录制的三套教程快速上手上位机编程
            上位机编程语言基础篇-使用C++
            上位机编程新手上路篇-编写程序
            上位机VC MFC程序开发精典实例大全源码与视频讲解配套下载408例

04 你将获得:
            了解RS232和RS485 串口并口通讯控制的过程
            RS232和RS485串口并口通讯控制通用的集成类与如何使用
            拥有开发RS232和RS485串口并口通讯控制程序的能力

05 您将投资:
           观看没视频的时间约1小时。
           代码编程实践的时间约2小时
           视频与集成类的投资费用100元
           微信上与作者在编程技术上的互动
源码附件
请点击此处下载

请先注册会员后在进行下载

已注册会员,请先登录后下载

文件名称:上位机MFC串口通讯源代码.rar 
下载次数:7  文件大小:206.11 KB  售价:100金币 [记录]
下载权限: 不限 以上或 VIP会员   [购买VIP]   [充值积分]   有问题联系我


源码加视频加课件附件
请点击此处下载

请先注册会员后在进行下载

已注册会员,请先登录后下载

文件名称:上位机MFC串口通讯视频教程与源代码.txt 
下载次数:9  文件大小:133 Bytes  售价:100金币 [记录]
下载权限: 不限 以上或 VIP会员   [购买VIP]   [充值积分]   有问题联系我


  

您的支持是我们创作的动力!  

  

您可花点闲钱积分自助任意充值

  

成为VIP会员 全站资源任意下载永久更新!


  

如果您认可,可联系功能定制!

  

如果您着急,可联系发您资料!

  

QQ联系我

微信扫扫联系我

  


上位机MFC串口通讯视频教程与源代码

上位机MFC串口通讯视频教程与源代码

0.串口类创建并添加串口参数等全局数据类型

关键讲解

  1. <font color="#000000">//0步
  2. #define WM_COMM_BREAK WM_USER+1// A break was detected on input.
  3. #define WM_COMM_CTS    WM_USER+2// The CTS (clear-to-send) signal changed state.
  4. #define WM_COMM_DSR    WM_USER+3// The DSR (data-set-ready) signal changed state.
  5. #define WM_COMM_ERR WM_USER+4// A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY.
  6. #define WM_COMM_RING WM_USER+5// A ring indicator was detected.
  7. #define WM_COMM_RLSD WM_USER+6// The RLSD (receive-line-signal-detect) signal changed state.
  8. #define WM_COMM_RXCHARWM_USER+7// A String was received and placed in the input buffer.
  9. #define WM_COMM_RXFLAG WM_USER+8// The event character was received and placed in the input buffer.  
  10. #define WM_COMM_TXEMPTY     WM_USER+9   // The last character in the output buffer was sent
  11. #define MAXSENDTIMES        50          //Repeat sending times when failed
  12. #define INTERVAL            10          //Internal waiting time when failed
  13. struct COM_PARA
  14. {
  15. UINT   nPortIndex;     
  16. UINT   nBaud;         
  17. CHAR   cParity;        
  18. UINT   nDataBits
  19. UINT   nStopBits
  20. DWORD  dwComEvent};

  21. </font>
复制代码
微软底层串口通讯 函数运行时会触发众多事件,宏WM_USER+1到WM_USER+9用于在触发对应事件时发送出消息。例程是通过虚拟函数来处理对应事件,在子类中要处理什么事件重写函数就好,所以这些宏仅作备用。
宏 MAXSENDTIMES 与INTERVAL用于处理串口通讯异常时重新建立连接。分别表示重连的最大次数与重连的间隔时间。我们都知道工业环境复杂,干扰众多,添加重连功能可以增加我们程序的鲁棒性。
结构体COM_PARA用于处理串口通讯的参数设置,其成员变量与串口参数串口号,波特率,奇偶校验位,数据位个数,停止位,掩码一一对应。

1.串口类成员变量添加与其初始化函数的实现
关键讲解
  1. <font color="#000000">//1步
  2. protected:
  3. CRITICAL_SECTION              m_CS
  4. HANDLE                        m_hWriteEvent;
  5. HANDLE                        m_hComStop;            
  6.     OVERLAPPED                    m_OverLapped;           
  7. OVERLAPPED                    m_WOverLapped;         
  8. OVERLAPPED                    m_ROverLapped;         
  9. CWinThread*                  m_pComThread;           
  10. HANDLE          m_hEventArray[2];      
  11. HANDLE                        m_hPort;               

  12. COM_PARA                      m_ComPara;              
  13. CString                       m_sSendData;            
  14. CString                       m_sLogPath;            

  15. void                          ComInit();
  16. void                          Lock();                 
  17. void                          Unlock();
  18. </font>
复制代码
这些成员变量都为集成类内部函数作用,起衔接数据作用,其具体的作用可以看源代码注释。
这些变量通过函数ComInit进行初始化, ComInit在类的构造函数中进行调用,也就是说,每构造一个类的对象时会自动调用此函数初始化变量。
工程项目中一般都是多线程设计,多线程程序中最大的忌讳就是多线程同时访问修改同一变量时,会使其结果未知。
所以集成类中加入Lock();      Unlock();两函数通过临界区变量避免这情况出现。此两函数需要成对出现。

2.串口类事件监控函数的实现


关键讲解
  1. <font color="#000000">UINT CComPort::ComThreadFunc(LPVOID pParam)
  2. {
  3. CComPort *pCom           = (CComPort*) pParam;
  4. bool     bFucResult      = FALSE;
  5. DWORD    Event           = 0;
  6. DWORD    dwError         = 0;
  7. DWORD    CommEvent       = 0;
  8. COMSTAT  comstat;
  9. while(true)
  10. {
  11. pCom->ComDetectStop();
  12. bFucResult = WaitCommEvent(pCom->m_hPort, &Event, &pCom->m_OverLapped)?true:false;//侦ì测a串?口ú事?件t;
  13. if (!bFucResult)
  14. {
  15. switch (dwError = GetLastError())
  16. {
  17. case ERROR_IO_PENDING: //normal return:no bytes to read
  18. break;
  19. case 87:                //also  valid reply:do nothing
  20. break;
  21. default:               //serious error occured.
  22. {
  23. pCom->PrintErrors(_T( "Communication failed to connect!") );
  24. pCom->Comm_Failed();
  25. return 0;
  26. }
  27. }
  28. }


  29. </font>
复制代码
  1. <font color="#000000">else
  2. {
  3. ClearCommError(pCom->m_hPort, &dwError, &comstat);
  4. if (comstat.cbInQue == 0)
  5. continue;
  6. }
  7. //><
  8.     Event = WaitForMultipleObjects(2, pCom->m_hEventArray, FALSE, 10);
  9. switch(Event)
  10. {
  11. case 0:// read event
  12. {
  13. GetCommMask(pCom->m_hPort, &CommEvent);
  14. if (CommEvent & EV_CTS)
  15. pCom->Comm_CTS();
  16. if (CommEvent & EV_RXFLAG)
  17. pCom->Comm_RXFLAG();
  18. if (CommEvent & EV_BREAK)
  19. pCom->Comm_Break();
  20. if (CommEvent & EV_ERR)
  21. pCom->Comm_ERR();
  22. if (CommEvent & EV_RING)
  23. pCom->Comm_Ring();
  24. if (CommEvent & WM_COMM_DSR)
  25. pCom->Comm_DSR();
  26. if (CommEvent & WM_COMM_RLSD)
  27. pCom->Comm_RLSD();
  28. if (CommEvent & WM_COMM_TXEMPTY)
  29. pCom->Comm_TXEMPTY();
  30. if (CommEvent & EV_RXCHAR)
  31. pCom->ComReadData();
  32. }  

  33. </font>
复制代码
  1. <font color="#000000">break;
  2. case 1: // write event
  3. pCom->ComSendDataExe();   
  4. break;
  5. }
  6. }
  7. //><
  8. return 0;
  9. }
  10. void CComPort::ComDetectStop()
  11. {
  12. DWORD dwResult = WaitForSingleObject(m_hComStop,0);
  13. if(dwResult==WAIT_OBJECT_0 || !m_hPort)
  14. {
  15. AfxEndThread(-1);
  16. }
  17. }
  18. </font>
复制代码
ComThreadFunc是一个线程函数,由打开串口的函数ComOpen调用,实时运行监控串口,带有一个参数,例程中传递的是类的指针CComPort *pCom           = (CComPort*) pParam;可在此线程函数中访问CComPort类数据。函数体内进入死循环监控数据,通过ComDetectStop()判断是否要退出死循环。
列循环内部调用函数WaitCommEvent(函数立即返回)侦测COM事件,正常返回ERROR_IO_PENDING往下执行,异常退出串口通讯。
紧接着调用函数WaitForMultipleObjects处理串口事件,串口读数据由ComReadData()完成,写数据由ComSendDataExe()完成。

3.串口类事件处理与日志生成函数的实现


关键讲解
  1. <font color="#000000">//3步
  2. protected://串口事件处理
  3. virtual void Comm_Break();
  4. virtual void Comm_CTS();
  5. virtual void Comm_DSR();
  6. virtual void Comm_ERR();
  7. virtual void Comm_Ring();
  8. virtual void Comm_RLSD();
  9. virtual void Comm_RXFLAG();
  10. virtual void Comm_TXEMPTY();
  11. virtual void Comm_RXCHAR(char c=0);
  12. virtual void Comm_Failed();
  13. public:
  14. CComPort();
  15. virtual ~CComPort();
  16. virtual void PrintErrors(CString sError);
  17. </font>
复制代码
串口事件处理函数都在监控函数中调用,可以选择性的在Ccomport子类的继承覆盖使用,一般会使用函数Comm_RXCHAR(char c=0)串口中接收一字节时会触发此函数。
另外Comm_Failed()也会继承用于处理串口异常事件;
串口运行时都会发生各种情况,通过函数PrintErrors可以将这些情况记录下来。函数体内通过宏_DEBUG判断当前程序是调试版本则弹出事件对话框,是发布版本则向磁盘写入事件。

4.串口类串口参数设置与串口开关函数的实现
关键讲解

  1. <font color="#000000">//4步
  2. protected:
  3. bool                          ComSetProtocol(COM_PARA *pComPara=NULL
  4. bool                          ComOpen();                        
  5. void                          ComClose
  6. </font>
复制代码
串口在使用前,控制与受控端的串口通讯参数必需保持一致才能正常通讯。
串口通讯参数常要设置的有串口号,波特率,数据位,奇偶校验位,停止位等待。
Ccomport类通过函数ComSetProtocol设置串口参数,然后通过函数ComOpen打开串口进行通讯。
函数函数ComOpen在设置了串口一系列参数后,开启一线程,调用线程函数ComThreadFunc实时监测串口。

ComClose()用于关闭串口,退出线程函数,在析构函数中调用了一次以保证实例对象释放时自动关闭串口,释放串口资源。

ComOpen函数体内有几点要注意的是
1.调用函数 CreateFile打开串口时,串口号格式为\\.\COM,以保证也可正常打开9以上的串口号。
2.调用函数CreateFile 传递参数FILE_FLAG_OVERLAPPED,实现串口异步通讯。

5.串口类数据收发与串口复位函数的实现
关键讲解
  1. <font color="#000000">//5步
  2. void                          ComReadData();         
  3. bool                          ComSendData(CString sData);      
  4. void                          ComSendDataExe();        
  5. bool                          ComReset();
  6. </font>
复制代码
在串口成功打开后,最重要的功能也就是1.向串口发送数据。2.从串口读取数据。从串口读取数据前面已介绍,只要重载函数Comm_RXCHAR(char c=0)进行数据累加就好。其具体是在ComReadData()内被调用。
数据的发送是通过ComSendData(CString sData);实现。参数sData为要发送的数据。数据发送的具体实现是通过ComSendDataExe完成。此函数执行失败会重复发送几次,达到最大次数MAXSENDTIMES,串口关闭。
函数ComReset会将串口进行复位,停止数据收发,清空缓存区数据。一般在串口初始时或异常后调用。

6.串口类的使用之连接断开下位机
关键讲解
BOOL  ConnectMeter();  //CONNECT METER
BOOL  DisconnectMeter(BOOLbNoticeFail=FALSE);//DISCONNECTMETER

一般串口都是连接智能仪表进行通讯。打开串口后会向仪表发送指令,仪表作出回应后串口才算成功连接。在具体通讯时应该根据仪表协议具体编写代码。这里通过与霍尼威尔310G扫描枪通讯协议为例进行串口类的使用。

ConnectMeter只打开事先设置的串口, DisconnectMeter进行串口关闭,函数 bNoticeFail 表示是否要调用Comm_Failed

7.串口类的使用之数据收发与出错处理


关键讲解
CString      m_sCodeReceived
bool         m_bReceived;

BOOL  GetBarcode(CString&sCode,short nTimeout=3000);
BOOL  GetBarcodeStop();//LETSCANNER STOP SCANNING
CString GetBarcodeLast();//getlast barcode;

void Comm_RXCHAR(charc=0)
void Comm_Failed();

在串口监测到一个字符时都会调用函数Comm_RXCHAR,在此函数中通过m_sCodeReceived进行字符的累加,边累加边提取数据。 在完整接收一帧数据后m_bReceived变量设为TRUE。

函数GetBarcode实现通过串口向扫描枪发送扫描指令sCode,枪超时nTimeout没回应则失败。
函数GetBarcodeStop实现通过串口向扫描枪发送停止扫描指令。
函数GetBarcodeLast获取上次扫描的结果。
向扫描枪发送的数据是通过其通讯手册查询0X16,0X54,0X0D为扫描指令0X16,0X55,0X0D为停止扫描指令.

8.串口类的使用之串口设置界面编写
关键讲解
#include "C3310G.h“
C3310G m_3310g;
void LoadAndSetComPara();

在编写的串口类后,就得设计 界面实现人机交互。首先是包含类对应的头文件#include"C3310G.h“
,其次是在界面文件中定义类的实例C3310Gm_3310g;
例程还添加了函数LoadAndSetComPara();实现串口参数的加载。在对话框函数OnInitDialog中进行了调用与打开串口。
LoadAndSetComPara();
if(!m_3310g.ConnectMeter())
MessageBox("failedto connect!");
然后是在界面部分调用m_3310g的成员函数实现串口通讯
实现按钮功能<从扫描枪获取条码><串口设置>.串口设置额外新建的对话框CComSet实现

9.额外功能之获取当前系统全部串口号
关键讲解
  1. <font color="#000000">void  CComPort::GetAllComPort(CStringArray &sPortArray)
  2. {
  3. HKEY hKey=NULL;
  4. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"),0,KEY_READ,&hKey)!=ERROR_SUCCESS)
  5. {
  6. return ;
  7. }
  8. CString valuename,databuffer;
  9. DWORD valuenamebufferlength=200,valuetype,databuddersize=200;
  10. int i=0;
  11. while(RegEnumValue(hKey,i++,valuename.GetBuffer(200),&valuenamebufferlength,NULL,&valuetype,(BYTE*)databuffer.GetBuffer(200),&databuddersize) != ERROR_NO_MORE_ITEMS)
  12. {
  13. sPortArray.Add(CString(databuffer));
  14. databuddersize=200;
  15. valuenamebufferlength=200;
  16. }
  17. RegCloseKey(hKey);
  18. }

  19. </font>
复制代码
在实际串口程序编写时,还会检测当前系统存在的全部串口号,而不是事先定义几个串口号供用户选择,这样当用户使用的串口号不在我们事先定义范围时,程序就无法满足要求。
获取串口号的方法有多种,当前例程通过注册表实现。其他方法可以在工控编程吧搜索关键字获取有效串口查









回复

使用道具 举报

大神点评(6)

点击查看
快速回复 返回列表 客服中心 搜索