WinCC调用C++生成的DLL文件

代码:
https://download.csdn.net/download/weixin_37928884/81123943
https://download.csdn.net/download/weixin_37928884/69778708

VS2012创建过程
请添加图片描述

请添加图片描述

WinCC调用C++生成的DLL文件
WinCC全局脚本

#include "apdefap.h"

int gscAction( void )
{
// WINCC:TAGNAME_SECTION_START
// syntax: #define TagNameInAction "DMTagName"
// next TagID : 1
// WINCC:TAGNAME_SECTION_END

// WINCC:PICNAME_SECTION_START
// syntax: #define PicNameInAction "PictureName"
// next PicID : 1
// WINCC:PICNAME_SECTION_END

//#pragma code("C:\Users\Test\Desktop\math_boiler\siemens\Debug\siemens_fb41.dll") 
#pragma code("C:\Users\Test\Desktop\math_boiler\siemens\Release\siemens_fb41.dll") 

float TCONT_C(float PV_IN41,float SP_INT41,float DISV41,float GAIN41,float TI41,float TD41,float DEADB_W41,float MAN41,float LMN_LLM41,float LMN_HLM41,unsigned char MAN_ON41);

#pragma code()

float siemens_lmn1;
float siemens_lmn2;

siemens_lmn1 = TCONT_C(98,100,0,2.0,40,20,0,50,0,100,0);
siemens_lmn2 = TCONT_C(98,100,0,2.0,40,20,0,50,0,100,1);

printf("siemens.FB41.lmn:%4.4f,%4.4f\r\n",siemens_lmn1,siemens_lmn2);

return 0; 
}

siemens_fb41.h

#pragma once
extern "C" __declspec(dllexport) float TCONT_C(float PV_IN41,float SP_INT41,float DISV41,float GAIN41,float TI41,float TD41,float DEADB_W41,float MAN41,float LMN_LLM41,float LMN_HLM41,unsigned char MAN_ON41);

siemens_fb41.cpp

// siemens_fb41.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"

// siemens_fb41.cpp : 定义控制台应用程序的入口点。
//
#include "siemens_fb41.h"

#ifndef TRUE
  #define TRUE 0x01
#endif 
#ifndef FALSE
  #define FALSE 0x00
#endif 

unsigned char    COM_RST = FALSE;  //完全重启动    
unsigned char    MAN_ON =  FALSE ;//TRUE;   //手动值打开   
unsigned char    PVPER_ON = FALSE;  //外设过程变量打开      
unsigned char    P_SEL = FALSE;   //比例作用打开      
unsigned char    I_SEL = TRUE;   //积分作用打开 
unsigned char    INT_HOLD = FALSE;  //积分作用保持 
unsigned char    I_ITL_ON = FALSE;  //积分作用初始化 
unsigned char    D_SEL = FALSE;  //微分作用打开 
    
//CYCLE :         TIME := T#1S;   //采样时间 
float CYCLE = 1; 
float SP_INT = 0.0;//内部设定值   
float PV_IN = 0.0;    //过程变量输入 
//PV_PER :        WORD := W#16#0; //外设过程变量    
int  PV_PER = 0;    
float MAN = 0.0;    //手动值 
float GAIN = 2.0;    //比例增益 
    
//TI :            TIME := T#20S;  //积分复位时间 
float TI = 20; 
//TD :            TIME := T#10S;  //微分时间 
float TD = 10;     
//TM_LAG :        TIME := T#2S;   //微分作用时间延时 
float TM_LAG = 2;    
float DEADB_W = 0.0;    //死区带宽     
float LMN_HLM = 100.0;  //积分值上限    
float LMN_LLM = 0.0;    //积分值下限     
float PV_FAC = 1.0;    //过程变量因子     
float PV_OFF = 0.0;    //过程变量偏移量     
float LMN_FAC = 1.0;    //调节值因子    
float LMN_OFF = 0.0;    //调节值偏移量     
float I_ITLVAL = 0.0;    //积分作用的初始化值    
float DISV = 0.0;    //干扰变量 
    
float LMN = 0.0;    //调节值   
//LMN_PER :       WORD := W#16#0; //外设调节值 
float  LMN_PER = 0;   
unsigned char    QLMN_HLM = FALSE;  //达到调节值上限    
unsigned char    QLMN_LLM = FALSE;  //达到调节值下限    
float LMN_P = 0.0;    //比例分量    
float LMN_I = 0.0;    //积分分量    
float LMN_D = 0.0;    //微分分量    
float PV = 0.0;    // 
float ER = 0.0;    //误差信号 
  
