Configure PLC Communication with User Program

Sep 14, 2025 min read

Introduction

I have seen many cases where there are multiple PLCs using the same program and the only difference between them is their communication configurations. In most of these cases, engineers have to manually change the PLCs’ communication configurations and download the hardware configuration.

The truth is it doesn’t have to be like that. In this article, I’m going to introduce a way to configure the SIEMENS PLC’s communication configuration with user program and recipe so that you can keep the same TIA Portal project and simply update the recipe. I’ll demonstrate using a user program to configure the PLC’s IP address, DNS server and NTP server configurations. There are more configurations to change but similar to my demonstrations.

Let’s go.

Hardware Configuration

To use the proposed approach in this article, the PLC’s hardware configuration must be kept in a certain state: the PLC’s communication configurations should not be set by the TIA Portal project and should be set by itself.

This is achieved by the below settings. Note that I am demonstrating the IP address, DNS server and NTP server configurations.

IP address.

ConfigDemo1

DNS server.

ConfigDemo2

NTP Server.

ConfigDemo3

In addition, one of the ways to use the PLC’s recipe systems to backup and restore the communication configuration is to use the integrated web server. Hence the below configuration must be made.

Enable web server.

ConfigDemo4

Allow web server access from the network interface.

ConfigDemo5

Program the Function Block

In my demonstration, the whole feature is programmed into 1 function block.

The SIEMENS Library used in this function block are:

  1. RecipeImport: import recipe from the PLC’s load memory.
  2. RecipeExport: export recipe to the PLC’s load memory.
  3. CommConfig: configure the PLC’s communication interface.

The usages of these SIEMENS Libraries are detailed in the TIA Portal help files so I’m not going to go into details.

Instead, I’ll share my function block for demonstration below.

FUNCTION_BLOCK "ConfigNetwork"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      i_CMD : Int;
      i_HWID_Interface : HW_INTERFACE;
      i_HWID_SubModule : HW_INTERFACE;
   END_VAR

   VAR 
      s_CMD : Int;
      s_Busy : Bool;
      s_RecipeImport {InstructionName := 'RecipeImport'; LibVersion := '1.2'} : RecipeImport;
      s_RecipeExport {InstructionName := 'RecipeExport'; LibVersion := '1.2'} : RecipeExport;
      s_Recipe : Array[0..1] of "UDT_NetworkConfig";
      s_NetworkConfig {InstructionName := 'CommConfig'; LibVersion := '1.0'} : CommConfig;
      s_NetworkConfigData : Struct
         Index : Int;
         Mode : UInt;
         DNS {InstructionName := 'Conf_DNS'; LibVersion := '1.0'; S7_SetPoint := 'False'} : Conf_DNS := (1, [()]);
         IPAddress {InstructionName := 'Conf_IPSuitev4'; LibVersion := '1.0'; S7_SetPoint := 'False'} : Conf_IPSuitev4 := (2, (), (), ());
         NTP {InstructionName := 'Conf_NTP'; LibVersion := '1.0'; S7_SetPoint := 'False'} : Conf_NTP := (1, [()]);
      END_STRUCT;
      s_Stp_Backup : Int;
      s_Stp_Restore : Int;
   END_VAR

   VAR CONSTANT 
      CMD_Idle : Int := 998;
      CMD_Backup : Int := 100;
      CMD_Restore : Int := 200;
      Stp_Backup_DNS : Int := 21;
      Stp_Backup_IP : Int := 22;
      Stp_Backup : Int := 24;
      Stp_Backup_Done : Int := 29;
      Stp_Restore_DNS : Int := 31;
      Stp_Restore_IP : Int := 32;
      Stp_Restore_NTP : Int := 33;
      Stp_Restore : Int := 34;
      Stp_Restore_Done : Int := 39;
   END_VAR


