单片机技术网|技术阅读
登录|注册

您现在的位置是:单片机技术网 > 技术阅读 > 揭秘PLC(三)RTS之IO篇

揭秘PLC(三)RTS之IO篇

揭秘继续,上一期我们介绍了PLC设备端的程序RTS与PC端编译的用户程序之间的交互的核心:双方定义好相同的含有函数指针的结构体,通过ld连接文件将其定义到固定的地址上去执行。

今天我们探究下PLC RTS的IO是如何实现的,首先说明一点,从实物上看,PLC的IO分两种,一种是PLC的CPU模块本体的IO,比如下图这款S7-1200,本体内置6个DI和4个DO


另一种是通过IO扩展模块,下图是一个比较好的例子,该系统有两种IO扩展模式:

方式1. CPU通过背板扩展IO模块。

方式2. CPU通过IO-LINK扩展。IO-LINK技术也是近些年工业总线技术的一个方向,以后有时间我们可以专门学习一下。


不管是通过背板还是IO-LINK来扩展IO,在电气攻城狮看来其实是没有本质区别的,这些IO通道都是仅仅是内存的一个bit,byte或者word而已,以Codesys为例,在PLC配置中添加一个Profibus-DP的主站(CP5613),然后可以在这个主站下添加不同的从站模块,假设这个从站有1个Byte和1个Word的输入,以及1个Byte和1个Word的输出,在配置界面就可以看到AT %IB0:BYTE字样,说明这个从站占用了I区的第0个字节,而1 WORD Slave-Out/Master-In占用了I区的1~2个字节,而输出则占用了Q区对应地址。上图实物中挂载了好几个模块,但如何区分到底哪个对应%IB0呢?聪明的小伙伴会发现我已经标注出了站地址这个输入项,IO模块插在背板中不同的槽位对应不同的站地址,当用户把模块板块插上时,应该就知道这个站地址对应的板块型号,在PLC配置界面插入对应GSD文件后,就需要根据实际模块的占位输入正确的站地址即可


1. PLC的内存分配

这个标题有些歧义,我实际想讲述的是,PLC所用到的存储器在MCU系统内的分配。从宏观上讲,MCU内部需要开辟6个空间

NameDescription
Code区用户代码区,存放用户代码以及配置信息的,可以是Flash,也可以是RAM
N区可以理解为用户代码的stack,用户定义的一些临时局部变量定位于此
M区提供给用户使用的RAM,用户可以通过%MB0的方式来读写该区域数据,通常用作全局变量
I区对应PLC系统所用到的Input数据
Q区对应PLC系统所用到的Output数据
R区掉电保持区,有些数据用户需要PLC在意外掉电后能非易失

R区的实现方式往往会对用户的使用有一定的限制,比如通过MCU内部的Flash存储R区内容,由于MCU内部的Flash是有擦写寿命的,一般也就10W次左右,那就要求用户不能频繁的写入R区;如果使用电池+SRAM组成的NVRAM,限制为电池的容量(PLC厂商往往会给出规格);如果使用MRAM存储Q区数据,就要求应用场合避免有强磁的环境。

PC端IDE已经知道M, I, Q, R各个区的数据了,并且也知道了通道上的一些参数,比如滤波参数,通道是否带诊断等等,那RTS是怎么知道这些的,这就是之前讲到的配置信息,其中即包括IO在I,Q区所站的位置,还包括各个通道的参数。以Beremiz为例,它将配置信息写入了之前讲的共享结构体:plc_app_abi_t

//IO manager data
plc_loc_tbl_t * l_tab; //Location table
uint32_t * w_tab; //Weigth table
uint16_t l_sz; //Location table size

struct _plc_loc_dsc_t
{

void *v_buf;
uint8_t v_type;
uint8_t v_size;
uint16_t a_size;
const uint32_t *a_data;
uint16_t proto;
};

上位机会在编译时,把IO通道相关的内容填入该结构体,RTS通过解析该结构体就可以拿到各个区所对应的通道值,然后将其对应到实际的IO上。

void plc_iom_set(void)
{
int32_t i, m_begin, o_end;

m_begin = plc_iom.m_begin;
o_end = plc_iom.m_end;

for (i = m_begin; i < o_end; i++)
{
plc_iom_registry[0].set(i);
}
}

void plc_iom_start(void)
{
uint8_t j;
for (j = 0; j < plc_iom_reg_sz; j++)
{
plc_iom_registry[j].start();
}
}

知识点:PLC有个关键的参数叫输入到输出时间,本质上影响设备的控制周期,还记得下面这张图么?就是PLC的主循环,主循环运行一圈的时间叫IEC运算周期,控制周期 = 2x运算周期,这是由于Input输入的变化可能发生在while(1)运行的任何位置,如果变化的点就在执行IO input之后,UserCode之前,就必须等到下一个周期才能被用户程序发现。


今天先聊到这里,下期我们介绍RTS 调试服务接口

PS:有小伙伴问文章中的代码哪里可以获取,官方的Beremiz是软PLC,仅支持PC,不过有俄罗斯的攻城狮在Github上开源了STM32平台的YAPLC,我将它移植到了NXP Kinetis系列产品,并做出了一些必要的修改,原本的用户程序下载是通过STM32 ISP软件实现的,这个操作方式对用户来说不是非常友好,我修改了它的调试服务接口,添加了下载命令,实现了Beremiz自动下载的功能。后续我会整理相关代码并上传到https://gitee.com/hudiekaxp