float sInvAlt = 0.0;    //上周期比例偏差值    
float sIanteilAlt = 0.0;    //上周期积分值 
float sRestInt = 0.0;    //上周期积分偏差量浮点数计算偏差
float sRestDif = 0.0;    //上周期微分偏差量浮点数计算偏差
float sRueck = 0.0;    //    
float sLmn = 0.0;    //上周期调节值    
unsigned char    sbArwHLmOn = FALSE;  //上周期达到调节值上限    
unsigned char    sbArwLLmOn = FALSE;  //上周期达到调节值下限    
unsigned char    sbILimOn = TRUE;   //备用-本程序没有使用该变量 

float TCONT_C(float PV_IN,float SP_INT,float DISV,float GAIN,float TI,float TD,float DEADB_W,float MAN,float LMN_LLM,float LMN_HLM,unsigned char MAN_ON)
{
	float LMN = 0;
	//VAR_TEMP 
	float rCycle;    //采样时间浮点值   
	float Iant;    //积分增量  
	float Diff;    //积分量    
	float Istwert;    //过程变量浮点值    
	float ErKp;    //偏差比例值     
	float rTi;    //积分时间浮点值     
	float rTd;    //微分时间浮点值 
	float rTmLag;    //微分作用时间延时浮点值    
	float Panteil;    //比例值    
	float Ianteil;    //积分值    
	float Danteil;    //微分值 
    
	float Verstaerk;    //    
	float RueckDiff;    //    
	float RueckAlt;    //上周期积分量    
	float dLmn;    //调节量    
	float gf;    //Hilfwert   
	float rVal;    //Real Hilfsvariable 
	if (COM_RST == TRUE) //PID初始化 
	{
        sIanteilAlt = I_ITLVAL ; 
        
		LMN = 0.0 ;        
		QLMN_HLM = FALSE ;        
		QLMN_LLM = FALSE ; 
		LMN_P = 0.0 ;         
		LMN_I = 0.0 ;        
		LMN_D = 0.0 ;        
		LMN_PER = 0 ; //LMN_PER := W#16#0 ;        
		PV = 0.0 ;         
		ER = 0.0 ;         
		sInvAlt = 0.0 ;        
		sRestInt = 0.0 ;         
		sRestDif = 0.0 ;         
		sRueck = 0.0 ;        
		sLmn = 0.0 ;       
		sbArwHLmOn = FALSE ;        
		sbArwLLmOn = FALSE ;	 
	}
    
	else
	{       
		rCycle = CYCLE / 1000.0 ;   //采样时间换为浮点数值//rCycle := DINT_TO_REAL( TIME_TO_DINT( CYCLE ) ) / 1000.0 ;   //采样时间换为浮点数值        
		Istwert = PV_PER * 0.0036898 ;//Istwert := DINT_TO_REAL( INT_TO_DINT( WORD_TO_INT ( PV_PER ) ) ) * 0.0036898 ;         
		Istwert = Istwert * PV_FAC + PV_OFF ;    //外设输入转换为浮点数值 
        
		if (PVPER_ON == FALSE)     //过程变量选择 
		{
			Istwert = PV_IN ;
		}

		PV = Istwert ; 
        
		ErKp = SP_INT - PV ;        //计算偏差 
        
		if (ErKp < -DEADB_W)
		{
				ER = ErKp + DEADB_W ; 
   		}     
		else if(ErKp > DEADB_W)
		{
			ER = ErKp - DEADB_W ; 
		}
		else
		{
			ER = 0.0 ;
		}

		ErKp = ER * GAIN ; //偏差比例增益 
        
		rTi = TI / 1000.0 ; //rTi := DINT_TO_REAL( TIME_TO_DINT( TI ) ) / 1000.0 ; 
        
		rTd = TD / 1000.0 ;//rTd := DINT_TO_REAL( TIME_TO_DINT( TD ) ) / 1000.0 ; 
        
		rTmLag = TM_LAG / 1000.0 ; //rTmLag := DINT_TO_REAL( TIME_TO_DINT( TM_LAG ) ) / 1000.0 ; 
        
		if (rTi < rCycle * 0.5)      //积分时间必须 >= 采样时间的0.5倍 
		{
			rTi = rCycle * 0.5; 
		} 
        
		if (rTd < rCycle)             //微分时间必须 >= 采样时间 
		{
			rTd = rCycle ;
		}
        
		if (rTmLag < rCycle * 0.5)    //微分作用延时时间必须 >= 采样时间的0.5倍 
		{
			rTmLag = rCycle * 0.5 ;
		}
       
		if (P_SEL == TRUE)    //比例作用投入 
		{
			Panteil = ErKp ; 
		}
		else
		{
			Panteil = 0.0 ; 
		}
        
		if (I_SEL == TRUE)    //积分作用投入 
		{
            
			if (I_ITL_ON == TRUE)     //积分初始化 
			{
				Ianteil = I_ITLVAL ; 
				sRestInt = 0.0 ; 
			}
			else if(MAN_ON == TRUE)  //手动值输入时的积分量计算用于用于手动切换自动无扰切换
			{
				Ianteil = sLmn - Panteil - DISV ; 
				sRestInt = 0.0 ;
			}           
			else    //积分计算 
			{
				Iant = ( rCycle / rTi ) * ( ErKp + sInvAlt ) * 0.5 + sRestInt ;
				if (((Iant > 0.0 && sbArwHLmOn ) || INT_HOLD ) || ( Iant < 0.0 && sbArwLLmOn )) //抗积分饱和 
				{
					Iant = 0.0 ;  
				}
				Ianteil = sIanteilAlt + Iant ; //当前积分值 := 上时刻积分值 + 本次积分量               
				sRestInt = sIanteilAlt - Ianteil  + Iant ; //感觉 sRestInt一直等于0.0 ;不知为何,通过运行发现不为0.0可能是浮点数计算误差              
			}
		}
		else
		{
			Ianteil = 0.0 ; 
			sRestInt = 0.0 ; 
		}
		Diff = ErKp ; 
        
		if (MAN_ON == FALSE && D_SEL == TRUE)     //微分作用投入 
		{
			Verstaerk = rTd / ( rCycle * 0.5 + rTmLag ) ;            
			Danteil = ( Diff - sRueck ) * Verstaerk ;              
			RueckAlt = sRueck ;             
			RueckDiff = rCycle / rTd * Danteil + sRestDif ;             
			sRueck = RueckDiff + RueckAlt ;             
			sRestDif = RueckAlt - sRueck + RueckDiff ; //同积分一样计算微分误差量 
		}        
		else
		{			            
			Danteil = 0.0 ;             
			sRestDif = 0.0 ;             
			sRueck = Diff ; 
		} 
 
		dLmn = Panteil + Ianteil + Danteil + DISV ; //PID输出
		if (MAN_ON == TRUE) //PID手动之打开 
		{   
			dLmn = MAN ; 
		}
		else
		{
			if ((I_ITL_ON == FALSE) && I_SEL == TRUE)   //干扰量处理
			{
				if (Ianteil > LMN_HLM - DISV && dLmn > LMN_HLM && dLmn - LMN_D > LMN_HLM)
				{
					rVal = LMN_HLM - DISV ;                     
					gf = dLmn - LMN_HLM ;                     
					rVal = Ianteil - rVal; 
					if (rVal > gf) 
					{                        
						rVal = gf ;                     
					}
					Ianteil = Ianteil - rVal ;
				}
				else if(Ianteil < LMN_LLM - DISV && dLmn < LMN_LLM  && dLmn - LMN_D < LMN_LLM)
				{
					rVal = LMN_LLM - DISV ; 
                    
					gf = dLmn - LMN_LLM ; 
                    
					rVal = Ianteil - rVal ; 
                    
					if (rVal < gf)
					{                       
						rVal = gf ;                   
					}
                    
					Ianteil = Ianteil - rVal ;
				}
			}
		}
            
		LMN_P = Panteil ;      
		LMN_I = Ianteil ;         
		LMN_D = Danteil ;         
		sInvAlt = ErKp ;         
		sIanteilAlt = Ianteil ; 
		sbArwHLmOn = FALSE ;        
		sbArwLLmOn = FALSE ; 
      
		if (dLmn >= LMN_HLM)      //调节辆限幅(上限) 
		{
			QLMN_HLM = TRUE ; 
			QLMN_LLM = FALSE ;             
			dLmn = LMN_HLM ;             
			sbArwHLmOn = TRUE ; 
		}
		else
		{
			QLMN_HLM = FALSE ; 
			if(dLmn <= LMN_LLM)  //调节辆限幅(下限)
			{
				QLMN_LLM = TRUE ;                 
				dLmn = LMN_LLM ;           
				sbArwLLmOn = TRUE ;
			}
			else
			{
				QLMN_LLM = FALSE ;
			}
		}
       
        
		sLmn = dLmn ;         
		dLmn = dLmn * LMN_FAC + LMN_OFF ;         
		LMN = dLmn ;       
		dLmn = dLmn* 276.48 ; 
        
		if (dLmn >= 32512.0) 
		{
			dLmn = 32512.0 ;
		}
		else if(dLmn <= -32512.0) 
		{
			dLmn = -32512.0 ;
		}
         
        
		LMN_PER = dLmn;//LMN_PER := INT_TO_WORD( DINT_TO_INT( REAL_TO_DINT( dLmn) ) ) ; 
    
		}
		//FB"CONT_C"的控制模式从手动切换到自动是无扰切换,反之不是无扰切换,需要通过编程实现。
		//MAN_ON == 0 自动
		//MAN_ON == 1 手动
		//增加如下程序,来实现自动切手动时的无扰动切换
		if(MAN_ON == 0)
		{//上升沿 自动转手动
			MAN = LMN;
		}

		return LMN;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨铮...

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值