ß Программирование
структуры
системы мониторинга
Адрес
документа: |
http://shabronov_s2.dyn-dns.ru/temp/gr_mi38_37_mp6_sh/gr_mi38_37_mp6_sh.doc инд
2-95-л6 |
В данной
лекции
рассматривается
программирование
структуры
системы
мониторинга.
Примеры
измерения
температуры
цифрового
датчика.
Однопоточное
и много
поточное
выполнение
алгоритма.
Особенности
потоков -
скрытые
явные.
Содержание:
Что
называется
алгоритмом? Понятие
алгоритма
является
довольно древним
и относится к
одному из
главных, а также
базовых
понятий в
математике,
программировании
и в
нашей
действительности.
На
картинках
ниже
показаны
циклические
действия по алгоритму:
Алгоритм
–
точные
сформулированные
указания,
порядок
определенных
действий,
которые
должны
обеспечить
достижение
поставленной
цели.
Термин
происходит
от
латинского написания
имени
известного
восточного
математика 787-850
годов
Мухаммеда аль-Хорезми
- Algorithmi. Этот
ученный был
первым, кто
сформулировал
точные
правила для
записи
натуральных
чисел, а
также
правила для
подведения
отсчётов в
столбик.
Довольно
интересным
фактом является
и то, что,
несмотря на
древние корни,
само понятие
было точно
сформулировано
лишь в начале
ХХ века. Ныне
алгоритм является
основной
составляющей
современного
бизнеса,
любого
учебного
процесса или
же
исследования.
Именно
поэтому
каждому современному
человеку
просто
необходимо
точно знать,
что означает
алгоритм.
Ниже на
рисунке
представлена
блок схема
алгоритма
мониторинга. Рядом показано
главное
(основное)
слово
программы,
отображающее
основные
этапы
алгоритма.
Стрелками
указано,
какому блоку
соответствует
слово
программы.
«Золотое»
правило - программируем
«сверху». В
начале пишем
по алгоритму
основное
слово
MAIN. И в нем
описываем
действия
«ПО
КРУПНОМУ».
Наш
изучаемый мониторинг
состоит из
одного цикла BEGIN …<тело
программы > …. UNTIL
В «теле
программы»
находятся
основные
«слова» отвечающие
за
мониторинг.
Имеется один
условный
переход -
проверка
граничных
условий. Второй
условный
переход –
повторение
измерений.
Разберем
блоки и слова
алгоритма.
|
Например,
проверка
запуска. Вход
по паролю и
т.д.
M_GRN_EKRAN - отображение
на экране
M_GRN_WRITE - запись
границы в
файле
А
если на стеке
0 – то
программа
возвращается
к слову BEGIN и
начинает
выполнять
повторно получение
данных из
источника. И все
повторяется
вновь.
Ниже
представлен
алгоритм
мониторинга
с
использованием
конструкции BEGIN … WHILE … REPEAT
Отличие
в том, что
проверка
условий
выхода проверяется
вначале, а
затем
получение данных
и их
обработка.
Это
все тот же пример
простого
цикла.
Все действия
программы
выполняются
последовательно.
Далее
рассмотрим
конкретную
программу
для
цифрового датчика.
Отвлечение
руководителя
анекдот - на
лекции не
озвучивать;
· Как
вам удалось
сохранить
брак? -
Просто в наше
время было
принято
чинить вещи,
а не выбрасывать
их. |
Используем
цифровой
датчика Dallas Semicondutor ds1820
и ds18b20.
Они
отличаются
разной
точностью
измерения.
Внешний
вид датчиков:
Схема
подключения
датчиков
протокола 1-wire:
Внешний
вид адаптера 1-wire USB- ds2490 и
рядом с ним
датчик ds1820
Для
работы с usb- 1-wire
производители
подготовили dll-библиотеку ibusb32.dll (скачать)
И
обязательно
требуется
установить драйверы
для работы с USB- адаптером
адрес1 адрес2
Ниже
представлен
текст программы.
Скопировать
блокнотом,
создать файл
с
расширением f.
Скомпилировать
программой компилятора
forth. В
папке с исполняемым
файлом,
должен
находиться и
файл ibusb32.dll.
А так же эта библиотека
может
находиться и
в области :\Windows\SYSTEM32\ Но
если Вы с
правами
гостя на
компьютере,
записать в
данный
каталог не
получиться.
\ начало
текста \ программа
чтения
датчика
температур Dallas Semiconductor
ds1820 в
одном
потоке WINAPI: TMEndSession IBUSB32.dll WINAPI: TMExtendedStartSession IBUSB32.dll WINAPI: TMGetVersion
ibusb32.dll WINAPI: TMSetup
IBUSB32.dll WINAPI: TMOneWireCom
IBUSB32.dll WINAPI: TMOneWireLevel
IBUSB32.dll WINAPI: TMBlockIO
IBUSB32.dll WINAPI: TMTouchReset
IBUSB32.dll WINAPI: TMNext
IBUSB32.dll WINAPI: SetConsoleCursorPosition KERNEL32.DLL WINAPI: SetConsoleTextAttribute KERNEL32.DLL WINAPI: MessageBeep
USER32.DLL ( пищание
системного
динамика ) WINAPI: Beep
KERNEL32.DLL ( звучит
звуковое
устройство
т-МС
F-ГЦ -- ) WINAPI: GetLocalTime
KERNEL32.DLL ( читаем
локальное
т.е.
установленное
на
компьютере
время ) \
резервируем
переменные
и константы
для работы 0 VALUE handle1 ( глобальная
переменная
описателя
устройства
сопряжения ) 0 VALUE BUF1 ( глобальная
переменная
для
сохранения
адресов
буферов
переменных ) 0 VALUE BUF2 ( глобальная
переменная
для
сохранения
адресов
буферов
данных
датчиков ) 0 VALUE In ( глобальная
переменная
для временого
хранения
индекса ) 0x8 CONSTANT NDAT ( максимальное
количество
датчиков на
одном
адаптере ) 0 VALUE IDAT ( глобальная
переменная
для
обнаруженных
датчиков на
линии
) 0 VALUE Nizm ( глобальная
переменная
для
подсчета
количества
измерений ) : NAME_DAN S"
file_temperatur_dan.xls" ; (
имя файла
данных
температур ) 0 VALUE FR1 ( указатель
для файла
данных ) : NAME_TRW S"
file_temperatur_trw.xls" ; (
имя файла
данных
тревог ) 0 VALUE FR2 ( указатель
для файла
тревог ) DECIMAL 30 CONSTANT T_TRWG ( гр.Ц
температура
выше
которой
выдается
тревога ) \ описываем
требуемые
слова для
работы
главного
слова мониторинга CREATE SYSTEMTIME 0x10 ALLOT ( память
под данные
для
системного
времени ) \ для
наглядного
вызова
часов минут
и тд
области
памяти в
выделенной
области
обозначены
через
отдельные
слова : wYear
0 + ; : wMonth
2 + ; : wDayOfWeek 4 + ; : wDay
6 + ; : wHour
8 + ; : wMinute
0xA + ; : wSecond
0xC + ; : wMilliseconds 0xE + ; : TIME&DATE1 ( -- wsec
sec min hr day mt year )
SYSTEMTIME GetLocalTime DROP
SYSTEMTIME wMilliseconds W@ ( мили секунда )
SYSTEMTIME wSecond
W@ ( секунда )
SYSTEMTIME wMinute
W@ ( минута )
SYSTEMTIME wHour
W@ ( час )
SYSTEMTIME wDay
W@ ( день )
SYSTEMTIME wMonth
W@ ( месяц )
SYSTEMTIME wYear
W@ ( год ) ; : TIME ( cc мм чч
-->
время
системы в стек ) SYSTEMTIME GetLocalTime
DROP SYSTEMTIME wSecond W@ ( секунда ) SYSTEMTIME wMinute W@ ( минута ) SYSTEMTIME wHour W@
( час ) ; : TEXT-ATTR ( fg bg -- установка цвета знака fg фона bg ) 0x10 * + H-STDOUT SetConsoleTextAttribute DROP ; : UST_ATR_LIM_CMD 0xF 8 TEXT-ATTR ( fg bg -- установка цветности вариант
) ; : UST_ATR_LIM1_CMD 0xF 5 TEXT-ATTR ( fg bg -- установка цветности вариант 1 тревоги ) ; : UST_ATR_LIM2_CMD 0xF 0xA TEXT-ATTR ( fg
bg -- установка цветности вариант 2 тревоги )
; : UST_ATR_NORM_CMD 0x7 0 TEXT-ATTR ( fg bg -- установка цветности исходное для терминала )
; : GotoXY ( x y --
установка
координаты
курсора в консоли.
) 0x10000 * + H-STDOUT
SetConsoleCursorPosition DROP ; : ZWUK ( Т-мс F-гц --- ) Beep DROP ; : BEEP_M2 (
цыганочка
с входом
вар2 ) 0x60 0x900 ZWUK 0x60 0x800 ZWUK 0x60 0x700 ZWUK 0x60 0x600 ZWUK 0x60 0x500 ZWUK ; : FIX ( M --> ) 0x100 /MOD GotoXY
( x y -- ) ; : .RF ( форматирование
без выдачи
это литерал
числа ) >R DUP >R ABS S>D <# #S R> SIGN
#> R>
OVER - 0 MAX SPACES ; : .R ( n1 n2 --
форматный
вывод n1 по
размеру n2 ) .RF TYPE ; : PAUSE1 ( N -->
пауза в N
миллисекунд
0> ) Sleep
DROP ; : ?KEY1
( K --> код клавиши ) KEY? IF KEY ELSE 0 THEN ; : ZWUK_TRW1 ( три тревожных звонка ) 3 0 DO 0x80 PAUSE1 0x40 MessageBeep DROP ( ВЫДАЕТСЯ ЗВУК ПИЩАЛКИ ДИНАМИКА ) LOOP ; \ контрольные слова для отладки программы : STOP1 BEGIN ?KEY1 DUP 0x1B = IF BYE THEN
0x20 = UNTIL ; CREATE KKS_B 0 , : KKS ( распечатаь
штатными
средствами
и
предупреждение
о исчерпании
стека ) BASE @ KKS_B ! ( систему
счисления на
сохранение ) CR ." ctk,N--> " DECIMAL
DEPTH DUP 1 < IF DUP 0= IF .
S"
Стек
пустой!" ( при
0 )
ELSE DROP S"
ОШИБКА - СТЕК
ИСЧЕРПАН !!!
"
THEN ANSI>OEM
TYPE
ELSE DUP .
HEX ." = " .SN
THEN
S" -->
верх " ANSI>OEM TYPE
KKS_B @ BASE ! (
вернули
систему
счисления )
; : M_PODGOTOVKA_KOL ( поиск
количества
датчиков на
шине ) handle1 0= IF EXIT THEN ( выходим
из подсчета
если нет
описателя
т.е. устройство
не работает ) NDAT 0 DO ( поиск в
цикле до
максимального
значения
датчиков
цикл типа do..loop )
BUF1 handle1 TMNext 1 = ( процедура
dll - поиск
номера
следующего
датчика ) IF ( да -
найден
новый
датчик )
BUF1 0x27 + ( A1 -- ) BUF2
I 0x10 * + 8 CMOVE ( Abuf1 -
сохранили
для
дальнейшей
работы МАС
адрес
датчика ) ELSE I TO IDAT ( записали
данные
кол-ва )
LEAVE ( выход т.к. поиск
окончен ) THEN
LOOP CR S" На
шине 1-wire
устройства
с мас:" ANSI>OEM
TYPE ( выводим
сообщение о
найденных
устройствах
) IDAT 0 DO
CR HEX BUF2 I 0x10 * + ( A -- ) 8 0 DO DUP I + C@ 3 .R LOOP DROP LOOP ( печатаем
номера ) \ BUF2 100 DUMP ( посмотреть
дамп с
содержимым
кодов датчиков
) KKS STOP1
; : M_PODGOTOVKA_DRV ( --
подключение
драйверов
для работы с
цифровым
датчиком и
сообщение
если
драйвер
подключить
не удалось ) \ STARTLOG ( ВКЛЮЧИТЬ
ФАЙЛ ОТЧЕТА
SPF.LOG ) \ ENDLOG ( выключить
файл отчета
) NAME_DAN R/W
CREATE-FILE DROP ( FR -- ) TO FR1 ( cоздали
файл для
записи и
чтения и
сохранили
указатель
на файл ) NAME_TRW R/W CREATE-FILE DROP ( FR -- )
TO FR2 ( cоздали
файл тревог
для записи и
чтения и сохранили
указатель
на файл ) 0x100
ALLOCATE THROW TO BUF1 ( заняли
временную
память и
записали
адрес ее начало
в локальную перменную
BUF1 ) 0x10 NDAT * ALLOCATE THROW
TO BUF2 ( заняли
временную
помять для
номера
датчика и
его данных на
каждый датчик
по 0x100 байт ) BUF1 TMGetVersion 1 = IF ( OK ) BUF1
ASCIIZ> CR TYPE ELSE ( err
) S" нет
файла драйвера
ibusb32.dll" ANSI>OEM CR TYPE
THEN 0 1
1
TMExtendedStartSession TO handle1 ( начали
сессию и
определили
описатель ) \
устанавливаются
параметры
для максимальной
длинны
линии
handle1 TMSetup ( 1-OK 3= ERR
) 1 <> IF 0 TO handle1 THEN (
проверка на
установку 1 ) 6 0 handle1 TMOneWireCom 6 <> IF 0 TO handle1 THEN ( проверка
на
установку 2 ) 2 1 0 handle1 TMOneWireLevel
0<> IF 0 TO handle1 THEN ( проверка
на
установку 3 )
M_PODGOTOVKA_KOL ( подсчет
количества
датчиков на
шине ) handle1 0= IF ( действия
при
отсутствии
устройства
на usb )
FR1 CLOSE-FILE ( fileid
-- ior
закрыли
файл )
DROP NAME_DAN DELETE-FILE ( c-addr u -- ior
удалили
файл )
DROP
FR2 CLOSE-FILE ( fileid
-- ior
закрыли
файл )
DROP NAME_TRW DELETE-FILE ( c-addr u -- ior
удалили
файл )
DROP
UST_ATR_LIM_CMD
ZWUK_TRW1
CR S" ВНИМАНИЕ!
Драйвер программой
не настроен!!!
" ANSI>OEM TYPE
CR S"
Возможные
причины: " ANSI>OEM
TYPE
CR S" Нет
устройства
и драйвера USB в
компьютере.
" ANSI>OEM TYPE
CR S" Включите
диспетчер
устройств и проконтролируйет
исправность.
" ANSI>OEM TYPE
CR S" Контакты
с технической
поддержкой по тс 913-905-8839 shabronov@ngs.ru
" ANSI>OEM TYPE
CR S" Ищите, и обрящете,
толцыте,
и отверзется
Евангелии
от Луки гл. 11,
ст. 9 " ANSI>OEM TYPE
CR S"
Программа
прекращает
работу!
Нажмите
любую
клавишу " ANSI>OEM TYPE
CR 0 0xA DO I . 0x400 PAUSE1 BEEP_M2 ?KEY1 0<> IF BYE THEN -1 +LOOP
UST_ATR_NORM_CMD BYE ( выход
из работы
программы )
THEN ; : M_PODGOTOVKA ( подготовка
) S"
Чтение
данных
температуры
цифрового
датчика ds1820 " ANSI>OEM TYPE CR S" Выход
из программы
клавиша - ESC "
ANSI>OEM TYPE
M_PODGOTOVKA_DRV ( --
подключение
драйверов
для работы с
цифровым
датчиком и
сообщение
если драйвер
подключить
не удалось ) ; : M_DAN_READ ( получение
данных ) IDAT 0 DO ( цикл
читаем
данные по
МАС имс
датчиков ) BUF1
0x100 0xFF FILL ( заполняем
кодом FF для
передачи )
handle1 TMTouchReset
DROP ( сигнал
сброса ) 0x55
BUF1 C! ( запись
команды
назначить имс ) BUF2 I
0x10 * + ( A1
) BUF1 1+ ( A1 A2 -- ) 8 CMOVE (
передали
МАС имс
датчика ) 0x44
BUF1 9 + C! ( команда
конвертации
температуры
после МАСа
)
0xA BUF1 handle1 TMBlockIO DROP ( выдали
команду
последовательность
из 0xA байт )
0x400 PAUSE1 (
ждем 1024 милисекунды
т.е
1секунду ) 0xBE
BUF1 9 + C! ( команда
чтения озу
датчика
вместо
конвертации
пишем ) 0xA 8
+ BUF1 handle1 TMBlockIO
DROP ( выдали
команду
последовательности
18 байт ) BUF1
0xA + ( A1
- находятся 2а
байта
данных
температуры
или FFFF если нет
данных ) BUF2 I
0x10 * + 8 + ( A1
A2 -
адрес для
хранения 2х
байт данных температуры
) 2 CMOVE
( -
передали
данные на
временное хранение
для
отображения
и записи в
файл )
LOOP ; \ --------------------------------------------- CREATE PKZ_M1 ( МАСИВ
ПОД
ЗНАЧЕНИЯ
ПЕРЕРАСЧЕТА
) \ 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 C, 1 C, 1 C, 2 C, 3 C,
3 C, 4 C, 5 C, 6 C, 6 C, 6 C, 7 C, 7 C, 8 C, 9 C, 9 C, : M_DAN_EKRAN_T1 ( At
Ndel=0x10/0x2 - отображение
для ds18b20
ds1820 код
делителя 0x10 и 0x2 ) S" Т, гр.Ц = " ANSI>OEM TYPE SWAP ( Ndel At -- ) DUP
C@ SWAP 1+ C@ 0x100 * + (
T -- ) DUP 0xFFF >
IF ( ОТРИЦАТЕЛЬНАЯ
ВЫДАЧА число
более FFF т/е
отрицательное
)
DUP 0xFFFF SWAP - ( отнимаем
для 16
разрядной
адресации )
[CHAR] - ( знак
минуса ) ELSE DUP [CHAR] + ( знак
плюса ) THEN EMIT ( Ndel T T -->
показываем
целое
значение ) DECIMAL ROT / 2 .R [CHAR] . ( показали
целое и
точку ) EMIT ( T --> ) 0xF AND (
ТОЛЬКО
ЦЕЛАЯ ЧАСТЬ )
PKZ_M1 + C@ 1 .R (
ПОКАЗЫВВЕМ ) ; : M_DAN_EKRAN ( отображение
на экране )
( цикл
показываем
данные и МАС имс
датчиков 1e 8
байт мас
далее 2а
байта
данные ) 0x400 ( точка
после меню ) IDAT 0x100 * + FIX (
устанавливаем
отображение
на экране
фиксировано
по
количеству
датчиков ) S" Nизм = " ANSI>OEM
TYPE DECIMAL Nizm DUP . 1+ TO Nizm ( учет
количества
измерений ) IDAT 0 DO
CR HEX BUF2 I 0x10 * + ( A -- ) 8 0 DO DUP I + C@ 3 .R LOOP
DUP C@ 0x28 = IF DUP
8 + ( A At -- ) 0x10
M_DAN_EKRAN_T1 ( At Ndel=0x10 - отображение для ds18b20 - т.е. где первый код имс = 0x28 ) THEN
DUP C@ 0x10 = IF DUP
8 + ( A At -- ) 0x2
M_DAN_EKRAN_T1 ( At Ndel=2 - отображение для ds1820 - т.е. где первый код имс = 0x10
) THEN
DROP ( убрали
адрес )
LOOP ( печатаем
номера и
температуры ) ; : M_DAN_WRITE_T1 ( At
Ndel=0x10 - запись в
файл для ds18b20 - т.е.
где первый
код имс = 0x28
) SWAP ( Ndel At -- ) DUP C@ SWAP 1+ C@ 0x100 * + ( T -- ) DUP
0xFFF > IF ( ОТРИЦАТЕЛЬНАЯ
ВЫДАЧА число
более FFF т/е
отрицательное
)
DUP 0xFFFF SWAP - ( отнимаем
для 16
разрядной
адресации )
S" -" ( знак
минуса ) ELSE DUP S" +" ( знак
плюса ) THEN ( Ndel T T A1 N1
) FR1 WRITE-FILE ( c-addr
u fileid -- ior ) DROP (
записали
знак ) ( Ndel T T -->
показываем
целое
значение ) DECIMAL ROT / 2 .RF FR1 WRITE-FILE ( c-addr u fileid
-- ior ) DROP ( записали
число целых )
S" ," ( зпт
) FR1 WRITE-FILE ( c-addr
u fileid -- ior ) DROP (
записали
запятую
разделитель
) ( Т ) 0xF AND (
ТОЛЬКО
ЦЕЛАЯ ЧАСТЬ )
PKZ_M1 + C@ 1 .RF (
записываем )
FR1 WRITE-FILE ( c-addr u
fileid -- ior ) DROP
(
записали
дробную
часть ) S" _" 0x9
2 PICK C!
FR1 WRITE-FILE ( c-addr u fileid
-- ior ) DROP (
записали
разделитель
таб
код 0x9 ) ; : M_DAN_WRITE_FILE ( запись
данных в
файле ) IDAT 0 DO ( запись
по строчно
данных темперутур
и
разделением
как на
экране а
подготавливаем
данные в BUF1 ) BUF2 I 0x10 * + ( A -- )
DUP C@ 0x28 = IF DUP
8 + ( A At -- )
0x10 M_DAN_WRITE_T1 ( At Ndel=0x10 - запись
в файл для ds18b20 -
т.е. где
первый код имс = 0x28 ) THEN
DUP C@ 0x10 = IF DUP
8 + ( A At -- )
0x2 M_DAN_WRITE_T1 ( At Ndel=2 -
запись в
файл для ds1820 - т.е.
где первый
код имс =
0x10 ) THEN
DROP ( убрали
адрес )
LOOP S" __" ( A1 N=1 ) 0xD
2 PICK C! ( код ВК )
0xA 2 PICK 1+ C! FR1
WRITE-FILE ( c-addr u fileid
-- ior ) DROP ( 2а байта перевода строки ) ; : M_DAN_TRW ( At Ndel=2 - 0/-1
контроль
предела для
ds1820 только для Ттрв > 0 гр.Ц
) SWAP ( Ndel At -- ) DUP C@ SWAP 1+ C@ 0x100 * + ( Ndel T -->
проверка
целого
значения ) SWAP / ( Tцел_изм -- ) T_TRWG > ( pz -- ) ; : M_USLOVIJ (
0/-1 –
проверка
условий ) 0 ( PZ --
признак в
стеке что
нет
превышения
температур
ставим
заранее и
убираем если
будет
превышение
в проверке
условия ) IDAT 0 DO ( цикл
проверки по
каждому
датчику
если превышен
то выход по
тревоге ) BUF2 I 0x10 * + ( PZ A -- ) DUP C@
0x28 = IF DUP 8 + ( A At --
) 0x10 M_DAN_TRW ( At Ndel=0x10 - 0/-1 контроль предела для ds18b20 ) IF ( PZ A -- ) 2DROP -1 LEAVE THEN THEN DUP C@
0x10 = IF DUP 8 + ( A At --
) 0x2 M_DAN_TRW ( At Ndel=2
- 0/-1 контроль предела для ds1820
) IF ( PZ A -- ) 2DROP -1
LEAVE THEN THEN ( PZ A --
) DROP ( PZ -- убрали адрес ) LOOP ( PZ -- ) ; : M_GRN_EKRAN ( отображение на экране )
CR S" Текущее время/чч:мм:cc/ :" ANSI>OEM TYPE
TIME ( cc мм чч
--> время системы в стек )
DECIMAL 3 .R S" :" TYPE 3 .R S" :" TYPE 3 .R
S"
Превышен
заданных
предел гр.ц = " ANSI>OEM TYPE T_TRWG 3 .R ; : M_GRN_EKRAN_CLS ( очистка
сообщений
на экране ) CR 0x50 SPACES ( передаем
0x40 пробеллов
на экран где
было
сообщение ) ; : M_DAN_WRITE_T2 ( At
Ndel=0x10 - запись в
файл fr2 для ds18b20 -
т.е. где
первый код имс = 0x28 ) SWAP ( Ndel At -- ) DUP C@ SWAP 1+ C@ 0x100 * + ( T -- ) DUP
0xFFF > IF ( ОТРИЦАТЕЛЬНАЯ
ВЫДАЧА число
более FFF т/е
отрицательное
)
DUP 0xFFFF SWAP - ( отнимаем
для 16
разрядной
адресации )
S" -" ( знак
минуса ) ELSE DUP S" +" ( знак
плюса ) THEN ( Ndel T T A1 N1
) FR2 WRITE-FILE ( c-addr
u fileid -- ior ) DROP (
записали
знак ) ( Ndel T T -->
показываем
целое
значение ) DECIMAL ROT / 2 .RF FR2 WRITE-FILE ( c-addr u fileid
-- ior ) DROP (
записали
число целых )
S" ," ( зпт
) FR2 WRITE-FILE ( c-addr
u fileid -- ior ) DROP (
записали
запятую
разделитель
) ( Т ) 0xF AND (
ТОЛЬКО
ЦЕЛАЯ ЧАСТЬ )
PKZ_M1 + C@ 1 .RF (
записываем )
FR2 WRITE-FILE ( c-addr u
fileid -- ior ) DROP
(
записали
дробную
часть ) S" _" 0x9
2 PICK C!
FR2 WRITE-FILE ( c-addr u fileid
-- ior ) DROP (
записали
разделитель
таб
код 0x9 ) ; : M_GRN_WRITE (
запись
границы в
файле ) \
записываем
время
события и
температуры
датчиков
но файл c
описателем FR2 DECIMAL TIME ( cc мм чч -->
время
системы в стек ) 3 .RF
FR2 WRITE-FILE ( c-addr u
fileid -- ior ) DROP
(
записали
час ) S" :"
(
знак ) FR2 WRITE-FILE ( c-addr
u fileid -- ior ) DROP (
записали
знак ) 3 .RF
FR2 WRITE-FILE ( c-addr u
fileid -- ior ) DROP
(
записали
минуты ) S" :"
(
знак ) FR2 WRITE-FILE ( c-addr
u fileid -- ior ) DROP (
записали
знак ) 3 .RF
FR2 WRITE-FILE ( c-addr u
fileid -- ior ) DROP
(
записали
секунды )
S" _" 0x9
2 PICK C! FR2 WRITE-FILE ( c-addr
u fileid -- ior ) DROP (
записали
разделитель
таб
код 0x9 )
IDAT 0 DO ( запись
по строчно
данных темперутур
и
разделением
как на
экране а
подготавливаем
данные в BUF1 ) BUF2 I 0x10 * + ( A -- )
DUP C@ 0x28 = IF DUP
8 + ( A At -- )
0x10 M_DAN_WRITE_T2 ( At Ndel=0x10 - запись
в файл fr2 для ds18b20 -
т.е. где
первый код имс = 0x28 ) THEN
DUP C@ 0x10 = IF DUP
8 + ( A At -- )
0x2 M_DAN_WRITE_T2 ( At Ndel=2 -
запись в
файл fr2 для ds1820 -
т.е. где первый
код имс =
0x10 ) THEN
DROP ( убрали адрес ) LOOP S" __" ( A1 N=1 ) 0xD
2 PICK C! ( код ВК )
0xA 2 PICK 1+ C! FR2
WRITE-FILE ( c-addr u fileid
-- ior ) DROP ( 2а байта перевода строки ) ; : M_OUT_WORK (
0/-1 проверка
условий
выхода ) ?KEY1 0x1B = ( -1 при нажатик
клавиши ESC ) ; : M_ZAVERCHEN ( завершение ) FR1
CLOSE-FILE ( fileid -- ior
закрыли
файл )
DROP FR2
CLOSE-FILE ( fileid -- ior
закрыли
файл )
DROP BUF2 FREE
DROP ( освободили
память ) BUF1 FREE
DROP ( освободили
память ) handle1 TMEndSession DROP ( и
закрыли ее 0=err 1ok ) BYE ; \
главное
слово
мониторинга
: MAIN ( главное
слово ) M_PODGOTOVKA ( подготовка
) BEGIN
M_DAN_READ ( получение
данных )
M_DAN_EKRAN ( отображение
на экране )
M_DAN_WRITE_FILE ( запись
данных в
файле )
M_USLOVIJ (
0/-1 –
проверка
условий ) IF ( да
– индикация.
Граница
нарушена )
M_GRN_EKRAN ( отображение
на экране )
M_GRN_WRITE (
запись
границы в
файле ) ELSE ( нет
- все
нормально )
M_GRN_EKRAN_CLS ( очистка
сообщений
на экране ) THEN M_OUT_WORK ( 0/-1
проверка
условий
выхода ) ( 0/-1
–
значение в
стеке ) UNTIL ( выход
из цикла
если будет -1
или к begin)
M_ZAVERCHEN ( завершение ) ; \
подготавливаем
переменные и
текст
программы
записываем
в исполняемый
файл. 0 TO SPF-INIT? ( в
переменную
записываем
код 0 – означает
что
инициализация
выполняется
) ' NOOP MAINX ! ( в
переменную
записываем
адрес выхода
) ' MAIN TO <MAIN> ( в
переменную
записываем старт
программы
со слова MAIN ) S" test2.exe" SAVE ( сохраняем
файл
исполнения с
именем test2.exe ) BYE ( выходим
из режима
редактирования
и компиляция,
т.е. все
бай-бай ) \ текст программы
окончен. |
Если
адаптер не
установился
или его нет,
то выдается
сообщение, в
противном
случае отображаются
показания
датчиков,
показано
ниже на
рисунке.
Отвлечение
руководителя
анекдот - на
лекции не
озвучивать;
|
Программа,
приведенная
в качестве
мониторинга,
выполнена в
режиме
одного
потока. Это
означает:
Но это
все очень
условное
разделение.
Исходить
надо из
требований к
процессу
измерения и
реализации
получаемых
данных.
Получаемые
данные,
отображают
какое-то явление
или процесс.
Например:
Что бы
выполнить
требования в
измерениях с
разными
временами
обращения
используют
разные
потоки. А
обмен данных
между ними
выполняют
через
выделенные
области
памяти. Ниже
блок схема
измерения, в
котором 5-ть
потоков.
Для
понимания
возможностей
и работы
потоков в
мониторинге
рассмотрим программу
с 2-мя дополнительными
потоками.
Используем программу
мониторинга
и ее основу
алгоритма. А
вместо
датчика
температуры
и показаний температуры,
используем
как параметр
-
время
нажатия
одной
клавиши –
например = клавиша=
1 . код = 0x30
Программа
измеряет
время двойного
нажатия
данной
клавиши в
миллисекундах.
Отображает
значение и
пишет время
события с
данными в файл.
Алгоритм
представлен
ниже на
рисунке.
CREATE BUF1 0x100 ALLOT ( заняли
память в 0x100 байт
для обмена
данными
между
потоками )
CREATE FR1 0 , (
переменная
для
идентификатора
потока
что бы его
можно было
остановить )
: POTOK ( слово
определяющее
поток начало
с
«двоеточия» )
* * * * * * * * * * * *
( в
теле потока
могут быть
любые новые
слова
программы )
* * * * * * * * * * * *
; (
последний
знак -
«тчк-зпт» )
‘ POTOK ( Aисполнения
) ТASK: exPOTOK ! ( cохранили адрес слова
определяющее
поток для
отдельного
старта )
* * * *
* *
: PODGOTOVKA ( в
теле
подготовки
запускаем
новый поток )
BUF1 exPOTOK START ( FR -- ) FR1 ! ( сохранили
идентификатор
созданного
потока )
;
FR1
@ STOP
( останов
потока )
\ начало
текста \ программа
учета
времени
двойного
нажатия
клавиши 1 и ее
отображения. WINAPI: SetConsoleCursorPosition KERNEL32.DLL WINAPI: SetConsoleTextAttribute KERNEL32.DLL WINAPI: MessageBeep
USER32.DLL ( пищание
системного
динамика ) WINAPI: Beep
KERNEL32.DLL ( звучит
звуковое
устройство
т-МС F-ГЦ -- ) WINAPI: GetLocalTime
KERNEL32.DLL ( читаем
локальное
т.е.
установленное
на компьютере
время ) WINAPI: GetTickCount
KERNEL32.DLL ( время c
начала
загрузки мс
в системе ) \
резервируем
переменные
и константы
для работы 0 VALUE BUF1 ( глобальная
переменная
для
сохранения
адресов
буферов
переменных ) 0 VALUE BUF2 ( глобальная
переменная
для
сохранения
адресов
буферов
данных
датчиков ) 0 VALUE In ( глобальная
переменная
для временого
хранения
индекса ) 0x8 CONSTANT NDAT ( максимальное
количество
датчиков на
одном
адаптере ) 0 VALUE IDAT ( глобальная
переменная
для
обнаруженных
датчиков на линии ) 0 VALUE Nizm ( глобальная
переменная
для
подсчета
количества
измерений ) : NAME_DAN S" file_dan.xls" ; (
имя файла
данных
температур ) CREATE FR1 0 , 0 , (
указатель
для файла
данных и
указатель
для потока в 4+
ячейке ) DECIMAL 5000 CONSTANT T_TRWG ( время
превышения
нажатия в
миллисекундах
) 0 VALUE PZ_N (
переменая
нажатия 0 нет 1
одно
нажатие 2 - два
нажатия ) 0 VALUE FR3 ( указатель
для
потока
времени
нажатия ) : TIME_SOST_WORKS ( -- wsec ) \ время
работы с
момента
старта в мс GetTickCount ( мили
секунда ) ; \ описываем
требуемые
слова для
работы главного
слова
мониторинга CREATE SYSTEMTIME 0x10 ALLOT (
память под
данные для
системного
времени ) \ для наглядного
вызова
часов минут
и тд
области
памяти в
выделенной
области
обозначены
через
отдельные
слова : wYear
0 + ; : wMonth
2 + ; : wDayOfWeek 4 + ; : wDay
6 + ; : wHour
8 + ; : wMinute
0xA + ; : wSecond
0xC + ; : wMilliseconds 0xE + ; : TIME&DATE1 ( -- wsec
sec min hr day mt year )
SYSTEMTIME GetLocalTime DROP
SYSTEMTIME wMilliseconds W@ ( мили
секунда )
SYSTEMTIME wSecond
W@ ( секунда
)
SYSTEMTIME wMinute
W@ ( минута
)
SYSTEMTIME wHour
W@ ( час
)
SYSTEMTIME wDay
W@ ( день
)
SYSTEMTIME wMonth
W@ ( месяц
)
SYSTEMTIME wYear
W@ ( год
) ; : TIME ( cc мм чч -->
время
системы в стек ) SYSTEMTIME GetLocalTime
DROP SYSTEMTIME wSecond W@ ( секунда ) SYSTEMTIME wMinute W@ ( минута ) SYSTEMTIME wHour W@
( час ) ; : TEXT-ATTR ( fg bg -- установка
цвета знака fg
фона bg
) 0x10 * + H-STDOUT SetConsoleTextAttribute DROP ; : UST_ATR_LIM_CMD 0xF 8 TEXT-ATTR ( fg bg -- установка
цветности
вариант ) ; : UST_ATR_LIM1_CMD 0xF 5 TEXT-ATTR ( fg bg -- установка
цветности
вариант 1
тревоги )
; : UST_ATR_LIM2_CMD 0xF 0xA TEXT-ATTR ( fg
bg -- установка
цветности
вариант 2
тревоги
) ; : UST_ATR_NORM_CMD 0x7 0 TEXT-ATTR ( fg bg -- установка
цветности
исходное для
терминала
) ; : GotoXY ( x y --
установка
координаты
курсора в консоли.
) 0x10000 * + H-STDOUT
SetConsoleCursorPosition DROP ; : ZWUK ( Т-мс F-гц --- ) Beep DROP ; : BEEP_M2 ( цыганочка
с входом
вар2 ) 0x60 0x900 ZWUK 0x60 0x800 ZWUK 0x60 0x700 ZWUK 0x60 0x600 ZWUK 0x60 0x500 ZWUK ; : FIX ( M --> ) 0x100 /MOD GotoXY
( x y -- ) ; : .RF ( форматирование
без выдачи
это литерал
числа ) >R DUP >R ABS S>D <# #S R> SIGN #> R> OVER - 0 MAX SPACES ; : .R ( n1 n2 --
форматный
вывод n1 по
размеру n2 ) .RF TYPE ; : PAUSE1 ( N --> пауза
в N
миллисекунд
0> ) Sleep DROP ; : ?KEY1
( K --> код клавиши ) KEY?
IF KEY ELSE 0 THEN ; : ZWUK_TRW1 ( три
тревожных
звонка ) 3 0 DO
0x80 PAUSE1 0x40 MessageBeep
DROP (
ВЫДАЕТСЯ
ЗВУК
ПИЩАЛКИ ДИНАМИКА
) LOOP ; \ контрольные
слова для отладки
программы
: STOP1 BEGIN ?KEY1 DUP 0x1B = IF BYE THEN
0x20 = UNTIL ; CREATE KKS_B 0 , : KKS ( распечатаь
штатными
средствами
и
предупреждение
о исчерпании
стека ) BASE @ KKS_B ! (
систему
счисления на
сохранение ) CR ." ctk,N--> " DECIMAL
DEPTH DUP 1 < IF DUP 0= IF .
S" Стек пустой!" (
при 0 )
ELSE DROP S" ОШИБКА -
СТЕК
ИСЧЕРПАН !!! "
THEN ANSI>OEM TYPE
ELSE DUP .
HEX ." = " .SN
THEN S" -->
верх " ANSI>OEM TYPE
KKS_B @ BASE ! (
вернули
систему
счисления ) ; : WORK_IZM_NAGIMA ( A=BUF1 -- поток
который
измеряет
время нажатия
клавиши ) ( Abuf1 -- aдрес где время
храниться ) BEGIN
PZ_N 1 = IF
DUP 4 + DUP @ 0= IF
-1 SWAP ! TIME_SOST_WORKS ( -- wsec ) OVER
! ELSE DROP THEN THEN
PZ_N 2 = IF
DUP 4 + 0! 0 TO PZ_N TIME_SOST_WORKS ( -- wsec ) OVER @ - OVER 8 + !
-1 OVER 3 4 * + ! (
установили
признак для
записи в файл
данных )
THEN 0 UNTIL ; ' WORK_IZM_NAGIMA TASK: exWORK_IZM_NAGIMA ( подготовлено
слово для запуска
потока
измерения ) : WORK_FILE_NAGIMA_T1 ( Abuf1 --- Abuf1 ---
запись
данных в
файл ) \
измеренные
данные
времени
нажатия находяться
в области 8 + от
начала их и выдаем но
в начале
текущее
время \
записываем
время
события и
температуры
датчиков
но файл c
описателем FR2 DECIMAL TIME ( cc мм чч -->
время
системы в стек ) 3 .RF
FR1 @ WRITE-FILE (
c-addr u fileid -- ior ) DROP (
записали
час ) S" :" (
знак ) FR1 @ WRITE-FILE ( c-addr u fileid -- ior ) DROP (
записали
знак ) 3 .RF
FR1 @ WRITE-FILE (
c-addr u fileid -- ior ) DROP (
записали
минуты ) S" :" (
знак ) FR1 @ WRITE-FILE ( c-addr u fileid -- ior ) DROP (
записали
знак ) 3 .RF
FR1 @ WRITE-FILE (
c-addr u fileid -- ior ) DROP (
записали
секунды )
S" _" 0x9 2 PICK C! FR1 @ WRITE-FILE ( c-addr u fileid -- ior ) DROP (
записали
разделитель
таб код 0x9 ) \ -------------------------------------------------------------------------- DUP 8 + @ 9
.RF FR1 @ WRITE-FILE ( c-addr u fileid -- ior ) DROP (
записали
число
миллисекунд
) S" _" 0x9 2 PICK C! FR1 @ WRITE-FILE ( c-addr u fileid -- ior ) DROP (
записали
разделитель
таб код 0x9 ) S" __" ( A1
N=1 ) 0xD 2 PICK C! ( код
ВК ) 0xA 2 PICK 1+ C! FR1 @ WRITE-FILE ( c-addr u fileid -- ior ) DROP ( 2а
байта
перевода
строки ) ; : WORK_FILE_NAGIMA ( A=BUF1 -- поток
который записывае
в файл время
нажатия
клавиши ) ( Abuf1 -- aдрес где все
храниться ) BEGIN
DUP 3 4 * + DUP @ (
признак
для записи в
файл данных
-1/0 )
IF 0! (
сбрасываем
и переходим
к записи в
файл )
WORK_FILE_NAGIMA_T1 ( Abuf1 --- Abuf1 ---
запись
данных в
файл )
ELSE DROP THEN
0 UNTIL ; ' WORK_FILE_NAGIMA TASK: exWORK_FILE_NAGIMA ( подготовлено
слово для
запуска
потока записи
в файл ) : M_PODGOTOVKA ( К
- подготовка ) S" Учет
времени
двойного
нажатия клавиши
1 " ANSI>OEM TYPE CR S" Выход
из
программы
клавиша - ESC "
ANSI>OEM TYPE \ STARTLOG (
ВКЛЮЧИТЬ
ФАЙЛ ОТЧЕТА SPF.LOG ) \ ENDLOG ( выключить
файл отчета
) NAME_DAN R/W CREATE-FILE DROP ( FR -- ) FR1 ! ( cоздали файл для
записи и
чтения и
сохранили
указатель
на файл ) 0x10
ALLOCATE THROW TO BUF1 ( заняли
временную
память и
записали
адрес ее
начало в
локальную перменную
BUF1 ) 0x10 NDAT * ALLOCATE THROW TO BUF2 BUF1 exWORK_IZM_NAGIMA START TO FR3 (
запустили
поток для
измерения
времени
нажатия ) BUF1 exWORK_FILE_NAGIMA START FR1 4 + ! (
запустили
поток для
измерения
времени нажатия ) ?KEY1 ( K -
код нажатия
выдали
сразу же ) ; : M_DAN_READ ( K - K
получение
данных ) DUP [CHAR] 1 = IF PZ_N 1+ TO PZ_N THEN (
при нажатии
увеличиваем
значение
признака ) ; \
--------------------------------------------- : M_DAN_EKRAN ( K -- K
отображение
на экране ) DUP 0= IF EXIT THEN 0x200 FIX S"
Нажата
клавиша :
" ANSI>OEM TYPE DUP EMIT S" время нажатия,мс
= " ANSI>OEM TYPE BUF1 8 + @ 9 .R ; : M_DAN_WRITE_FILE ( запись
данных в
файле ) ; : M_DAN_TRW ( At Ndel=2 - 0/-1
контроль
предела для ds1820 только для Ттрв > 0 гр.Ц
) ; : M_USLOVIJ ( 0/-1
– проверка
условий ) 0 ; : M_GRN_EKRAN ( отображение
на экране ) \
0x300 FIX DUP 0<> IF
DUP EMIT THEN ; : M_GRN_EKRAN_CLS (
очистка
сообщений
на экране ) ; : M_GRN_WRITE ( запись
границы в
файле ) ; : M_OUT_WORK ( k1 - K2 0/-1
проверка
условий
выхода ) DROP ?KEY1 DUP 0x1B = ( K PZ=-1 при нажатик
клавиши ESC ) ; : M_ZAVERCHEN ( завершение ) FR1 @ CLOSE-FILE ( fileid -- ior
закрыли
файл ) DROP BUF2 FREE DROP (
освободили
память ) BUF1 FREE DROP (
освободили
память ) BYE ; \
главное
слово
мониторинга
: MAIN ( главное
слово ) M_PODGOTOVKA ( K -
подготовка ) BEGIN ( K --
код нажатия
на стеке ) M_DAN_READ ( k --
получение
данных ) M_DAN_EKRAN (
отображение
на экране ) M_DAN_WRITE_FILE (
запись
данных в
файле ) M_USLOVIJ ( 0/-1 –
проверка
условий ) IF (
да –
индикация.
Граница
нарушена ) M_GRN_EKRAN (
отображение
на экране ) M_GRN_WRITE (
запись
границы в
файле ) ELSE (
нет -
все
нормально ) M_GRN_EKRAN_CLS (
очистка
сообщений
на экране ) THEN M_OUT_WORK ( Kkl 0/-1
проверка
условий
выхода ) UNTIL ( выход
из цикла
если будет -1
или к begin) M_ZAVERCHEN ( K
завершение ) ; \
подготавливаем
переменные и
текст
программы
записываем
в исполняемый
файл. 0 TO SPF-INIT? ( в
переменную
записываем
код 0 –
означает что
инициализация
выполняется
) ' NOOP MAINX ! (
в
переменную
записываем
адрес выхода
) ' MAIN TO <MAIN> ( в
переменную
записываем старт
программы
со слова MAIN ) S" test2.exe" SAVE (
сохраняем
файл
исполнения с
именем test2.exe ) BYE ( выходим
из режима
редактирования
и компиляция,
т.е. все
бай-бай ) \ текст программы
окончен. |
Отвлечение
руководителя
анекдот - на
лекции не
озвучивать;
· Скромность
красит
человека. В
серенький цвет. |
Модификация
– 1-й уровень
понимания.
Новые
свойства – 2-ой
уровень
понимания.
Изменения
алгоритма –
3-ий уровень
понимания и
создания.
Задача
практической
полезности
Внимание!
Задачи
выполняются и
передаются
руководителю
на электронную
почту с
соблюдением
правил оформления. Архив
должен
содержать; титульный
лист – 1 файл,
Текст задачи
– на каждую
задачу свой
текстовый
файл.
Исполняемый
файл. Имя
текстового
файла задачи
должно соответствовать
имени
исполняемого
файла.
На
практических
занятиях
каждый
обучаемый в
группе
должен
выполнить
выше,
приведенные
задачи.
Решение и
обоснование
выбора
решения,
стиль
отображения,
ошибки в
работе
программы -
определяют
оценку
обучаемого. Количество
задач и их
оценивание
задано по
условию =ИЛИ=
Т.е. если предполагается ответ
на 5 то все
предыдущие
уровни
предоставлять
не надо.
Отвлечение
руководителя
анекдот - на
лекции не
озвучивать;
·
Критика
должна быть
конструктивной.
Оскорбления
должны быть
аргументированы.
"Ты дурак, потому
что ты
идиот" - так,
например. |
Внимание!
– программы
клавиатурного
почерка
могут иметь
коммерческий
статус или
отсутствовать
на сайтах по предлагаемым,
на этих
сайтах ссылкам.
Поиск
и
использование
программ не входит
в тему данной
лекции.
Отвлечение
руководителя
анекдот - на
лекции не
озвучивать;
·
Ленивые
всё делают
быстро. Чтобы
поскорее
отделаться
от
работы. И
делают
качественно.
Чтобы потом
не переделывать. |
Подготовлено
10-3-2016
Автор Шабронов
Андрей
Анатольевич тс.
913-905-8839 shabronov@ngs.ru
Ред-2 -11-3-2016