BEGIN
	REGION CMD_Response
	    
	    IF #i_CMD <> #s_CMD AND NOT #s_Busy THEN
	        
	        #s_CMD := #i_CMD;
	        #s_Busy := TRUE;
	        
	        CASE #s_CMD OF
	                
	            #CMD_Backup:
	                
	                #s_Stp_Backup := #Stp_Backup_DNS;
	                
	            #CMD_Restore:
	
	                #s_Stp_Restore := #Stp_Restore;
	                
	            #CMD_Idle:
	                
	                #s_Stp_Backup := #Stp_Backup_Done;
	                #s_Stp_Restore := #Stp_Restore_Done;
	                #s_Busy := FALSE;
	                
	        END_CASE;
	        
	    END_IF;
	    
	END_REGION
	
	
	REGION Backup Sequence
	    
	    IF #s_CMD = #CMD_Backup THEN
	        
	        CASE #s_Stp_Backup OF
	                
	            #Stp_Backup_DNS:
	                
	                #s_NetworkConfig(REQ   := TRUE,
	                                 HW_ID := #i_HWID_SubModule,
	                                 MODE  := 0,
	                                 DATA  := #s_NetworkConfigData.DNS);
	                
	                IF #s_NetworkConfig.DONE THEN
	                    
	                    #s_Recipe[0].DNS := #s_NetworkConfigData.DNS.DNS_Server[1];
	                    #s_NetworkConfig(REQ := FALSE);
	                    #s_RecipeExport(REQ := FALSE);
	                    #s_Stp_Backup := #Stp_Backup_IP;
	                    
	                END_IF;
	                
	            #Stp_Backup_IP:
	                
	                #s_NetworkConfig(REQ    := TRUE,
	                                 HW_ID  := #i_HWID_Interface,
	                                 MODE   := 0,
	                                 DATA   := #s_NetworkConfigData.IPAddress);
	                
	                IF #s_NetworkConfig.DONE THEN
	                    
	                    #s_Recipe[0].IP := #s_NetworkConfigData.IPAddress.IPAddress;
	                    #s_Recipe[0].SubnetMask := #s_NetworkConfigData.IPAddress.SubnetMaskPrefix;
	                    #s_Recipe[0].Gateway := #s_NetworkConfigData.IPAddress.Gateway;
	                    #s_NetworkConfig(REQ := FALSE);
	                    #s_RecipeExport(REQ := FALSE);
	                    #s_Stp_Backup := #Stp_Backup;
	                    
	                END_IF;
	                
	            #Stp_Backup:
	                
	                #s_RecipeExport(REQ       := TRUE,
	                                RECIPE_DB := #s_Recipe);
	                
	                IF #s_RecipeExport.DONE THEN
	                    
	                    #s_NetworkConfig(REQ := FALSE);
	                    #s_RecipeExport(REQ := FALSE);
	                    #s_Stp_Backup := #Stp_Backup_Done;
	                    
	                END_IF;
	                
	            #Stp_Backup_Done:
	                
	                #s_Busy := FALSE;
	                
	        END_CASE;
	        
	    END_IF;
	    
	END_REGION
	
	
	REGION Restore Sequence
	    
	    IF #s_CMD = #CMD_Restore THEN
	        
	        CASE #s_Stp_Restore OF
	                
	            #Stp_Restore:
	                
	                #s_RecipeImport(REQ       := TRUE,
	                                RECIPE_DB := #s_Recipe);
	                
	                IF #s_RecipeImport.DONE THEN
	                    
	                    IF #s_Recipe[1].ApplyConfig THEN
	                        
	                        #s_NetworkConfigData.DNS.DNS_Server[1] := #s_Recipe[1].DNS;
	                        #s_NetworkConfigData.DNS.Count := 1;
	                        #s_NetworkConfigData.IPAddress.write_mode := 2;
	                        #s_NetworkConfigData.IPAddress.IPAddress := #s_Recipe[1].IP;
	                        #s_NetworkConfigData.IPAddress.SubnetMaskPrefix := #s_Recipe[1].SubnetMask;
	                        #s_NetworkConfigData.IPAddress.Gateway := #s_Recipe[1].Gateway;
	                        #s_NetworkConfigData.NTP.Count := 1;
	                        #s_NetworkConfigData.NTP.NTP_Server[1] := #s_Recipe[1].NTPServer;
	                        #s_NetworkConfig(REQ := FALSE);
	                        #s_RecipeImport(REQ := FALSE);
	                        #s_Stp_Restore := #Stp_Restore_DNS;
	                        
	                    ELSE
	                        
	                        #s_NetworkConfig(REQ := FALSE);
	                        #s_RecipeImport(REQ := FALSE);
	                        #s_Stp_Restore := #Stp_Restore_Done;
	                        
	                    END_IF;
	                    
	                END_IF;
	                
	            #Stp_Restore_DNS:
	                
	                #s_NetworkConfig(REQ   := TRUE,
	                                 HW_ID := #i_HWID_SubModule,
	                                 MODE  := 1,
	                                 DATA  := #s_NetworkConfigData.DNS);
	                
	                IF #s_NetworkConfig.DONE THEN
	                    
	                    #s_NetworkConfig(REQ := FALSE);
	                    #s_RecipeImport(REQ := FALSE);
	                    #s_Stp_Restore := #Stp_Restore_IP;
	                    
	                END_IF;
	                
	            #Stp_Restore_IP:
	                
	                #s_NetworkConfig(REQ   := TRUE,
	                                 HW_ID := #i_HWID_Interface,
	                                 MODE  := 1,
	                                 DATA  := #s_NetworkConfigData.IPAddress);
	                
	                IF #s_NetworkConfig.DONE THEN
	                    
	                    #s_NetworkConfig(REQ := FALSE);
	                    #s_RecipeImport(REQ := FALSE);
	                    #s_Stp_Restore := #Stp_Restore_NTP;
	                    
	                END_IF;
	                
	            #Stp_Restore_NTP:
	                
	                #s_NetworkConfig(REQ   := TRUE,
	                                 HW_ID := #i_HWID_SubModule,
	                                 MODE  := 1,
	                                 DATA  := #s_NetworkConfigData.NTP);
	                
	                IF #s_NetworkConfig.DONE THEN
	                    
	                    #s_NetworkConfig(REQ := FALSE);
	                    #s_RecipeImport(REQ := FALSE);
	                    #s_Stp_Restore := #Stp_Restore_Done;
	                    
	                END_IF;
	                
	            #Stp_Restore_Done:
	                
	                #s_Busy := #s_Recipe[1].ApplyConfig := FALSE;
	                
	        END_CASE;
	        
	    END_IF;
	    
	END_REGION
END_FUNCTION_BLOCK

Demonstration

Below is a demonstration of how the function block backs up and configures the PLC’s communication.

Conclusion

Using the SIEMENS PLC’s recipe system and user program to configure the PLC’s communication interface can allow us to keep a consistent hardware configuration and software. WIth different recipes loaded, the PLC configures itself automatically. In my option, this is a much more elegant way to develop and deploy an application.