ST | C# | Знак. | Длина |
BYTE, USINT | byte | + | 8 бит |
INT | short | ± | 16 бит |
WORD, UINT | ushort | + | 16 бит |
DINT | int | ± | 32 бита |
DWORD, UDINT | uint | + | 32 бита |
REAL | float | ± | 32 бита |
LREAL | double | ± | 64 бита |
Ничего сложного, для базовых типов нужно учитывать разницу в длине слов. Специфические типы данных DT и TIME требуют особого подхода. STRING и ARRAY - особого подхода с элементами эквилибристики. Работа со структурами STRUCT - тема отдельного разговора.
Дата и время
TIME в языке ST - это промежуток времени (длина), DT - дата и время события (момент). Соответственно в C# для TIME подходит TimeSpan, для DT - DateTime.
TIME хранится в памяти ПЛК как 32-х разрядное, целое, беззнаковое число, содержащее количество миллисекунд:
int htime = client.CreateVariableHandle("MAIN.t"); UInt32 ttime = 0; ttime = (UInt32)client.ReadAny(htime, ttime.GetType()); TimeSpan span = TimeSpan.FromMilliseconds(ttime);
Я специально использовал тип данных UInt32, чтобы был виден размер данных. По желанию его можно заменить на uint.
С DT немного сложнее, но не сильно - это опять-таки 32-х разрядное, целое, беззнаковое, содержащее количество секунд, прошедшее с 1 января 1970 года:
int hdate = client.CreateVariableHandle("MAIN.td"); int tdate = 0; tdate = (int)client.ReadAny(hdate, tdate.GetType()); DateTime dt = new DateTime(1970, 1, 1).AddSeconds(tdate); Console.WriteLine(string.Concat("DT td = ", dt.ToLongDateString(), " / ", dt.ToLongTimeString()));
Я немного расширил пример выводом даты и времени в консоль.
Массивы данных
Сразу отмечу, что строки - это одномерные массивы символов. Нет никакой разницы между работой со строками и массивами.
В старых версиях TwinCAT необходимо было учитывать, что в конце строки стоит символ '\0' и соответственно увеличивать на единицу размер массива под строку. Начиная со второй версии, про нулевой символ и увеличение размера можно забыть: просто передавайте длину строки в символах.Для чтения и записи массивов используется дополнительный параметр, передающий количество элементов массива. Для одномерного массива - число элементов, для двумерного - число строк, затем число столбцов.
VAR str : STRING := 'abcdef'; strT : T_MaxString := '01234abcdef'; arr : ARRAY [1..5] OF WORD; arr2D : ARRAY [1..3, 1..5] OF WORD; END_VAR
string str = ""; string strT = ""; ushort[] arr = new ushort[5]; ushort[,] arr2d = new ushort[3, 5]; str = (string) (client.ReadAny(h_str, str.GetType(), new int[] { 80 })); strT = (string) (client.ReadAny(h_strT, strT.GetType(), new int[] { 255 })); arr = (ushort[]) (client.ReadAny(h_arr, arr.GetType(), new int[] { 5 })); arr2d = (ushort[,])(client.ReadAny(h_arr2D, arr2d.GetType(), new int[] { 3, 5 }));
При записи строк - длину указывать необходимо, т. к. можно передавать только часть строки, а вот при записи массивов наоборот - длину передавать не только не нужно, но и нельзя:
client.WriteAny(h_str, str, new int[] { str.Length }); client.WriteAny(h_arr, arr); client.WriteAny(h_arr2D, arr2d);
Все переменные сразу
Существует возможность прочитать список всех переменных ПЛК-программы: получить исчерпывающую информацию об окружении переменной, ее типе, группе, смещении в памяти, родительской структуре и пр. В терминологии TwinCAT - это называется "Symbol Information". Даже комментарий, оставленный в строке с объявленной переменной, будет доступен через информацию окружения.
// Загружаем информацию о всех доступных переменных TcAdsSymbolInfoLoader symbolLoader = client.CreateSymbolInfoLoader(); TcAdsSymbolInfoCollection infoCollection = symbolLoader.GetSymbols(true); foreach (TcAdsSymbolInfo symInfo in infoCollection) { string name = symInfo.Name; string shortName = symInfo.ShortName; string type = symInfo.Type; int size = symInfo.Size; string comment = symInfo.Comment; long iGroup = symInfo.IndexGroup; long iOffset = symInfo.IndexOffset; TcAdsSymbolInfo parentInfo = symInfo.Parent; Console.WriteLine(string.Concat( name, Environment.NewLine, shortName, Environment.NewLine, type, Environment.NewLine, size, Environment.NewLine, comment, Environment.NewLine, iGroup, ":", iOffset, Environment.NewLine )); }
Name и ShortName ничем, к сожалению, не отличаются, хотя должны. Поля Parent и xxxSubSymbol (в примере выше его нет) организуют переменные в иерархию.
Подробнее про назначение полей можно прочитать в справочной системе "TcAdsSymbolInfo Members".
No comments
Post a Comment
Note: Only a member of this blog may post a comment.