Step7中有关时间和定时器的使用和例程1

本文参考西门子技术中心的相关文章整理而成。

在step7中提供了比较丰富的与时间有关的元素,例如定时器、系统时钟以及相关的组织块和系统功能块等,非常方便。

1、定时器

西门子PLC定时器最小时间单元为10ms,可用的定时器指令列表如下:

S_PULSE脉冲定时器
S_PEXT扩展脉冲定时器
S_ODT接通延时定时器
S_ODTS保持接通延时定时器
S_OFFDT断开延时定时器
---(SP)脉冲定时器线圈
---(SE)扩展脉冲定时器线圈
---(SD)接通延时定时器线圈
---(SS)保持接通延时定时器线圈
---(SF)断开延时定时器线圈
西门子PLC定时器有数量限制,如果定时器不够用,可以使用IEC定时器,具体描述参见下面有关IEC定时器的描述。不同型号的CPU定时器的数量是不同的,可以在线从CPU的属性中查看,点击CPU,然后选择PLC ->Module Information...,画面如下:


点击完成后,选择Performance Data按钮。查看Timers数量,画面如下:


2、IEC定时器(SFB3、SFB4、SFB5)

IEC定时器没有数量限制,IEC定时器通过系统功能块SFB3(TP)、SFB4(TON)、SFB5(TOF)来实现,分别对应定时器指令的脉冲定时器、接通延时定时器和断开延时定时器,具体功能块的参数和使用方法可参考在线帮助。

2.1 SFB3(TP)

简单的程序如下:


DB1为SFB3的背景数据块,当M0.0从0变为1定时器启动,10秒钟内M0.1输出为1,时间到后M0.1为0,产生一个10秒的脉冲。如果在10秒钟内M0.0从1变为0,则M0.1的输出不变,从MD2可以读出定时器已运行的时间。

2.2 SFB4(TON)

简单的程序如下:


DB1为SFB4的背景数据块,当M0.0从0变为1定时器启动,定时时间到(10秒钟)M0.1输出为1。如果定时时间未到M0.0从1变为0,则定时器复位,从MD2可以读出定时器已运行的时间。

2.3 SFB5(TOF)

简单的程序如下:


DB1为SFB5的背景数据块,当M0.0为1,则M0.1输出为1,当M0.0从1变为0定时器启动,定时时间到(10秒钟)M0.1输出为0。如果定时时间未到M0.0从0变为1,则定时器复位,从MD2可以读出定时器已运行的时间。

3、系统时钟(SFC0、SFC1、OB1)

3.1 设置系统时钟的两种方法

1)直接使用STEP7软件中的相关指令在联机的情况下直接设定系统时钟,如下图所示,选中项目中的站,使用SIMATIC Manager ->Diagnostic/Setting ->Set Time of Day指令设置系统时钟:


也可打开程序块或硬件组态,使用PLC ->Set Time of Day指令来在线设置系统时钟,画面如下:


勾选“Take from PG/PC”,使用计算机时钟同步PLC时钟,然后点击“Apply”按钮完成。

2)使用SFC0来设置系统时钟

创建一个DB块DB1,打开DB1块定义一个DATE_AND_TIME的变量如图所示:


打开符号表定义DB1的符号名:


这里先介绍一下DATE_AND_TIME变量的格式,其由八个字节组成分别代表年、月、日、时、分、秒、毫秒,最后一个字节0-3位代表星期,4-7为表示毫秒,是以BCD码表示的。


然后打开OB1,首先将需要设定的时间以16进制BCD码的形式赋值给定义的DATA_AND_TIME变量的各个字节,最后一个字节不需要设定,系统会自己计算并赋值,例如设定的时间为07年8月15日13点20份10秒。


在程序中调用SFC0,将存放设定时间的DATA_AND_TIME变量以符号名的方式赋给SFC0的PDT形参,返回变量赋值给MW100,这样当M0.0由0到1时SFC0被执行。


在程序运行后打开监视和修改变量表即可观察到最后一个字节DB1.DBB7的低4位已经被系统自动计算为4即星期三。


为了观察系统时间是否被正确设定,我们在DB1中再定义一个DATA_AND_TIME的变量如图所示:


在OB1中调用SFC1读取系统时钟并将系统时间传送给“DB_time”.readtime变量:


打开Monitor/Modify Variables表,添加变量,通过按动修改变量按钮将M0.0的状态改为true,然后通过按下监视变量按钮观察变量状态


3.2 读取系统时钟

我们可以通过使用SFC1或OB1中的临时变量OB1_DATA_TIME来读取系统时钟。

1)使用SFC1的方法上面已经介绍,不再重复。

2)使用OB1中的临时变量OB1_DATA_TIME来读取系统时钟

OB1的每个循环周期都读取系统时钟并存放在OB1_DATA_TIME临时变量中,如下图所示我们将LB12开始的8个字节赋值给MB12开始的8个字节。


