12.PMAC上位机-中断通信(下位机通知上位机)

之前说过,上位机控制硬件都是通过发送指令进行的,这是单向的。那么反过来,下位机硬件给上位机发送指令怎么才能实现呢?对于PMAC来说,最常见的情况就是,当PMAC一次运动完成时通知当前PC程序运动已完成。


1.下位机通知上位机原理


如下图所示,


PC给PMAC发送指令控制它做什么,当运动程序完成后中断通知上位机,在中断的同时发送一个标识P100表明完成的程序号,这个标明到底是1号轴运动完,还是是2号轴运动完。在PC端有一个中断回调函数,下位机发送中断后,会自动跳转到该函数中,中断函数接受中断,根据标识P100来决定不同的情况不同的处理。

通俗来说,就是如下流程:

[plain]  view plain  copy
  1. PC->PMAC:发送指令,告诉它做什么         (&1b40r)  
  2. PMAC:做完了,等待PC处理完前一个通知           (While (M613 = 1)  wait)  
  3. PMAC->PC:某某事做完了,PC你就看着处理吧        (P100=1 M613=1)  
  4.   
  5. PC:针对PMAC通知的事判断属于什么类型并处理        (根据P100判断)  
  6. PC->PMAC:处理完了,下位机可以发下一个通知消息了 (P100=0 M613=0)  

如上图所示,M613这个是用硬件跳线配置的,指定当前中断响应通道,具体的设置在这里。P100是我们指定的上下位机通信变量,这个是自己定义的,也可以是P1/P2/P3等。


2.下位机代码

[plain]  view plain  copy
  1. &1  
  2. CLOSE ;确认所有缓冲区被关闭  
  3.   
  4. OPEN PROG 40  
  5. CLEAR  
  6.   
  7. TA(200)  
  8. TS(20)  
  9. F(30)  
  10. INC  
  11. Linear  
  12.   
  13. X(10) Y(40)  
  14. dwell 0  
  15.   
  16. ;中断发送程序段  
  17. While (M613 = 1)  wait  ;等待上一次中断响应处理完成  
  18. P100=1                  ;标明当前完成的程序,可为0、1、2等自定义的值  
  19. M613=1                  ;向上位机发送中断  
  20.   
  21. CLOSE  

3.上位机处理代码

注册中断处理函数:

[cpp]  view plain  copy
  1. BOOL CInterruptDlg::ConnectPmac()  
  2. {  
  3.     //链接Pcomm32.dll函数库,注意引入myRuntimeLink头文件  
  4.     if (NULL == PmacRuntimeLink(PMAC_NUM))  
  5.     {  
  6.         AfxMessageBox(TEXT("链接Pcomm32.dll函数库和打开PMAC卡连接失败!"));  
  7.         return m_bIsConnect = FALSE;  
  8.     }  
  9.       
  10.     //中断函数绑定  
  11.     if(  FALSE == PmacINTRFuncCallInit(PMAC_NUM, InterruptFunc2, 0, 0xFF1F))  
  12.     {  
  13.         AfxMessageBox(TEXT("PMAC函数中断初始化失败"));  
  14.         return m_bIsConnect = FALSE;  
  15.     }  
  16.       
  17.     return m_bIsConnect = TRUE;  
  18. }  

对应的中断函数处理如下:

[cpp]  view plain  copy
  1. //中断处理  
  2. void WINAPI InterruptFunc2(DWORD msg, PINTRBUFFER pBuffer)  
  3. {  
  4.     extern CInterruptApp theApp;  
  5.     TCHAR szRes[MAX_PATH];  
  6.     TCHAR szCmd[MAX_PATH];  
  7.       
  8.     if (pBuffer->dwInterruptType == ISR_IR6)  
  9.     {  
  10.         if (1 == PmacGetVariable(PMAC_NUM, 'P', 100, 0))  
  11.         {  
  12.             AfxMessageBox(TEXT("处理完成!"));  
  13.               
  14.             //重置中断  
  15.             lstrcpy(szCmd, "M613=0 P100=0");  
  16.             PmacGetResponse(0,szRes,MAX_PATH,szCmd);  
  17.         }  
  18.     }  
  19. }  


演示程序源代码下载地址,在该程序中点击电机开始回零后,回零按钮灰度化。直到下位机完成回零发送中断给上位机程序,上位机程序判断后处理使能按钮。这个程序是最简单的中断处理程序,主要是为了阐明原理,再复杂的程序都和这个原理一样的,基于这个原理我们可以开发更复杂的上下位机交互程序。

注意这里不能用默认安装完成后的runtime.h,原本的我试过有问题,必须用我放在程序源文件夹里的重写myRuntime.h

更多PMAC代码参见我的网站,基本上都是这个系列涉及到的知识点。


到此为止,PMAC的使用系列基本上写完了,看完这一个系列,基本的PMAC编程和调试应该没有问题了,剩下的就是Read The Fuck Manual了。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
* * MODBUS协议 * * * 介绍: * 此modbus上位机 协议类 具有较强的通用性 * 本协议类最主要的思想是 把所有向下位机发送的指令 先存放在缓冲区中(命名为管道) * 再将管道中的指令逐个发送出去。 * 管道遵守FIFO的模式。管道中所存放指令的个数 在全局变量中定义。 * 管道内主要分为两部分:1,定时循环发送指令。2,一次性发送指令。 * 定时循环发送指令:周期性间隔时间发送指令,一般针对“输入寄存器”或“输入线圈”等实时更新的变量。 * 这两部分的长度由用户所添加指令个数决定(所以自由性强)。 * 指令的最大发送次数,及管道中最大存放指令的个数在常量定义中 可进行设定。 * * 使用说明: * 1,首先对所定义的寄存器或线圈进行分组定义,并定义首地址。 * 2,在MBDataTable数组中添加寄存器或线圈所对应的地址。 注意 寄存器:ob = new UInt16()。线圈:ob = new byte()。 * 3,对所定义的地址 用属性进行定义 以方便在类外进行访问及了解所对应地址的含义。 * 4,GetAddressValueLength函数中 对使用说明的"第一步"分组 的元素个数进行指定。 * 5,在主程序中调用MBConfig进行协议初始化(初始化内容参考函数)。 * 6,在串口中断函数中调用MBDataReceive()。 * 7,定时器调用MBRefresh()。(10ms以下) * 指令发送间隔时间等于实时器乘以10。 例:定时器5ms调用一次 指令发送间隔为50ms。 * 8,在主程序初始化中添加固定实时发送的指令操作 用MBAddRepeatCmd函数。 * 9,在主程序运行过程中 根据需要添加 单个的指令操作(非固定重复发送的指令)用MBAddCmd函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值