BeckHoff_FB --> SET SNR 功能块
SET SNR 是工业自动化中用于设置序列号(Serial Number)的功能块,常见于 PLC 或工业通信协议中。它通过格式化字符串模板(如SET SNR %s;%d;%d;%d;%s$R$N
)构建指令,向外部系统(如 MES、MMC)发送序列号配置请求。功能块可接收序列号、参数值等输入,组合成标准消息格式,用于绑定产品标识、设备参数或生产数据,支持生产追溯、物料管理等场景。通常与通信模块配合,在接收到确认响应(ACK)或处理超时 / 错误时,更新状态标志,确保数据交互的可靠性。
一、功能块实例化
二、功能块变量声明
(*IN variables*)
(*---------------------------------------------*)
VAR_INPUTptIN_STATION_ITAC :POINTER TO ST_ITAC_V2_0;sSerialNumber :STRING;uiSerialNumberMode :UINT;uiState :UINT :=1;uiLayer :UINT :=2;sStation :STRING;starIOParameters:ARRAY[1..siMAX_PARAM_LINES] OF ST_SET_SNR_Param;(* Data for communication *)bIn_SendCMD :BOOL; (* Start send command. Wait for response *)
END_VAR(*---------------------------------------------*)
(*OUT variables*)
(*---------------------------------------------*)
VAR_OUTPUTbOut_ACK :BOOL;bOut_NAK :BOOL;
END_VAR(*---------------------------------------------*)
(*Local variables*)
(*---------------------------------------------*)
VARiStep,iStepOld :INT;fbiTonTimeinStep : TON;tTimeinStep : TIME;sArg1 :STRING[MAX_STRING_LENGTH];sArg2 :STRING[MAX_STRING_LENGTH];FormatString :FB_FormatString;END_VAR(*---------------------------------------------*)
(*IN/OUT variables*)
(*---------------------------------------------*)
VAR_IN_OUTEND_VARVAR CONSTANTtTimeout :TIME:=t#30s ;
END_VAR
三、功能块 代码
(* Timer *)
IF iStep <> iStepOld THENiStepold := istep;fbiTonTimeinStep(IN:= FALSE, PT:= t#1h, Q=> , ET=> tTimeinStep);
ELSEfbiTonTimeinStep(IN:= TRUE, PT:= t#1h, Q=> , ET=> tTimeinStep);
END_IFCASE iStep OF0:(*clear function's return value*)bOut_ACK := FALSE;bOut_NAK := FALSE;iStep := iStep+1;1:(* wait for command *)IF bIn_SendCMD THENptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bError := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bRecACK := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bRecNAK := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sErrText := '';ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sSerialNrRecv := '';ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.uiSerialNrModeRecv := 0;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.uiStatusRecv := 0;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.uiLayerRecv := 0;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sStationRecv := '';ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sSerialNr := sSerialNumber;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.uiSerialNrMode := uiSerialNumberMode;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.uiStatus := uiState;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.uiLayer := uiLayer;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sStation := sStation;MEMCPY (destAddr := ADR (ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.starParameterValues) ,srcAddr := ADR(starIOParameters),n := SIZEOF(starIOParameters));ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bSendRequest := TRUE;iStep := iStep+1;END_IF;2:(* wait for answer *)IF ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bRecACK THENIF sSerialNumber <> ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sSerialNr THENFormatString( sFormat := '02| FB_SEQ_iTAC_SET_SNR Recieved SerialNumber [%s] is not matching with sent SerialNumber [%s]',arg1 := F_STRING(ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sSerialNrRecv),arg2 := F_STRING(ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sSerialNr),sOut => ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sErrText);bOut_NAK := TRUE;ELSIF ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.uiStatusRecv <> ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.uiStatus THENFormatString( sFormat := '02| FB_SEQ_iTAC_SET_SNR Recieved Status [%s] is not OK',arg1 := F_UINT(ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.uiStatus),sOut => ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sErrText);bOut_NAK := TRUE;ELSEbOut_ACK := TRUE;END_IFiStep:= iStep +1;END_IFIF ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bRecNAK THENbOut_NAK := TRUE;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bError := TRUE;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sErrText := '02| FB_SEQ_iTAC_SET_SNR -> NAK received ';iStep:= iStep +1;END_IFIF tTimeinStep>tTimeout THENbOut_NAK := TRUE;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bRecACK := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bRecNAK := TRUE;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bError := TRUE;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sErrText := '02| FB_SEQ_iTAC_SET_SNR -> timout ';iStep:=iStep +1;END_IF3: (*END*)IF NOT bIn_SendCMD THENiStep:= 0;END_IFELSEiStep := 3;END_CASE;
四、功能块代码说明
1、计时器与状态管理
IF iStep <> iStepOld THENiStepold := iStep;fbiTonTimeinStep(IN:= FALSE, PT:= t#1h, Q=> , ET=> tTimeinStep); // 状态切换时重置计时器
ELSEfbiTonTimeinStep(IN:= TRUE, PT:= t#1h, Q=> , ET=> tTimeinStep); // 保持计时
END_IF;
- 功能:记录每个状态的持续时间,用于超时检测。
2、状态机流程
1. 初始化状态(iStep=0)
iecst
0: (* 清除输出标志 *)bOut_ACK := FALSE;bOut_NAK := FALSE;iStep := iStep+1;
- 功能:重置通信结果标志,准备新的请求。
2. 发送请求状态(iStep=1)
iecst
1: (* 等待发送命令 *)IF bIn_SendCMD THEN// 重置通信状态ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bError := FALSE;// ... 清除其他标志和接收缓冲区// 设置序列号参数ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sSerialNr := sSerialNumber;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.uiSerialNrMode := uiSerialNumberMode;// ... 设置其他参数// 复制参数数组到通信缓冲区MEMCPY(destAddr := ADR(ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.starParameterValues),srcAddr := ADR(starIOParameters),n := SIZEOF(starIOParameters));ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bSendRequest := TRUE; // 触发发送iStep := iStep+1;END_IF;
- 功能:
- 配置序列号、模式、状态等参数。
- 使用
MEMCPY
将本地参数数组(starIOParameters
)复制到通信缓冲区。 - 触发 SET_SNR 请求,切换到等待响应状态。
3. 接收响应状态(iStep=2)
2: (* 等待响应 *)IF ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bRecACK THEN// 验证返回的序列号和状态是否匹配IF sSerialNumber <> ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.sSerialNrRecv THENbOut_NAK := TRUE; // 序列号不匹配,返回错误ELSIF ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.uiStatusRecv <> uiState THENbOut_NAK := TRUE; // 状态不匹配,返回错误ELSEbOut_ACK := TRUE; // 验证通过,返回成功END_IF;iStep := iStep+1;END_IF;IF ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bRecNAK THENbOut_NAK := TRUE; // 收到否定响应iStep := iStep+1;END_IF;IF tTimeinStep > tTimeout THENbOut_NAK := TRUE; // 超时处理iStep := iStep+1;END_IF;
- 功能:
- 验证 MMC 系统返回的序列号和状态是否与发送值一致。
- 根据响应类型(ACK/NAK)或超时,设置对应的输出标志。
4. 结束状态(iStep=3)
3: (* 结束 *)IF NOT bIn_SendCMD THENiStep := 0; // 发送命令取消时重置状态机END_IF;
- 功能:等待发送命令信号结束,然后返回初始化状态。
3、核心功能总结
- 参数设置:通过
SET_SNR
功能块向 MMC 系统发送序列号、状态和参数值。 - 数据验证:对比发送与接收的序列号和状态,确保数据一致性。
- 错误处理:处理 NAK 响应和超时情况,提供明确的错误信息。
- 状态保持:命令信号持续期间保持当前状态,避免重复操作。
五、附录
声明功能块