搜索
bottom↓
回复: 54

开源PLC学习笔记01(再从51开始)——2013_11_7

  [复制链接]

出0入0汤圆

发表于 2013-11-7 19:09:48 | 显示全部楼层 |阅读模式
*******************************
背景介绍:
      8月份从零开始学习PLC和单片机(之前看了2个月模拟电子和数字电子,现在感觉顺序反了,应该先入门单片机,反过来再理解电路更容易),说句实话,现在网上资料非常丰富,只要选对了入门资料(视频、开发板或软件等),入门还是比较容易。

     PLC是利用三菱仿真软件入门的,再加上天天PLC的视频巩固一下,网上买了96元包邮的STM32仿三菱工控板,399买了触摸屏,做了几个简单试验,对如何利用STM32作PLC非常感兴趣。

     感觉STM32 PLC不再是高利润产品,毕竟淘宝上一搜就是上百家在卖,所以更容易把重心放在学习上。

    这里的热热闹闹的开源已经过去4年多了,当然我觉得这里的开源对现在仿三菱PLC的繁荣有着重要贡献。网上相关的PLC代码有好多种,下载看了,代码太长,真得很难入门。

     借鉴自己单片机入门经历,打算遍简化代码遍理解,并以笔记的形式表现出来。另外,我现在没有作出一个PLC板子,也没能让下载的代码通讯成功,也没有理解到代码的十分之一,这是起点。
***********************************

