程序编码(共3篇)
程序编码 篇1
摘要:针对分段收费系统中程序逻辑结构复杂、维护升级困难等问题,提出了一种在计费程序中运用区间编码的方法,结合实际应用中的收费标准,阐述了区间编码应用原理,给出了区间基于区间编码的编程模型,并对区间编码方法的性能和优势进行了讨论。该方法可显著改善程序的逻辑结构,方面计费程序维护和升级。
关键词:区间编码,计费程序,程序设计
0引言
日常生活中,很多计费系统在不同时间段有不同的收费标准,例如电话通信计费、出租车计费、停车场收费和网吧计费等,在不同时段使用服务需要支付的费用往往相差较大。这些收费标准在数学上可使用分段函数来表示,但在使用编程语言实现时,需要比较复杂的分支选择结构来描述[1],当计费系统划分的收费区间较多时,程序的逻辑将变得非常复杂,如果程序 设计使用 了大量的“if…else…”选择语句,那么程序的可读性将变得极差[2,3],这不利于收费系统的维护和升级。为此,本文提出了一种区间编码方法,可以有效简化程序设计,给计费系统的维护和升级带来方便。
1算法设计
本文结合某停车场收费实例详述算法原理,停车场收费规则如下:
将一昼夜划分为 两个收费 时间段:(T0,T1)和 (T1,T0),例如白天计费时段(6:00-22:00)和夜晚计 费时段(22:00-6:00)。不同区间有不同的收费标准,区间(T0,T1):第一计费时间单位收费x元,每超过一个计费单位按y元收费;区间(T1,T0):统一收费z元,不论时间长短。
对于停车超过一个昼夜的情况,整个昼夜计费为区间(T0,T1)和区间 (T1,T0)的计费之和,不足一昼夜的部分,依照上述规则按实际情况进行收费。在上述计费标准中,停车不满一个计费时间单位的按一个计费时间单位计费。
1.1区间模型
根据上述收费标准,一昼夜以24小时制表示,将00:00作为昼夜分界点[4],其极坐标 如图1所示。由于昼 夜分界点的存在,实际上两个收费区间被划分为3个收费区间,即(T0,T1)、(T1,Td)和区间(Td,T0)。
区间模型中,每个符号的意义说明如表1所示。
1.2计费区间编码
根据一昼夜计费区间划分情况,对每个计费区间进行二进制行编码[5]。本计费系统中有3个计费区间,需要两位二进制数来进行编码。对于有N个计费区间的情况,编码位数i与N满足约束表达式:2i-1<N≤2i。区间编码如表2所示。
对于任意的停车开始时间和停车结束时间都落在三者之中的任意一个区间,因此可以用一个区间对来表征一次停车,区间对用四位二进制数表示前两位代表停车开始时间所在区间,后两位代表收费结束时间所在区间,三区间的任意组合形成的 区间对集 合包括了 所有计费 情况。穷举每一种组合可以得出每一种收费情况的编码和计费表达式,收费编码如表3所示。
说明:[(t1 -T0)/tΔ]Γ 表示对得到的数据进行上取整,例如12.03上取整为12,12.00上取整为12;一个昼夜的收费价格由 [(T1 -T0)/tΔ]Γ ×y+ (x-y)+z确定;aa’、bb’、cc’表示停车开始时间和停车结束时间在同一区间,但停车结束时间小于停车开始时间
2编程模型
根据计费编码,可设计清晰的编程步骤,整个算法流程如图2所示。整个程序设计基于switch分支选择结构,首先计算t0~t1 时间间隔内包含整个昼夜的数目,即时间间隔除24小时所得的商数,根据商数计算整昼夜收费价格,然后根据t0、t1所在区间确定收费编码进而确定要采用的计费表达式,根据计费表达式计算不足一昼夜部分的计费价格,最后将与上述整昼夜收费价格相加得到总的收费价格。
计费编码占4bit,可选用一个字节表示。例如停车开始时间为09:00,结束时间是当天23:00的情况,根据区间编码,开始时间对应的区间码为01,结束时间对应的区间码为10,因此计费 编码为 (0b00000001< <2)+0b00000010 ,即0110,值为6。
3性能分析
与普通分段收费算法相比,引入区间编码方法可以有效改善计费算法设计,利用区间排列组合方法,可以穷举任意一种收费情况,防止遗漏;对区间进行编码后,在设计程序时,使用switch…case…语句替代if…else…语句,同时利用switch语句的顺序执行特性,对相同的 收费表达式进行合并。以上述停车场计费标准为例,使用区间编码方法,至少可以省去12个“if…else…”语句对,极大改善了程序的逻辑结构保证了程序的可读性;同时该算法具有很好的可扩展性,当计费区间增多,只需增加区间的编码位数即可容纳增加的计费区间。随着区间增多,区间编码方法对计费算法的辅助设计效果愈加明显。
4结语
本文主要阐述区间编码方法在计费系统中的应用原理,所涉及的停车场收费标准是实际运用中的一个计费系统特例,在其它收费场合可能并不适用,例如收费规则中没有考虑不同区间之间的缓冲时间问题,但它具有分段收费问题的一般特性,并不妨碍区间编码方法的运用。对于其它分段计费系统,可参照本文应用原理设计收费程序,改善程序的逻辑结构,方便计费系统的维护和升级。
程序编码 篇2
1,一般情况下对话框第一栏都是菜单栏,因此首先就是建立菜单栏。在GUI控件使用时所有的控件都是层层嵌套的,说的意思就是控件依托,并最终整合到面板上,进而在添加事件侦听器,以响应时间的发生;
建立菜单:
private JMenu JSSFMenu=new JMenu(“结算收费(J)”);private JMenuItem DBCZItem=new JMenuItem(“电表出帐/审核(A)”);private JMenuItem DBJFItem=new JMenuItem(“电表缴费(F)”);
* GUI程序设计模式总结:
* GUI框架的设计步骤:
* 1,首先要建立主框架:方法如下: JFrame f=new JFrame();
* 2,取得框架的内容窗格 Container contentPane=f.getContentPane();
* 3,在制作复杂的用户界面时,常常需要使用多个JPanel将复杂的界面分解为相对建大的子界面,然后在对每个JPanel进行布局;
JPanel p=new JPanel();
* 在布局管理器中:
* 对于流式布局则是直接调用add(p);里面的p指的是组件的对象
* 对于边框布局都是调用add的重载函数来实现的;例如边框布局采用的add(new JButton(“North”,BorderLayout.NORTH));
setLayout();
public void setLayout(LayoutManager mgr)设置此容器的布局管理器。
参数:
mgr-指定的布局管理器
例如设置网格布局管理器:p.setLayout(new GridLayout(3,2));
* 对于网格布局则有下面的添加组件的代码框架: JPanel p=new JPanel();
p.setLayout(new GridBagLayout());容器p设置为网格袋布局
/创建约束条件:
GridBagConstraints constraints=new GridBagConstraints();
//按照约束条件constraints将txtField添加到p中;
p.add(txtField,constraints);
* 4,将面板添加到框架的内容窗格中;contentPane.add(p);这里的p就是组件对象;
* 这里的add的添加方法不同就有不同的布局管理:这里的例子是边框布局
2,处理控件的依耐关系,及消息的定义;各种细节的设计(例如快捷键)
消息的处理机制将是以后重点的研究对象,本程序内采用匿名内部类的方法实现;
任何实现了Actionlistner接口的类所生产的对象,均可作为事件的侦听器,并实例化actionformed()这里面有消息处理的方法;
3,控件的逐级加入,JSSFMenu.add(DBJFItem);//将下拉子菜单加入到主菜单中去 menuBar.add(JSSFMenu);//将主菜单加入到主菜单工具条中
4,引入面板对象JPanel,在这之前要定义到要加入到面板的控件,例如标签,Jlable 可以对控件进行必要地显示效果设置,这些都可以调用现有的方法实现,参考说明文档就可以实现;
最后要设置控件的布局模式:
5,将面板加入到框架的内容窗格中; contentPanel.add(P);在制作复杂的用户界面时,常常需要使用多个JPanel将复杂的界面分解为较为简单的子界面,然后再对每个JPanel进行布局。此时我们知道,面板就是一个容器,以此为依托包含各种组件,最后在框架中时并独立设置这些组件的布局方式:contentPane.add(statusPanel,BorderLayout.SOUTH);这里的这个例子就是将statusPanel加入到框架中去,并设置了其在主框架中的布局:south 其实面板对象内部,也是需要设置组件的布局方式,因为面板中还有标签,文本。如下:
LayoutUtil.add(statusPanel,GridBagConstraints.NONE, GridBagConstraints.CENTER,0,0,0,0,1,1,labStatus);这也遵循逐级加入的思想,这种逐级加入的设计思想,使GUI程序设计的由内至外,逐步添加。使程序更加明朗;
代码如下: /* * 主要研究java程序设计的基本步骤与方法,以及程序在设计过程中应注意的问题及原则 * 这是主程序MAINAPP 也就是主程序的入口,是显示框架的模块 * 研究框架的设计模式以及主要的java技术,* 对话框设计的一般模式如下:
* 1,确定所选取的控件,一般情况下,都是在第一行建立菜单栏。* 建立菜单:注意上下菜单的依耐关系;
* 2,主程序界面的显示:获取框架的内容窗格;Container contentPane=f.getContentPanel();* 如下的例子: * * */
import javax.swing.*;import javax.swing.event.*;import java.awt.*;import java.awt.event.*;import javax.swing.border.*;import java.sql.*;import java.util.*;import edu.njust.cs.*;
class MainApp extends JFrame{ //系统启动时的等待画面
private JFrame splashScreen=null;//收费结算菜单
private JMenu JSSFMenu=new JMenu(“结算收费(J)”);private JMenuItem DBCZItem=new JMenuItem(“电表出帐/审核(A)”);private JMenuItem DBJFItem=new JMenuItem(“电表缴费(F)”);//基础资料菜单
private JMenu JCZLMenu=new JMenu(“基础资料(Z)”);private JMenuItem GYItem=new JMenuItem(“雇员资料(G)”);private JMenuItem CBBItem=new JMenuItem(“抄表班(C)”);private JMenuItem SFBItem=new JMenuItem(“收费班(S)”);private JMenuItem FLItem=new JMenuItem(“费率(F)”);private JMenuItem DBItem=new JMenuItem(“电表资料(D)”);//设置菜单
private JMenu SZMenu=new JMenu(“设置(C)”);private JMenuItem SysConfigItem=new JMenuItem(“系统参数设置...(S)”);//帮助菜单
private JMenu HelpMenu=new JMenu(“帮助(H)”);JMenuItem aboutItem=new JMenuItem(“关于本程序...(A)”);//内容窗格
private Container contentPane;//当前内容窗格中的面板
private JPanel selectedPanel=null;//状态信息
JLabel labStatusContent=null;//登录用户
private JLabel labUserContent=null;//数据库连接
Connection con=null;//参数信息
private Properties prop=null;
public MainApp(){ /*SwingUtilities.invokeLater(new Runnable(){ public void run(){ showSplashScreen();} });*/ //创建菜单
setIconImage(new ImageIcon(“image/title20.jpg”).getImage());this.setTitle(“结算收费演示系统”);contentPane=getContentPane();//创建菜单
constructMenu();//创建状态条
constructStatusPanel();//读入系统参数 } public void constructMenu(){ //创建菜单 //构建菜单
JMenuBar menuBar=new JMenuBar();//收费结算菜单----------------BEGIN JSSFMenu.setMnemonic(KeyEvent.VK_J);//表示助记符的键代码 //电表出帐
DBCZItem.setMnemonic(KeyEvent.VK_A);/*DBCZItem.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ MainApp.this.setSelectedPanel(new DBCZPanel(MainApp.this,con));} });*/ //利用匿名内部类实现消息侦听
JSSFMenu.add(DBCZItem);//将下拉子菜单加入到menuBar中;
//电表缴费
DBJFItem.setMnemonic(KeyEvent.VK_F);
JSSFMenu.add(DBJFItem);menuBar.add(JSSFMenu);//收费结算菜单----------------END
//基础资料菜单----------------BEGIN JCZLMenu.setMnemonic(KeyEvent.VK_Z);//雇员
GYItem.setMnemonic(KeyEvent.VK_G);
JCZLMenu.add(GYItem);//分隔线
JCZLMenu.addSeparator();//抄表班
CBBItem.setMnemonic(KeyEvent.VK_C);
JCZLMenu.add(CBBItem);//收费班
SFBItem.setMnemonic(KeyEvent.VK_S);
JCZLMenu.add(SFBItem);//费率
FLItem.setMnemonic(KeyEvent.VK_F);
JCZLMenu.add(FLItem);//分隔线
JCZLMenu.addSeparator();//电表
DBItem.setMnemonic(KeyEvent.VK_D);
JCZLMenu.add(DBItem);menuBar.add(JCZLMenu);//设置菜单-------------BEGIN SZMenu.setMnemonic(KeyEvent.VK_C);//系统参数设置
SysConfigItem.setMnemonic(KeyEvent.VK_S);SZMenu.add(SysConfigItem);menuBar.add(SZMenu);//设置菜单-------------END //帮助菜单-------------BEGIN HelpMenu.setMnemonic(KeyEvent.VK_H);//关于
aboutItem.setMnemonic(KeyEvent.VK_A);HelpMenu.add(aboutItem);menuBar.add(HelpMenu);//帮助菜单-----------END setJMenuBar(menuBar);}
//创建状态条
public void constructStatusPanel(){ //将控件几种加入框架,并利用合理利用布局模式
JPanel statusPanel=new JPanel();//新建一个面板JPanel,这个面板对象只管下面状态栏的显示;
Border loweredBevelBorder=BorderFactory.createLoweredBevelBorder();//设置边界样式 statusPanel.setLayout(new GridBagLayout());//利用面板对象设置布局模式;为GridBagLayout布局
JLabel labStatus=new JLabel(“ 提示信息 ”);labStatusContent=new JLabel();JLabel labUser=new JLabel(“ 用户名 ”);labUserContent=new JLabel();labUserContent.setPreferredSize(new Dimension(90,3));
labUser.setBorder(loweredBevelBorder);labUserContent.setBorder(loweredBevelBorder);labStatus.setBorder(loweredBevelBorder);labStatusContent.setBorder(loweredBevelBorder);//设置组件边框;
LayoutUtil.add(statusPanel,GridBagConstraints.NONE, GridBagConstraints.CENTER,0,0,0,0,1,1,labStatus);LayoutUtil.add(statusPanel,GridBagConstraints.BOTH, GridBagConstraints.CENTER,100,100,1,0,1,1,labStatusContent);LayoutUtil.add(statusPanel,GridBagConstraints.NONE, GridBagConstraints.CENTER,0,0,2,0,1,1,labUser);LayoutUtil.add(statusPanel,GridBagConstraints.VERTICAL, GridBagConstraints.CENTER,0,100,3,0,1,1,labUserContent);//设置控件的布局,调用自定义包中的方法;
contentPane.add(statusPanel,BorderLayout.SOUTH);}
public static void main(String []args){ Font font=new Font(“微软雅黑”, 0, 12);SetFont.setFont(font);//设置全局字体 MainApp ma=new MainApp();ma.setDefaultCloseOperation(EXIT_ON_CLOSE);ma.setSize(600,400);//设置主画面初始大小 ma.show();//满屏显示
//ma.setExtendedState(MAXIMIZED_BOTH);} }
程序编码 篇3
编码器或直线式位移传感器是工业自动化生产中必不可少的控制器件。如果所有设备编码器或直线式位移传感器都工作正常、程序编写合理, 设备通常并不会出现问题。但工业生产现场条件恶劣, 在高温、振动、电磁干扰等情况下, 编码器采集数据可能出现错误信号, 严重者编码器本身就由于干扰或寿命到期而损坏。由于此类事件的不可预知性, 如果设备程序没有对传感器等的校验程序, 继续按照错误信号执行动作, 必然会出现误动作、设备损坏、制品不合格甚至人身伤害等严重事故发生。其解决方法可以通过安装冗余传感器或增加其他用来检测传感器故障与否的硬件, 但势必又增大了成本, 因此必须在成本和有效避免危险之间找到平衡点。本文介绍了一种通过编程来检测编码器或直线式位移传感器故障, 以提高设备安全控制的方法。
1 编码器校验块
本文使用西门子step 7编程软件来描述编码器校验程序, 其他PLC编程软件的程序可照此思路编写相应的程序。Fc2是编码器校验块, 这个块的目的是把编码器采集回来的Actual Pos (实际数) 与控制机构的最大和最小极限位置数、1个Switch Cal (极限位置处接近开关) 、1个Switch Sv (中间位置处接近开关, 此开关可选) 位置做比较运算, 校验编码器是否出现故障。
如图1所示编码器诊断块有12个输入:Actual Pos编码器采集的位置数;Min Pos检测行程最小位置值;Max Pos检测行程最大位置值;Ctrl On编码器校验块的使能开关;Switch Cal极限位置处接近开关程序地址;Min Pos Cal极限位置处接近开关位置最小值;Max Pos Cal极限位置处接近开关位置最大值;Sv On中间位置处接近开关使能开关;Switch Sv中间位置处接近开关程序地址;Min Switch Sv中间位置处接近开关位置最小值;Max Switch Sv中间位置处接近开关位置最大值;Window窗口值。3个输出:Warning警告;Diag诊断;Calibrated校验结果;9个临时变量:Sv Max Pos OK;Sv Min Pos OK;Sv Min Max1OK;SvMin Max0OK;Min1;Min0;Max0;Max1;Rel Cal。
2 校验程序
为了便于理解程序, 校验程序中每个位置如图2所示。
判断选中中间位置处接近开关参与校验 (Sv On) 的情况下, Max0小于等于Min0则出现数字重叠, 警告输出, 图2中是如果“G”小于等于“I”则设置不合适, 报警 (Warning) 需要重新设定值。程序如下:
判断实际值是否大于等于最小值, 如图2, 数据是否大于“L” (Min Pos) , 如果是, 此项最小值检测正常 (Min Pos OK) 。程序如下:
再判断实际值是否小于等于最大值, 如图2, 数据是否小于“A” (Max Pos) , 如果是, 此项最大值检测正常 (Max Pos OK) 。程序如下:
判断选中中间位置处接近开关 (Switch Sv) 检测的情况下, 判断中间位置处接近开关发讯时数据是否正常, 中间位置处接近开关发讯时, 编码器实际数是否在如图2中, 大于“K” (Min1) 且小于“E” (Max1) , 如果是, 此项检测正常 (Sv Min Max1OK=1) 。程序如下:
再次判断选中中间位置处接近开关 (Switch Sv) 检测的情况下, 判断中间位置处接近开关不发讯时数据是否正常。接近开关2不发讯时, 编码器实际数是否在如图2中, 数据是否在大于“G” (Max0) 或者小于“I” (Min0) 区域, 如果是, 此项检测正常 (Sv MinMax0OK=1) 。程序如下:输
引入中间变量“Rel Cal”, 看实际值是否在如图2中, 大于“D” (Min Pos Cal) 和小于“B” (Max Pos Cal) 之间, 如果是“Rel Cal=1”。程序如下:
判断极限位置处接近开关 (Switch Cal) 在发讯时, “Rel Cal”是否为“1”, 即大于“D” (Min Pos Cal) 和小于“B” (Max Pos Cal) 之间, 如果是, 正常, 如果不是, 数据有误, “Diag”为1。程序如下:
判断在极限位置处接近开关 (Switch Cal) 在发讯时, 如果“Rel Cal”为“1”, 同时, 4个判断条件:“MaxPos OK”、“Min Pos OK”、“S2Min Max1OK”、“S2Min Max-0OK”都为1, “Diag”为“0”, 校验块使能“Ctrl On”为“1”的情况下, 输出校验正常“Calibrated”为1, 并且输出校验正常“Calibrated”自保。程序如下:
编写好校验程序块后, 设备的每一个编码器就可以共用此块校验了, 对应不同的编码器输入不同的输入数据, 并且可以单独控制是否需要校验, “Ctrl On”是否为“1”。如果某个编码器故障, 或由于调试需要不想对某个编码器校验, 只要在该编码器校验程序, 如图1中的“M10.0”处给相应的输入“1”为校验, “0”为不校验。是用一个极限位置接近开关校验还是用2个接近开关校验, “Sv On”是否为“1”。如图1中的“M10.1”处输入“1”为极限位置接近开关和中间位置接近开关校验, “0”为只用极限位置接近开关校验。建议使用2个接近开关校验, 因为中间处接近开关可设置在设备的某危险位置的临界位置上, 一旦检测到校验有误, 可马上停止机构“手动”“自动”动作, 处理故障, 查看是编码器故障还是接近开关松动, 或者是损坏, 之后在校验通过后才能动作, 从而把危险降到最低。在把校验结果“Calibrated”绑定在每个与此动作相关的机构“手动”、“自动”动作条件上时, 能大大提高设备的安全稳定性。
3 结论
用编程软件实现设备安全校验是一种成本低、易实现、效果好的方法。在笔者对挤压机自动控制系统若干年的调试及用户反馈的设备运行状况来看, 校验程序经受住了时间的考验, 对提高系统的可靠性起到了重要作用。对于其他工业过程控制中涉及编码器或是直线式位移传感器的程序安全控制, 都可起到有效校验作用。
参考文献
[1]楼晓春.PLC控制系统外部故障的自诊断设计[J].轻工机械, 2008, 26 (3) :67-69.
[2]康毅, 李正文, 吴锦强.对提高PLC系统可靠性的探讨[J].测控技术, 2004, 23 (10) .
[3]WOLFGANG A.HALANG, BERNDJ.KRAMER.Safety Assurance in Process Control.IEEE SOFTWARE, 1994, 61-67[J].
[4]罗雪莲.PLC控制系统的故障诊断技术[J].兵工自动化, 2004, (3) :79-81.
[5]刘茂银, 梅碧舟.压力机控制系统中PLC的应用及设计[J].锻压装备与制造技术, 2007, 42 (3) :45-47.
[6]张传斌, 王俊豪.PLC在设备故障检测与诊断中的应用[J].机械制造与自动化, 2006, (5) :166-167.
[7]朱朝宽.机床PLC改造过程中的故障自诊断设计[J].新技术新工艺, 2005, (5) :40-41.