Simatic Step 7. STL. Доступ к текущему времени.

PLC
  В предыдущей статье Simatic Step 7. STL. Вычисление числа дней в месяце (DayOfMonth) пришлось немного углубиться в преставление системного времени Simatic Step 7. Получилось не очень (ни туда, ни сюда), решил оформить эту тему отдельной статьей. Разговор пойдет только о системном формате времени DATE_AND_TIME. Simatic поддерживает и другие форматы (TIME_OF_DAY (DWord, время суток), S5TIME (Word, время в формате Simatic, для таймеров и счетчиков), TIME (DWord, время в формате IEC), DATE (DWord, дата в формате IEC)), межформатные преобразования предусмотрены стандартной библиотекой.

  Чтобы обеспечить доступ в Step 7 STL к текущему времени есть два варианта:
  1. Воспользоваться встроенной стандартной функцией считывания системного времени «READ_CLK» (SFC1). Она возвращает время в структуре DATE_AND_TIME (DT), которая должна быть определена и создана;
  2. В каждом организационном блоке программы Step 7 уже определено стандартом 20 байт для системных данных. Первые 12 содержат общую информацию о ОB (класс приоритета, номер OB) и информацию зависящую от типа ОB. Последние 8 байт в каждом ОB занимает структура типа DATE_AND_TIME (DT);

Структура DATE_AND_TIME (DT):

  DATE_TIME_BCD_YEAR : BYTE; 	//Текущий год
  DATE_TIME_BCD_MONTH : BYTE; 	//Текущий месяц
  DATE_TIME_BCD_DAY : BYTE; 	//Текущий день
  DATE_TIME_BCD_HOUR : BYTE; 	//Текущий час
  DATE_TIME_BCD_MIN : BYTE; 	//Текущая минута
  DATE_TIME_BCD_SEC : BYTE; 	//Текущая секунда
  DATE_TIME_BCD_MSEC : BYTE; 	//Текущая милисекунда
  DATE_TIME_BCD_WEEK : BYTE;	//Текущая неделя (7..4, 3..0 милисекунды)

Данные представлены в двоично-десятичном BCD формате, в каждом байте две цифры.


Минимальная дата в структуре DATE_AND_TIME равна 01.01.1990 года, максимальная 31.12.2089 года.

  Первая функция пригодна для ситуации… Честно говоря не знаю для чего эта функция, ни разу не потребовалась. Единственно, что приходит в голову — экономия 8 байт глобальной памяти. Запросил и разместил время в локальной памяти, обработал и вышел.
  Структура DATE_AND_TIME в конце заголовка каждого стандартного ОВ так и называется, с добавкой номера блока. Для блока ОВ1 это будет OB1_DATE_TIME, это неразрывный 8-байтный блок.
  Cтруктура DATE_AND_TIME содержит данные в BCD формате, но арифметические функции преобразования времени требуют двоичных данных. Это относится и к библиотечным функциям со временем, сначала они конвертируют DATE_AND_TIME в двоичный формат. Я предпочитаю избегать лишнего преобразования данных, и вместе с сохранением текущего времени в глобальной области (области меркеров) сразу их конвертирую.
  Для доступа к необходимым значениям используется косвенная адресация (применимо только внутри ОВ1):

NETWORK
TITLE = Дата и время
  LAR1 P##OB1_DATE_TIME;// указатель на структуру DATE_AND_TIME
// Текущий год
  L  B [AR1,P#0.0]; 	// #OB1_DATE_TIME_BCD_YEAR
  BTI; 			// BIN  <-  BCD
  T  MB114; 		// в область меркеров 
// Текущий месяц
  L  B [AR1,P#1.0]; 	// #OB1_DATE_TIME_BCD_MONTH
  BTI; 			// BIN  <-  BCD
  T  MB115; 		// в область меркеров
// Текущий день
  L  B [AR1,P#2.0]; 	// #OB1_DATE_TIME_BCD_DAY
  BTI; 			// BIN  <-  BCD
  T  MB116; 		// в область меркеров 
// Текущий час      
  L  B [AR1,P#3.0]; 	// #OB1_DATE_TIME_BCD_HOUR
  BTI; 			// BIN  <-  BCD
  T  MB117; 		// M117.0 меняется каждый час 
// Текущая минута
  L  B [AR1,P#4.0]; 	// #OB1_DATE_TIME_BCD_MIN
  BTI; 			// BIN  <-  BCD
  T  MB118; 		// в область меркеров 
// Текущая секунда      
  L  B [AR1,P#5.0]; 	// #OB1_DATE_TIME_BCD_SEC
  BTI; 			// BIN  <-  BCD
  T  MB119; 		// M119.0 секундный флаг   

Вместо структуры OB1_DATE_TIME при необходимости я переопределяю более развернутый вариант:

  OB1_DATE_TIME_BCD_YEAR : BYTE; 	//Текущий год
  OB1_DATE_TIME_BCD_MONTH : BYTE; 	//Текущий месяц
  OB1_DATE_TIME_BCD_DAY : BYTE; 	//Текущий день
  OB1_DATE_TIME_BCD_HOUR : BYTE; 	//Текущий час
  OB1_DATE_TIME_BCD_MIN : BYTE; 	//Текущая минута
  OB1_DATE_TIME_BCD_SEC : BYTE; 	//Текущая секунда
  OB1_DATE_TIME_BCD_MSEC : BYTE; 	//Текущая милисекунда
  OB1_DATE_TIME_BCD_WEEK : BYTE;	//Текущая неделя (7..4, 3..0 милисекунды)

Работать с ним еще проще (прямая адресация):

NETWORK
TITLE = Дата и время
// Текущий год
  L  #OB1_DATE_TIME_BCD_YEAR; 	// локальная переменная
  BTI; 				// BIN  <-  BCD
  T  MB114; 			// в область меркеров 
// Текущий месяц
  L  #OB1_DATE_TIME_BCD_MONTH; 	// локальная переменная
  BTI; 				// BIN  <-  BCD
  T  MB115; 			// в область меркеров
// Текущий день
  L  #OB1_DATE_TIME_BCD_DAY; 	// локальная переменная
  BTI; 				// BIN  <-  BCD
  T  MB116; 			// в область меркеров 
// Текущий час      
  L  #OB1_DATE_TIME_BCD_HOUR; 	// локальная переменная
  BTI; 				// BIN  <-  BCD
  T  MB117; 			// M117.0 меняется каждый час 
// Текущая минута
  L  #OB1_DATE_TIME_BCD_MIN; 	// локальная переменная
  BTI; 				// BIN  <-  BCD
  T  MB118; 			// в область меркеров 
// Текущая секунда      
  L  #OB1_DATE_TIME_BCD_SEC; 	// локальная переменная
  BTI; 				// BIN  <-  BCD
  T  MB119; 			// M119.0 секундный флаг 

Теперь везде, где требуются данные о текущем времени, они берутся из области меркеров. Кроме того даром получились нужные программе часовой M117.0 и секундный M119.0 меркеры.
  • 0
  • 19 ноября 2016, 17:06
  • anakost

Комментарии (0)

RSS свернуть / развернуть
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.