PLC
直播中

李中宏

7年用户 1211经验值
私信 关注

如何去实现一个基于梯形图的软PLC设计

梯形图的原理是什么?
梯形图是如何运行的?
如何去实现一个基于梯形图的软PLC设计?

回帖(1)

王苑苑

2021-9-23 14:28:00
  梯形图显示到编译--软PLC的实现
  PLC(Programmable Logic Controller 可编程逻辑控制器)是在工业环境下使用的数字逻辑操作系统。其编程语言有我们最为熟悉的梯形图,本篇文章将从梯形图的原理、编译、运行,实现一个软PLC。
  一、基本原理
  梯形图可以理解为一个电路图,通过梯形图上的元件的通断来控制整个程序逻辑。元件的状态只有“通”和“断”;元件的关系可以分为“与”、“或”、“非”。是不是似曾相识?这里我们把含有逻辑关系的元件当做一个逻辑块;通过这些逻辑块最终输出到元件——输出块。
  如下图:
  
  图1 简单梯形图
  从母线出发,连接逻辑块到输出块的通路称为输出图。如上图为一个输出图。
  只有一个逻辑块和输出块的图称为最简图,如下图所示:
  
  图2 最简图
  有了上面的基本原理,接下来就可以抽象梯形图,从而实现梯形图的显示和编译。
  二、算法原理
  1、初始状态将每个元件当做一个逻辑块或者输出块。如图1中的M000、X000等为逻辑块,Y001、Y002为输出块
  2、取出一个输出图。
  3、合并相邻输出块、输出块
  4、如果合并后为最简图则返回第2步取下一个输出图,不是则继续3步
  伪代码如下:
  if( getNextOutputGraph() )
  {
  if( !isTheSimpleGraph() )
  {
  shiftGraph();
  }
  }
  outputPLCInstructions();
  图1的梯形图处理结果如下,输出PLC指令:
  
  三、运行
  将上面编译出来的PLC指令,输入到PLCCore,使用解析运行将模拟PLC运行。图中灰色表示元件导通,双击元件可以改变元件状态,如果双击M001导通,则Y001和Y002导通一次。
  
  下面是已经支持的指令表,PLCCore是在三菱PLC下参考制作,可以直接模拟三菱PLC的程序
  static InsItem g_insItems[] = {
  {{dinsDEBUG}, sinsNOP-1, “DEBUG”, 1,0, ARG_COIL_G },
  {{dinsLD}, sinsLD, “LD”, 1,0, ARG_COIL_BIT},
  {{dinsLDI}, sinsLDI, “LDI”, 1,0, ARG_COIL_BIT},
  {{dinsLDP}, sinsLDP, “LDP”, 1,0, ARG_COIL_BIT},
  {{dinsLDF}, sinsLDF, “LDF”, 1,0, ARG_COIL_BIT},
  {{dinsAND}, sinsAND, “AND”, 1,0, ARG_COIL_BIT},
  {{dinsANI}, sinsANI, “ANI”, 1,0, ARG_COIL_BIT},
  {{dinsANDP}, sinsANDP, “ANDP”, 1,0, ARG_COIL_BIT},
  {{dinsANDF}, sinsANDF, “ANDF”, 1,0, ARG_COIL_BIT},
  {{dinsOR}, sinsOR, “OR”, 1,0, ARG_COIL_BIT},
  {{dinsORI}, sinsORI, “ORI”, 1,0, ARG_COIL_BIT},
  {{dinsORP}, sinsORP, “ORP”, 1,0, ARG_COIL_BIT},
  {{dinsORF}, sinsORF, “ORF”, 1,0, ARG_COIL_BIT},
  {{dinsANB}, sinsANB, “ANB”, 0,0, 0},
  {{dinsORB}, sinsORB, “ORB”, 0,0, 0},
  {{dinsMPS}, sinsMPS, “MPS”, 0,0, 0},
  {{dinsMRD}, sinsMRD, “MRD”, 0,0, 0},
  {{dinsMPP}, sinsMPP, “MPP”, 0,0, 0},
  {{dinsINV}, sinsINV, “INV”, 0,0, 0},
  {{dinsMEP}, sinsMEP, “MEP”, 0,0, 0},
  {{dinsMEF}, sinsMEF, “MEF”, 0,0, 0},
  {{dinsOUT}, sinsOUT, “OUT”, 1,0, ARG_COIL_X | ARG_COIL_Y | ARG_COIL_M },
  {{dinsOUTT}, sinsOUTT, “OUT”, 2,0, ARG_COIL_T,ARG_COIL_DATA},
  {{dinsOUTC}, sinsOUTC, “OUT”, 2,0, ARG_COIL_C,ARG_COIL_DATA},
  {{dinsOUT}, sinsOUTMS, “OUT”, 1,0, ARG_COIL_M },
  {{dinsOUTS}, sinsOUTMS, “OUT”, 1,0, ARG_COIL_S },
  {{dinsSET}, sinsSET, “SET”, 1,0, ARG_COIL_X | ARG_COIL_Y | ARG_COIL_M },
  {{dinsSETS}, sinsSETMS, “SET”, 1,0, ARG_COIL_S },
  {{dinsSET}, sinsSETMS, “SET”, 1,0, ARG_COIL_M },
  {{dinsRST}, sinsRST, “RST”, 1,0, ARG_COIL_X | ARG_COIL_Y | ARG_COIL_M },
  {{dinsRSTTC}, sinsRSTMSTC,“RST”, 1,0, ARG_COIL_T | ARG_COIL_C },
  {{dinsRSTS}, sinsRSTMSTC,“RST”, 1,0, ARG_COIL_S },
  {{dinsRST}, sinsRSTMSTC,“RST”, 1,0, ARG_COIL_M },
  {{dinsPLS}, sinsPLS, “PLS”, 1,0, ARG_COIL_X | ARG_COIL_Y | ARG_COIL_M | ARG_COIL_S },
  {{dinsPLF}, sinsPLF, “PLF”, 1,0, ARG_COIL_X | ARG_COIL_Y | ARG_COIL_M | ARG_COIL_S },
  {{dinsSTL}, sinsSTL, “STL”, 1,0, ARG_COIL_S},
  {{dinsRET}, sinsRET, “RET”, 0,0, 0},
  {{dinsMC}, sinsMC, “MC”, 1,0, ARG_COIL_N },
  {{dinsMCR}, sinsMCR, “MCR”, 1,0, ARG_COIL_N },
  {{dinsNOP}, sinsNOP, “NOP”, 0,0, 0},
  {{dinsEND}, sinsEND, “END”, 0,0, 0},
  {{dinsADD}, sinsADD, “ADD”, 3,0, ARG_COIL_DATA,ARG_COIL_DATA,ARG_COIL_D | ARG_COIL_V },
  {{dinsSUB}, sinsSUB, “SUB”, 3,0, ARG_COIL_DATA,ARG_COIL_DATA,ARG_COIL_D | ARG_COIL_V },
  {{dinsMUL}, sinsMUL, “MUL”, 3,0, ARG_COIL_DATA,ARG_COIL_DATA,ARG_COIL_D | ARG_COIL_V },
  {{dinsDIV}, sinsDIV, “DIV”, 3,0, ARG_COIL_DATA,ARG_COIL_DATA,ARG_COIL_D | ARG_COIL_V },
  {{dinsINC}, sinsINC, “INC”, 1,0, ARG_COIL_D | ARG_COIL_V },
  {{dinsDEC}, sinsDEC, “DEC”, 1,0, ARG_COIL_D | ARG_COIL_V },
  {{dinsMOV}, sinsMOV, “MOV”, 2,0, ARG_COIL_DATA,ARG_COIL_D | ARG_COIL_V },
  {{dinsCMP}, sinsCMP, “CMP”, 3,0, ARG_COIL_DATA,ARG_COIL_DATA,ARG_COIL_M},
  {{dinsCJ}, sinsCJ, “CJ”, 1,0, ARG_COIL_P},
  {{dinsCJP}, sinsCJP, “CJP”, 1,0, ARG_COIL_P},
  {{dinsSRET}, sinsSRET, “SRET”, 0,0, 0},
  {{dinsFEND}, sinsFEND, “FEND”, 0,0, 0},
  {{dinsCALL}, sinsCALL, “CALL”, 1,0, ARG_COIL_P},
  {{dinsP}, sinsP, “P”, 1,0, ARG_COIL_P},
  {{dinsDADD}, sinsDADD, “DADD”, 3,1, ARG_COIL_DATA,ARG_COIL_DATA,ARG_COIL_D | ARG_COIL_V},
  {{dinsDSUB}, sinsDSUB, “DSUB”, 3,1, ARG_COIL_DATA,ARG_COIL_DATA,ARG_COIL_D | ARG_COIL_V},
  {{dinsDMUL}, sinsDMUL, “DMUL”, 3,1, ARG_COIL_DATA,ARG_COIL_DATA,ARG_COIL_D | ARG_COIL_V},
  {{dinsDDIV}, sinsDDIV, “DDIV”, 3,1, ARG_COIL_DATA,ARG_COIL_DATA,ARG_COIL_D | ARG_COIL_V},
  {{dinsDINC}, sinsDINC, “DINC”, 1,1, ARG_COIL_D | ARG_COIL_V},
  {{dinsDDEC}, sinsDDEC, “DDEC”, 1,1, ARG_COIL_D | ARG_COIL_V},
  {{dinsDMOV}, sinsDMOV, “DMOV”, 2,1, ARG_COIL_DATA,ARG_COIL_D | ARG_COIL_V},
  {{dinsDCMP}, sinsDCMP, “DCMP”, 3,1, ARG_COIL_DATA,ARG_COIL_DATA,ARG_COIL_M},
  {{dinsLD_E}, sinsLD_E, “LD=”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsAND_E}, sinsAND_E, “AND=”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsOR_E}, sinsOR_E, “OR=”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsLD_NE}, sinsLD_NE, “LD《》”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsAND_NE}, sinsAND_NE, “AND《》”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsOR_NE}, sinsOR_NE, “OR《》”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsLD_B}, sinsLD_B, “LD》”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsAND_B}, sinsAND_B, “AND》”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsOR_B}, sinsOR_B, “OR》”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsLD_EB}, sinsLD_EB, “LD》=”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsAND_EB}, sinsAND_EB, “AND》=”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsOR_EB}, sinsOR_EB, “OR》=”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsLD_S}, sinsLD_S, “LD《”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsAND_S}, sinsAND_S, “AND《”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsOR_S}, sinsOR_S, “OR《”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsLD_ES}, sinsLD_ES, “LD《=”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsAND_ES}, sinsAND_ES, “AND《=”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsOR_ES}, sinsOR_ES, “OR《=”, 2,0, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsLDD_E}, sinsLDD_E, “LDD=”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsANDD_E}, sinsANDD_E, “ANDD=”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsORD_E}, sinsORD_E, “ORD=”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsLDD_NE}, sinsLDD_NE, “LDD《》”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsANDD_NE}, sinsANDD_NE,“ANDD《》”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsORD_NE}, sinsORD_NE, “ORD《》”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsLDD_B}, sinsLDD_B, “LDD》”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsANDD_B}, sinsANDD_B, “ANDD》”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsORD_B}, sinsORD_B, “ORD》”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsLDD_EB}, sinsLDD_EB, “LDD》=”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsANDD_EB}, sinsANDD_EB,“ANDD》=”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsORD_EB}, sinsORD_EB, “ORD》=”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsLDD_S}, sinsLDD_S, “LDD《”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsANDD_S}, sinsANDD_S, “ANDD《”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsORD_S}, sinsORD_S, “ORD《”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsLDD_ES}, sinsLDD_ES, “LDD《=”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsANDD_ES}, sinsANDD_ES,“ANDD《=”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsORD_ES}, sinsORD_ES, “ORD《=”, 2,1, ARG_COIL_DATA,ARG_COIL_DATA},
  {{dinsDDRVA}, sinsDDRVA, “DDRVA”, 4,1, ARG_COIL_DATA, ARG_COIL_DATA, ARG_COIL_Y, ARG_COIL_Y },
  {{dinsDDRVI}, sinsDDRVI, “DDRVI”, 4,1, ARG_COIL_DATA, ARG_COIL_DATA, ARG_COIL_Y, ARG_COIL_Y },
  {{dinsDRVA}, sinsDRVA, “DRVA”, 4,0, ARG_COIL_DATA, ARG_COIL_DATA, ARG_COIL_Y, ARG_COIL_Y },
  {{dinsDRVI}, sinsDRVI, “DRVI”, 4,0, ARG_COIL_DATA, ARG_COIL_DATA, ARG_COIL_Y, ARG_COIL_Y },
  };
  由于项目很久没有维护,PLCCore使用c语言编写,已经成功跑在Stm32上,windows模拟器也是同个PLCCore。但界面使用MFC,后面整理完会将项目开源。敬请期待。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分