通过监视变量表即可看到实时的系统时钟。




附注:

系统时钟的毫秒值的完整显示方法如下:


由于字节7中的高四位是用于表示毫秒的个位数值的,低4位是用于表示星期的,鉴于显示的原因,使用语句“L W#16#FFF0”和"L B#16#F"分别通过字与(即“AW”)的操作指令将下图所示的QW6和QB8输出地址中相应的值屏蔽掉,否则下图中QW6的值将显示为W#16#7853(而3是表示星期数的),同样QB8的值将显示为B#16#53(5表示毫秒值)。



  • 3
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个简单的例程,用于使用imx6ull内核的epit定时器字符驱动: ```c #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/device.h> #include <linux/uaccess.h> #include <linux/errno.h> #include <linux/slab.h> #include <linux/io.h> #include <linux/interrupt.h> #define DEV_NAME "epit_timer" #define EPIT_BASE_ADDR 0x020D0000 #define EPIT_IRQ_NUM 88 typedef struct { dev_t dev_num; struct cdev cdev; struct class *cls; struct device *dev; void __iomem *epit_base; int irq_num; bool is_opened; } epit_timer_t; static epit_timer_t epit_timer; static irqreturn_t epit_irq_handler(int irq, void *dev_id) { // TODO: interrupt handler return IRQ_HANDLED; } static int epit_open(struct inode *inode, struct file *filp) { if (epit_timer.is_opened) { return -EBUSY; } epit_timer.is_opened = true; filp->private_data = &epit_timer; return 0; } static int epit_release(struct inode *inode, struct file *filp) { epit_timer.is_opened = false; return 0; } static ssize_t epit_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { // TODO: read timer value return -EINVAL; } static ssize_t epit_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { // TODO: write timer value return -EINVAL; } static const struct file_operations epit_fops = { .owner = THIS_MODULE, .open = epit_open, .release = epit_release, .read = epit_read, .write = epit_write, }; static int __init epit_init(void) { int ret; // Allocate device number epit_timer.dev_num = 0; ret = alloc_chrdev_region(&epit_timer.dev_num, 0, 1, DEV_NAME); if (ret < 0) { printk(KERN_ERR "Failed to allocate device number: %d\n", ret); return ret; } // Initialize cdev structure cdev_init(&epit_timer.cdev, &epit_fops); epit_timer.cdev.owner = THIS_MODULE; // Add cdev to system ret = cdev_add(&epit_timer.cdev, epit_timer.dev_num, 1); if (ret < 0) { printk(KERN_ERR "Failed to add cdev: %d\n", ret); goto err_cdev_add; } // Create device class and device epit_timer.cls = class_create(THIS_MODULE, DEV_NAME); if (IS_ERR(epit_timer.cls)) { ret = PTR_ERR(epit_timer.cls); printk(KERN_ERR "Failed to create class: %d\n", ret); goto err_cls_create; } epit_timer.dev = device_create(epit_timer.cls, NULL, epit_timer.dev_num, NULL, DEV_NAME); if (IS_ERR(epit_timer.dev)) { ret = PTR_ERR(epit_timer.dev); printk(KERN_ERR "Failed to create device: %d\n", ret); goto err_dev_create; } // Map epit base address epit_timer.epit_base = ioremap(EPIT_BASE_ADDR, 0x1000); if (!epit_timer.epit_base) { printk(KERN_ERR "Failed to map epit base address\n"); ret = -ENOMEM; goto err_ioremap; } // Request irq epit_timer.irq_num = EPIT_IRQ_NUM; ret = request_irq(epit_timer.irq_num, epit_irq_handler, IRQF_TRIGGER_RISING, DEV_NAME, &epit_timer); if (ret < 0) { printk(KERN_ERR "Failed to request irq: %d\n", ret); goto err_request_irq; } // Success printk(KERN_INFO "epit timer driver loaded\n"); return 0; err_request_irq: iounmap(epit_timer.epit_base); err_ioremap: device_destroy(epit_timer.cls, epit_timer.dev_num); err_dev_create: class_destroy(epit_timer.cls); err_cls_create: cdev_del(&epit_timer.cdev); err_cdev_add: unregister_chrdev_region(epit_timer.dev_num, 1); return ret; } static void __exit epit_exit(void) { // Free irq free_irq(epit_timer.irq_num, &epit_timer); // Unmap epit base address iounmap(epit_timer.epit_base); // Destroy device class and device device_destroy(epit_timer.cls, epit_timer.dev_num); class_destroy(epit_timer.cls); // Remove cdev from system cdev_del(&epit_timer.cdev); // Free device number unregister_chrdev_region(epit_timer.dev_num, 1); printk(KERN_INFO "epit timer driver unloaded\n"); } module_init(epit_init); module_exit(epit_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("imx6ull epit timer driver"); ``` 此代码仅供参考,其的TODO注释需要根据具体的应用场景来实现。同时,还需要在Makefile添加编译该模块的规则。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值