使用SCL语言,在博图TIA中编写ModbusRTU_CRC校验程序,使用两个FC块,实现两种不同的应用,CRC1将计算结果直接输出,CRC2将计算的结果插入到输入数组的最后端.
博图TIA中ModbusRTU_CRC校验程序的实现
使用SCL语言,在博图TIA中编写ModbusRTU_CRC校验程序,使用两个FC块,实现两种不同的应用CRC1将计算结果直接输出,CRC2将计算的结果插入到输入数组的最后端.
TIA中自带了modbusRTU通讯库,之所以自己实现CRC校验码的计算只是为了更深入的学习TIA SCL编程序.
实现效果及代码截图



代码片段
CRC1
| FUNCTION : Void |
| { S7_Optimized_Access := 'TRUE' } |
| VERSION : 0.1 |
| VAR_INPUT |
| CrcData : Variant; |
| END_VAR |
| |
| VAR_OUTPUT |
| CrcValue : Word; |
| CrcErr : Word; |
| END_VAR |
| |
| VAR_TEMP |
| Preset : Word; |
| LoopLength : Int; |
| ArrayPoint : Int; |
| i : Int; |
| ArrayLength : UDInt; |
| Array1 : Array[0..999] of Byte; // 最多1000个字节 |
| Err : Int; |
| END_VAR |
| |
| |
| BEGIN |
| #ArrayLength:= CountOfElements(#CrcData); |
| |
| IF #ArrayLength <= 1000 THEN //这里的1000如果需要调大,对应的数组临时变量Array1也要调大 |
| #Err := MOVE_BLK_VARIANT(SRC := #CrcData, COUNT := #ArrayLength, SRC_INDEX := 0, DEST_INDEX := 0, DEST => #Array1); |
| #Preset := 16#FFFF; |
| #LoopLength := 0; |
| #ArrayPoint := 0; |
| |
| //计算CRC校验码 |
| WHILE #LoopLength < #ArrayLength DO //数据长度 |
| #Preset := #Preset XOR #Array1[#ArrayPoint]; |
| #ArrayPoint := #ArrayPoint + 1; |
| FOR #i := 0 TO 7 DO |
| IF (#Preset AND 16#01) = 16#01 THEN |
| #Preset := SHR(IN := #Preset, N := 1); |
| #Preset := #Preset XOR 16#A001; |
| ELSE |
| #Preset := SHR(IN := #Preset, N := 1); |
| END_IF; |
| END_FOR; |
| #LoopLength := #LoopLength + 1; |
| END_WHILE; |
| |
| //#CrcValue := #Preset; |
| #CrcValue := SHR_WORD(IN := #Preset, N := 8) + SHL_WORD(IN := #Preset, N := 8); |
| #CrcErr := 16#0000; |
| ELSE |
| #CrcErr := 16#8000; |
| END_IF; |
| |
| END_FUNCTION |
SEND1
| DATA_BLOCK "SEND1" |
| { S7_Optimized_Access := 'FALSE' } |
| VERSION : 0.1 |
| NON_RETAIN |
| STRUCT |
| CrcData : Array[0..5] of Byte; |
| CrcValue : Word; |
| CrcError : Word; |
| END_STRUCT; |
| |
| |
| BEGIN |
| CrcData[0] := 16#01; |
| CrcData[1] := 16#03; |
| CrcData[2] := 16#00; |
| CrcData[3] := 16#00; |
| CrcData[4] := 16#00; |
| CrcData[5] := 16#01; |
| |
| END_DATA_BLOCK |
CRC2
| FUNCTION : Void |
| { S7_Optimized_Access := 'TRUE' } |
| VERSION : 0.1 |
| VAR_INPUT |
| Command : Variant; |
| dataLen : Int; |
| END_VAR |
| |
| VAR_TEMP |
| buffer : Array[0..#MaxLen] of Byte; |
| i : Int; |
| j : Int; |
| CrcReg : Word; |
| Len : Int; |
| END_VAR |
| |
| VAR CONSTANT |
| MaxLen : Int := 255; |
| END_VAR |
| |
| |
| BEGIN |
| IF #dataLen = 0 OR #dataLen > CountOfElements(IN := #Command) - 2 THEN |
| RETURN; |
| ELSE |
| #Len := #dataLen; |
| END_IF; |
| |
| #CrcReg := 16#FFFF; |
| |
| //将数据转到缓冲区 |
| VariantGet(SRC:=#Command, |
| DST=>#buffer); |
| |
| //计算CRC校验码 |
| FOR #i := 0 TO (#Len - 1) DO |
| #CrcReg := #CrcReg XOR #buffer[#i]; |
| FOR #j := 0 TO 7 DO |
| IF (#CrcReg AND 16#1) = 1 THEN |
| #CrcReg := SHR_WORD(IN := #CrcReg, N := 1); |
| #CrcReg := #CrcReg XOR 16#A001; |
| ELSE |
| #CrcReg := SHR_WORD(IN := #CrcReg, N := 1); |
| END_IF; |
| END_FOR; |
| END_FOR; |
| |
| #buffer[#Len + 1] := SHR_WORD(IN := #CrcReg, N := 8); |
| #buffer[#Len] := #CrcReg AND 16#FF; |
| |
| //将缓冲区数据再写入到指针所指向的区域 |
| VariantPut(SRC := #buffer, |
| DST := #Command); |
| |
| |
| END_FUNCTION |
SEND2
| DATA_BLOCK "SEND2" |
| { S7_Optimized_Access := 'FALSE' } |
| VERSION : 0.1 |
| NON_RETAIN |
| STRUCT |
| CrcData : Array[0..7] of Byte; |
| END_STRUCT; |
| |
| |
| BEGIN |
| CrcData[0] := 16#01; |
| CrcData[1] := 16#03; |
| CrcData[2] := 16#00; |
| CrcData[3] := 16#00; |
| CrcData[4] := 16#00; |
| CrcData[5] := 16#01; |
| |
| END_DATA_BLOCK |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库