出0入0汤圆

 楼主| 发表于 2013-11-7 19:26:13 | 显示全部楼层
   对我这样的初学者,首先是下载能实现仿PLC完整代码,因为开源的PLC的MCU不再是热门的,所以这方面未能如愿。
  
   我刚开始一上来就看STM32的代码(论坛里的,http://www.amobbs.com/thread-5554905-1-1.html),果然又长又难理解,下载到片子里也不能通讯。

   又看4年前简易PLC的代码(http://www.amobbs.com/thread-3608835-1-2.html),没有MCU没法试,这没什么问题,尽管有详细的注释,这个代码一样复杂。

   看了简易PLC仿真帖子(http://www.amobbs.com/thread-3592500-1-3.html),感觉入门应该从这里开始。

   PLC的通讯协议应该是最难的,这个入门放在后面,先入门PLC指令在单片机内的实现,上面简易PLC仿真这方面做得非常不错。
   我在这个基础上只保留了能让仿真运行的代码,这样代码就很短,理解PLC指令的实现就变得门槛低了。尽管这样,剩下的代码对我还是有挑战性,不过难度较完整的代码下降了一个数量级。

    在后面的学习笔记01,我将尽量理解剩余的代码,看是否能换成适合我的形式。
*******************************************************************

出0入0汤圆

 楼主| 发表于 2013-11-7 19:34:09 | 显示全部楼层
oldbeginner 发表于 2013-11-7 19:26
对我这样的初学者,首先是下载能实现仿PLC完整代码,因为开源的PLC的MCU不再是热门的,所以这方面未能如 ...



   简易PLC仿真不包含通讯功能,其实命令只包含LD,OUT,SET和RST。16个输入端口,8个输出端口。

   函数非常少,只有:
   1、主函数;
   2、端口初始化;
   3、LD和OUT的函数;
   4、PLC运行函数。

   这一部分的难点和重点集中在数据定义上。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-11-7 19:39:00 | 显示全部楼层
oldbeginner 发表于 2013-11-7 19:34
简易PLC仿真不包含通讯功能,其实命令只包含LD,OUT,SET和RST。16个输入端口,8个输出端口。

    ...

好像图片太大了,重新上传一个小一点的。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-11-7 19:53:02 | 显示全部楼层
oldbeginner 发表于 2013-11-7 19:39
好像图片太大了,重新上传一个小一点的。



主函数,非常喜欢简单的主函数。超过10行代码的函数都不喜欢,不包括符号和if、while类似语句。
void main(void)
{
        while (1)
    {
                //初始化IO端口,必须
                RefreshIO();   
               
                //PLC执行去找二当家的,当老大就是好
                main_PLC();
        }
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-11-7 20:04:56 | 显示全部楼层
oldbeginner 发表于 2013-11-7 19:53
主函数,非常喜欢简单的主函数。超过10行代码的函数都不喜欢,不包括符号和if、while类似语句。
void m ...



PLC执行函数,在这里是手工把PLC命令输入,毕竟刚开始不能通讯。

用到了5个命令,后3个命令是通过宏定义的:
1、LD
2、OUT
3、SET
4、RST
5、END

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出75入0汤圆

发表于 2013-11-7 20:32:27 | 显示全部楼层
同楼主一起学习,这是很重要的基础,单片机控制方面的编程尽量按照PLC梯形图的思路。

出0入0汤圆

发表于 2013-11-7 20:32:50 | 显示全部楼层
很不错啊

出0入0汤圆

发表于 2013-11-7 20:38:51 来自手机 | 显示全部楼层
支持楼主

出0入0汤圆

 楼主| 发表于 2013-11-7 20:41:28 | 显示全部楼层
本帖最后由 oldbeginner 于 2013-11-7 20:54 编辑
oldbeginner 发表于 2013-11-7 20:04
PLC执行函数,在这里是手工把PLC命令输入,毕竟刚开始不能通讯。

用到了5个命令,后3个命令是通过宏定 ...




现在开始第一对函数的学习,LD和OUT,这是PLC中常用的指令,实话实说,三菱PLC仿真软件通关后,我还是不会LD,因为我一直用梯形图学习编程的。知道表达什么意思基本就可以了。

void _LD(unsigned char a)
{
  ACC_BIT <<= 1;
  ACC_BIT |= a;
}

先将上面表达式变为,缩写对初学者是一种负担(现在同时在学C语言)。
void _LD(unsigned char a)
{
  ACC_BIT = ACC_BIT<<1;
  ACC_BIT = ACC_BIT | a;
}

这里需要了解ACC_BIT是什么定义。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入16汤圆

发表于 2013-11-7 21:07:20 | 显示全部楼层
挺不错!希望楼主坚持完成做好!

出0入0汤圆

发表于 2013-11-7 21:10:15 | 显示全部楼层
  协议倒是 有。

出0入0汤圆

 楼主| 发表于 2013-11-7 21:16:52 | 显示全部楼层
oldbeginner 发表于 2013-11-7 20:41
现在开始第一对函数的学习,LD和OUT,这是PLC中常用的指令,实话实说,三菱PLC仿真软件通关后,我还是 ...



找到ACC_BIT定义,是无符号字母类型,
//  位运算器及 7级中间过渡栈
unsigned char   data  ACC_BIT;      

我需要查找资料 data表示什么,在入门的时候见过code。现在到时候来理解一下了,同样网上找资料(我一般找好几个,对比一下)。
************************************
http://blog.sina.com.cn/s/blog_81bc3add0101347t.html

data: 固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小
data --->   可寻址片内ram

bdata --->   可位寻址的片内ram
idata --->  可寻址片内ram,允许访问全部内部ram
pdata ---> 分页寻址片外ram
xdata ---> 可寻址片外ram
code ---> 程序存储区 (64k 地址范围)
***************************************
引出了acc,网上搜一下资料http://zhidao.baidu.com/question/440331825.html,累加器,累加器ACC是一个8位的存储单元,是用来放数据的。不知道怎样利用ACC做运算,暂时搁置,边研究边学。

花了一些精力,基本得出这样一个分析结果,ACC_BIT是一个会用到累加器的无符号字符型变量。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入8汤圆

发表于 2013-11-7 21:22:23 | 显示全部楼层
很不错 也前来学习学习

出0入0汤圆

 楼主| 发表于 2013-11-7 21:48:38 | 显示全部楼层
oldbeginner 发表于 2013-11-7 21:16
找到ACC_BIT定义,是无符号字母类型,
//  位运算器及 7级中间过渡栈
unsigned char   data  ACC_BIT;  ...

我是看了OUT函数后,理解了LD函数的。还得放张图片来说明。


以上图为例,X0只有0或1两种情况,将两者的函数合在一起:

  1、 ACC_BIT= ACC_BIT << 1;
   
  2、 ACC_BIT=ACC_BIT | a;

  3、return(ACC_BIT & 0x01);
*************************
利用二进制,如果第一次使用,ACC_BIT=0000 0000;,
  1、ACC_BIT左移一位后,还是0000 0000;
  2、后面的a就是图中的X0,只有0或1两种情况
      A:a=0,ACC_BIT=0000 0000
      B:a=1,ACC_BIT=0000 0001
  
  3、ACC_BIT & 0x01,
      A:a=0,ACC_BIT=0000 0000
                                &0000 0001
          返回值为0;
      B:a=1,ACC_BIT=0000 0001
                                &0000 0001
          返回值为1。

如果不是第一次使用,则可以假设ACC_BIT=xxxx xxxx; (x可以是0,也可以是1,不确定)
       其实只要左移1位,填充的是0,返回值就是a的值。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-11-7 21:49:54 来自手机 | 显示全部楼层
收藏,希望坚持下去

出0入0汤圆

发表于 2013-11-7 21:53:43 来自手机 | 显示全部楼层
谢谢楼主写的细致。

出0入0汤圆

 楼主| 发表于 2013-11-7 22:24:15 | 显示全部楼层
本帖最后由 oldbeginner 于 2013-11-7 22:52 编辑
oldbeginner 发表于 2013-11-7 21:48
我是看了OUT函数后,理解了LD函数的。还得放张图片来说明。




学习了LD和OUT之后再学习SET和RST就轻松了,因为方法一致。

#define  _SET(a)        if ((ACC_BIT & 0x01) != 0)  { a = 1; }

变为
            if ((ACC_BIT & 0x01) != 0)  
                   {
                      a = 1;
                   }

要理解SET,还需要和LD联合在一起

将LD和SET函数合在一起分析,要做参数修改,因为都采用虚参数a,容易混淆,所以将LD中的参数改为x,SET中的参数改为y:

  1、 ACC_BIT= ACC_BIT << 1;
   
  2、 ACC_BIT=ACC_BIT | x;
         
  3、if ((ACC_BIT & 0x01) != 0)  
          {
                  y = 1;
           }
*********************************
剩下的工作就是复制粘贴,然后修改
*************************
利用二进制,如果第一次使用,ACC_BIT=0000 0000;,
  1、ACC_BIT左移一位后,还是0000 0000;
  2、LD函数中的参数x就是图中的X0,值为0或1
      A:x=0,ACC_BIT=0000 0000
      B:x=1,ACC_BIT=0000 0001
  
  3、ACC_BIT & 0x01,
      A:x=0,ACC_BIT=0000 0000
                                &0000 0001
          此时SET函数的y没被赋值,保持原来状态;
      B:x=1,ACC_BIT=0000 0001
                                &0000 0001
          此时SET函数的y=1;。

如果不是第一次使用,则可以假设ACC_BIT=xxxx xxxx; (x可以是0,也可以是1,不确定)
       其实只要左移1位,填充的是0,ACC_BIT=xxxx xxxx0,结论不变。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-11-7 23:17:46 | 显示全部楼层
标记下
·

出0入0汤圆

发表于 2013-11-7 23:46:28 | 显示全部楼层
MARK,,占位

出0入0汤圆

发表于 2013-11-8 07:17:57 | 显示全部楼层
太好了,向您学习

出0入0汤圆

发表于 2013-11-8 08:12:43 | 显示全部楼层
好,支持

出0入0汤圆

 楼主| 发表于 2013-11-8 11:11:25 | 显示全部楼层
oldbeginner 发表于 2013-11-7 22:24
学习了LD和OUT之后再学习SET和RST就轻松了,因为方法一致。

#define  _SET(a)        if ((ACC_BIT &  ...

学好SET后,RST实际上也可以理解了,#define  _RST(a)        if ((ACC_BIT & 0x01) != 0)  { a = 0; },只是赋值不同,SET是置位,RST是复位。

**************
现在可以进入到端口定义和端口初始化函数。
先看端口定义:



对初学者来说,还是比较复杂的,还需要再看PLC_Memory.c中的定义:
//  位元件 X 存储位
TYPE_BIT_BYTE   data  rX[_X_BYTE];

//  位元件 Y 存储位                                
TYPE_BIT_BYTE   data  rY[_Y_BYTE];   

要理解上面的定义,还需要看PLC_Configure.h中的定义(真绕,多费精力):
// 16个输入端口,    编号:X0-X7 X10-X17
#define   _X_num      16
          
// 8个输出端口,    编号:Y0-Y7
#define   _Y_num      8           

// 16个输入端口,所占内存字节数
#define   _X_BYTE     (_X_num + 7) / 8  

// 8个输出端口,所占内存字节数  
#define   _Y_BYTE     (_Y_num + 7) / 8   

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-11-8 11:32:34 | 显示全部楼层
本帖最后由 oldbeginner 于 2013-11-8 11:33 编辑

为了使每个帖子里要表达的主体更加清晰和一致,端口定义的理解将放在笔记02中。本帖子可能还会根据对PLC指令理解的加深,而更新。
开源PLC学习笔记02(再从51开始)——2013_11_8

笔记01的内容是精简PLC仿真的引出,理解几个常用PLC指令的51实现,从而对入门有个初步认识。

出0入0汤圆

发表于 2013-11-8 14:44:15 | 显示全部楼层
学习PLC,谢谢楼主。

出0入0汤圆

发表于 2013-11-8 18:29:43 | 显示全部楼层
唉,花这么多时间学习一种过时的技术!

出0入0汤圆

 楼主| 发表于 2013-11-8 19:49:54 | 显示全部楼层
dongfangjian 发表于 2013-11-8 18:29
唉,花这么多时间学习一种过时的技术!

呵呵,你没仔细看背景介绍,我现在是感兴趣想学习,如果想开发一种跟上的技术肯定不会花时间再学PLC。

出0入0汤圆

发表于 2013-11-8 20:11:43 | 显示全部楼层
我说的是51这种架构的芯片,而不是PLC,而且这个软件离真正的PLC还差得很远。

出0入0汤圆

 楼主| 发表于 2013-11-8 20:35:47 | 显示全部楼层
dongfangjian 发表于 2013-11-8 20:11
我说的是51这种架构的芯片,而不是PLC,而且这个软件离真正的PLC还差得很远。 ...

明白你的意思了,不过51是资料比较丰富的,我一开始就看STM32的代码,理解都没法入门。

出0入0汤圆

发表于 2013-11-10 19:15:29 | 显示全部楼层
必须MARK

出0入0汤圆

发表于 2013-11-19 18:03:19 | 显示全部楼层
支持楼主

出0入0汤圆

发表于 2013-11-19 19:13:42 | 显示全部楼层
不错,支持楼主!先从简单的一步一个脚印打好基础。

出0入0汤圆

发表于 2013-11-19 22:39:01 | 显示全部楼层
支持楼主!

出0入0汤圆

发表于 2013-11-21 13:38:58 | 显示全部楼层
楼主好样的。。。。

出0入0汤圆

发表于 2013-12-2 11:28:57 | 显示全部楼层
佩服楼主啊!一起学习!正好也在研究!

出0入0汤圆

发表于 2013-12-2 21:33:17 | 显示全部楼层
学习中,

出0入0汤圆

发表于 2014-1-1 21:37:25 | 显示全部楼层
跟你学习,顶

出0入0汤圆

发表于 2014-1-1 22:47:32 | 显示全部楼层
学习,学习

出0入0汤圆

发表于 2014-3-3 10:16:43 | 显示全部楼层
先 mark,,,移植想学PLC,,觉得自动控制挺有意思的,,,

出0入0汤圆

发表于 2014-3-5 13:11:39 | 显示全部楼层
正在学习自动控制,紧跟楼主的脚步。不管是哪一种MCU总是要从零开始的

出0入0汤圆

发表于 2014-4-7 16:57:49 | 显示全部楼层
一步一步跟着老大学!

出0入0汤圆

发表于 2014-7-18 10:17:58 | 显示全部楼层
跟着楼主学习~~

出0入0汤圆

发表于 2014-11-24 23:03:28 | 显示全部楼层
跟随楼主的脚步,这第一篇笔记我也学的差不多了,感谢楼主的无私分享,不然真找不到从何处下手

出0入0汤圆

发表于 2015-3-10 14:39:11 | 显示全部楼层
从头开始一步步跟着学习!

出0入4汤圆

发表于 2015-5-14 11:07:20 | 显示全部楼层
好贴,收藏了慢慢消化~

出0入0汤圆

发表于 2015-6-23 10:13:52 | 显示全部楼层
跟着楼主学习

出0入0汤圆

发表于 2015-6-23 19:00:42 | 显示全部楼层
oldbeginner 发表于 2013-11-8 11:11
学好SET后,RST实际上也可以理解了,#define  _RST(a)        if ((ACC_BIT & 0x01) != 0)  { a = 0; }, ...

#define  _SET(a)        if ((ACC_BIT & 0x01) != 0)  { a = 1; }

#define  _RST(a)        if ((ACC_BIT & 0x01) != 0)  { a = 0; }
怎么感觉第二条不对!这样可以实现复位么。。。

出10入95汤圆

发表于 2016-1-4 20:48:59 | 显示全部楼层

出20入0汤圆

发表于 2016-7-28 09:30:51 | 显示全部楼层
你好,源代码哪里下载的,可否给你链接?

出0入0汤圆

发表于 2017-3-29 20:55:14 | 显示全部楼层
支持,,,

出0入0汤圆

发表于 2020-1-8 18:36:15 来自手机 | 显示全部楼层
看了一下时间,隔了这么久。PLC的思路值得学习的。收获满满

出0入0汤圆

发表于 2020-1-9 16:45:40 | 显示全部楼层
了解学习下  谢谢分享

出0入0汤圆

发表于 2020-3-26 12:24:21 | 显示全部楼层
千里之行始于足下,支持楼主!不知道楼主现在进行的咋样啦

出0入4汤圆

发表于 2020-4-3 17:36:34 | 显示全部楼层
跟着楼主学着理解PLC通讯部分与软元件与单片机内部地址,很棒的帖子,好好吸收学习

出100入101汤圆

发表于 2020-4-4 14:14:49 | 显示全部楼层
lz发布的笔记不错!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子论坛 ( 公安交互式论坛备案:44190002001997 粤ICP备09047143号 )

GMT+8, 2022-6-30 13:13

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表