请参考以下代码,这是使用SCL编写的实现多个仪表进行485通讯轮询的程序:
[code]FUNCTION_BLOCK FB_485_Polling
VAR_INPUT
aDevAddr : ARRAY [1..50] OF WORD; //设备地址数组
wCommand : WORD; //读取数据指令
wDataAddr : WORD; //数据寄存器地址
wDataLen : WORD; //数据长度
END_VAR
VAR_OUTPUT
aReadValue : ARRAY [1..50, 1..50] OF WORD; //读取的数据值
wErrorCode : WORD; //错误码
END_VAR
VAR
nNumDevices : WORD; //设备数量
nIndex : WORD; //索引
bIsBusy : BOOL := FALSE; //是否正在通信中
nCurrentDevice : WORD := 1; //当前通信的设备编号
nCommResult : WORD; //通信结果
END_VAR
//初始化程序
IF FIRST_SCAN THEN
nNumDevices := UDINT_TO_WORD(DINT#LWORD(aDevAddr) MOD 100000000);
nIndex := 1;
END_IF;
//判断是否正在通信中
IF bIsBusy THEN
CASE nCommResult OF
//通信成功,将读取的数据保存到数组中
0:
FOR i := 1 TO wDataLen DO
aReadValue[nCurrentDevice, i] := wRxData[wDataAddr + i - 1];
END_FOR;
//判断是否还有其他设备需要通信
nIndex := nIndex + 1;
IF nIndex <= nNumDevices THEN
nCurrentDevice := nIndex;
bIsBusy := FALSE;
ELSE
wErrorCode := 0; //没有错误
RETURN; //结束程序
END_IF;
//通信失败,记录错误码并结束程序
1..255:
wErrorCode := nCommResult;
RETURN;
END_CASE;
ELSE
//发送读取数据指令给当前设备
nCommResult := SendCmd(aDevAddr[nCurrentDevice], wCommand, wDataAddr, wDataLen, wRxData);
bIsBusy := TRUE;
END_IF;[/code]
该程序的输入参数包括:
- aDevAddr:设备地址数组,存储了需要轮询的设备的地址;
- wCommand:读取数据指令,表示需要从仪表中读取什么类型的数据;
- wDataAddr:数据寄存器地址,表示需要从哪个寄存器开始读取数据;
- wDataLen:数据长度,表示需要读取多少个数据。
输出参数包括:
- aReadValue:读取的数据值,是一个二维数组,第一维表示设备编号,第二维表示读取到的数据;
- wErrorCode:错误码,如果通讯出错则会记录错误码。
该程序会依次遍历设备地址数组中的地址,通过485总线向每个设备发送指定的读取数据指令,等待设备返回数据后保存到数组中。如果通讯失败,则记录错误码并结束程序。 |