Прежде всего, микроконтроллер это процессор со всеми его "атрибутами", плюс встроенная, энергонезависимая память (программ и данных), что позволяет отказаться от внешней памяти программ и поместить программу в его энергонезависимую память.
Это позволяет создавать очень простые (в схемотехническом отношении) и компактные устройства, выполняющие, тем не менее, достаточно сложные функции. Иногда даже диву даешься: эта маленькая "штучка" заменяет целую "груду старого железа"
Любой микроконтроллер, по своим возможностям, конечно же, уступает процессору компьютера, но тем не менее, существует весьма обширный класс устройств, которые преимущественно реализуются именно на микроконтроллерах. И в самом деле, компьютер в карман не положишь и от батареек его не запитаешь. Поэтому, во многих случаях, микроконтроллерам просто нет альтернативы. "Сердцем" микроконтроллера является арифметико - логическое устройство (АЛУ).
Проще всего его представить в виде банального калькулятора, кнопками которого управляет программа, написанная на языке ассемблер (то есть, программист). Если вдуматься, то ничего особо сложного, в механизме управления такого рода калькулятором, нет. И в самом деле, если нужно, например, сложить числа А и В, то в тексте программы сначала задаются константы А и В, а затем дается команда "сложить". Программисту вовсе не обязательно знать, что происходит с нулями и единицами (разве только только для общего развития), ведь калькулятор он на то и калькулятор, чтобы избавить пользователя от "возни" с машинными кодами и прочими "неудобоваримостями".
Когда Вы работаете с компьютером, Вам и не нужно детально знать, что происходит в дебрях операционной системы.
Если Вы туда "полезете", то "с ума сойдете", а микроконтроллер, по своей сути, есть тот же самый компьютер, но только простой. Программисту только нужно детально знать, каким именно образом "приказать железяке" сделать то, что необходимо для достижения задуманного. Микроконтроллер можно представить себе как некий универсальный "набор" многофункциональных модулей (блоков), "рычаги управления" которыми находятся в руках программиста. Этих "рычагов" достаточно большое количество, и естественно, их нужно освоить и точно знать, что именно произойдет, если "дернуть" (дать команду на языке ассемблер) за тот или иной "рычаг". Вот здесь-то уже нужно знать, как "отче наше", каждую деталь и не жалеть на это "узнавание" времени. Только таким образом пустую "болванку" (незапрограммированый ПИК) можно "заставить"
выполнять какие-то "осмысленные" действия, результат большей части которых можно проверить в симуляторе MPLAB (об этом - позднее), даже не записывая программу в ПИК.
Итак, необходим переход к "модульному" мышлению. Любой микроконтроллер можно уподобить детскому конструктору, в состав которого входит множество всяких предметов, манипулируя с которыми, можно получить тот или иной конечный "продукт". Давайте с ними разберемся и "разложим все по полочкам". В качестве примера я буду использовать один из самых распространенных PIC контроллеров PIC16F84A. Он является как бы "проматерью" более сложных ПИКов, содержит минимальный "набор" модулей и как нельзя лучше подходит для первичного "въезда в м/контроллеры".
Энергонезависимая память.
Начнем с энергонезависимой памяти (память программ и память данных).
Информация, заложенная в энергонезависимую память, сохраняется при выключении питания, и поэтому именно в нее записывается программа.
То "место" энергонезависимой памяти, куда записывается программа, называется памятью программ. Объем памяти программ может быть различен. Для PIC16F84A, он составляет 1024 слова. Это означает, что он предназначен для работы с программами, объем которых не превышает 111024 слов.
Слово памяти программ не равно одному байту (8 бит), а больше его (14 бит). Отдельная команда, которую ПИК будет в дальнейшем выполнять, занимает одно слово в памяти программ. В зависимости от названия этой команды в ассемблере, слово принимает то или иное числовое значение в машинном коде. После записи в ПИК "прошивки" программы, слова памяти программ (машинные коды) как бы "превращаются" в команды, которые располагаются, в памяти программ, в том же порядке, в котором они следуют в исходном тексте программы, написанном на языке ассемблер, и в том же порядке им присваиваются адреса, при обращении к которым, та или иная команда "извлекается" из памяти программ для ее выполнения. Последовательность же их выполнения определяется логикой программы. Это означает то, что выполнение команд может происходить не в порядке последовательного возрастания их адресов, с шагом в одну позицию (так называемый инкремент), а "скачком". Дело в том, что только уж самые простейшие программы, в пределах одного их полного цикла, обходятся без этих "скачков", называемых переходами, и выполняются строго последовательно. В остальных же случаях, так называемая (мной) "рабочая точка программы" "мечется по тексту программы как угорелая" (как раз благодаря этим самым переходам).
Термин "рабочая точка программы" - моя "самодеятельность". В свое время, я был очень сильно удивлен отсутствием чего-то подобного в информации, связанной с объяснением работы программ. Казалось бы, чего проще, по аналогии, например, с рабочей точкой транзистора, сделать более комфортным "въезд в механику" работы программ? Так нет же, как будто специально, придумываются такие "головокружительные заменители", причем, в различных случаях, разные, что запутаться в этом очень просто. Итак, рабочую точку программы можно представить себе в виде некоего "шарика от пинг-понга", который "скачет" по командам текста программы в соответствии с алгоритмом (логикой) исполнения программы. На какую команду "шарик скакнул", та команда и исполняется. После этого он "перескакивает" на другую команду, она исполняется, и т.д. Эти "скачки" происходят непрерывно и в течение всего времени включения питания устройства (исполнения программы).
Любая более-менее сложная программа разбивается на части, которые выполняют отдельные функции (своего рода программки в программе) и которые называются подпрограммами. Атрибут любой подпрограммы - функциональная законченность производимых в ней действий.
По сути своей, эта "выдумка" введена в программирование для удобства реализации принципа "разделяй и властвуй": "врага" ведь гораздо легче "разгромить по частям, чем в общей массе". Да и порядка больше.
Безусловные переходы (переходы без условия) между подпрограммами (если они последовательно не переходят одна в другую), осуществляются при помощи команд безусловных переходов, в которых обязательно указывается адрес команды в памяти программ (косвенно - в виде названия подпрограммы или метки), на которую нужно перейти. Существуют также переходы с условием (условные переходы), то есть, с задействованием так называемого стека. Более подробно о переходах я расскажу позднее. Адреса команд определяются счетчиком команд (он называется PC). То есть, каждому состоянию счетчика команд соответствует одна из команд программы. Если команда простая, то счетчик просто инкрементируется (последовательно выполняется следующая команда), а если команда сложная (например, команда перехода или возврата), то счетчик команд изменяет свое состояние "скачком", активируя соответствующую команду.
Примечание: инкремент - увеличение на единицу величины числа, с которым производится эта операция, а декремент - уменьшение на единицу (так называемые комплиментарные операции). В простейшем случае, то есть в случае отсутствия в программе переходов, счетчик команд PC, начиная с команды "старта" (нулевой адрес), многократно инкрементируется, 12 последовательно активизируя все команды в памяти программ. Это означает, что в большинстве случаев, за каждый так называемый машинный цикл (такт работы программы: для ПИКов он равен четырем периодам тактового генератора) работы ПИКа, происходит исполнение одной команды. Есть и команды исполнение которых происходит за 2 машинных цикла (м.ц.), но их меньше. Команд, которые исполняются за 3 м.ц. и более нет. Таким вот образом, на большинстве участков программы (я их называю "линейными участками"), последовательно и перебираются адреса в памяти программ (команды последовательно исполняются).
В более сложных программах, с большим количеством условных и безусловных переходов, работу счетчика команд PC можно охарактеризовать фразой "Фигаро здесь, Фигаро там". 1 машинный цикл (м.ц.) равен 4-м периодам тактового генератора ПИКа. Следовательно, при использовании кварца на 4 Мгц., 1 м.ц.=1 мкс. Выполнение программы, в рабочем режиме (кроме работы в режиме пониженного энергопотребления SLEEP), никогда не останавливается, то есть, за каждый машинный цикл (или за 2, если команда исполняется за 2 м.ц.) должно выполняться какое-либо действие (команда). Тактовый генератор, формирующий машинные циклы, работает постоянно. Если его работу прервать, то исполнение программы прекратится.
Может сложиться ложное представление о том, что работу программы можно на какое-то время остановить, используя одну или несколько команд – "пустышек", не производящих полезных действий (есть такая команда NOP). Это представление не верно, так как в этом случае, речь идет только о задержке выполнения следующих команд, а не об остановке исполнения программы. Программа исполняется и в этом случае, так как "пустышка" есть та же самая команда программы, только не производящая никаких действий (короткая задержка). Если же нужно задержать выполнение каких-либо последующих команд на относительно длительное время, то применяются специальные, циклические подпрограммы задержек, о которых я расскажу позднее. Даже тогда, когда программа "зависает" ("глюк"), она исполняется, просто только не так, как нужно. Остановить (в буквальном смысле этого слова) исполнение программы можно только прекратив работу тактового генератора. Это происходит при переходе в режим пониженного энергопотребления (SLEEP), который используется в работе достаточно специфических устройств. Например, пультов дистанционного управления (и т.д.).
Отсюда следует вывод: программы, не использующие режим SLEEP (а таких - большинство), для обеспечения непрерывного выполнения команд программы, обязательно должны быть циклическими, то есть, иметь так называемый полный цикл программы, причем, многократно повторяющийся в течение всего времени включения питания. Проще говоря, рабочая точка программы должна непрерывно (не останавливаясь) "мотать кольца" полного цикла программы (непрерывно переходить с одного "кольца" на другое).
Общие выводы:
1. Команды программы "лежат" в памяти программ в порядке расположения команд в тексте программы.
2. Адреса этих команд находятся в счетчике команд PC и каждому адресу соответствует одна из команд программы.
3. Команда активируется (исполняется), если в счетчике команд находится ее адрес.
4. Активация команд происходит либо последовательно (на "линейном" участке программы), либо с переходом ("скачком") на другую команду (при выполнении команд переходов), с которой может начинаться как подпрограмма (переход на исполнение подпрограммы), так и группа команд, выделенная меткой (переход на исполнение группы команд, которой не присвоен "статус" подпрограммы).
5. Выполнение команд программы никогда не останавливается (за исключением режима SLEEP), и поэтому программа должна быть циклической.
Кроме памяти программ, PIC16F84A имеет энергонезависимую память данных (EEPROM память данных). Она предназначена для сохранения данных, имеющих место быть на момент выключения питания устройства, в целях их использования в дальнейшем (после следующего включения питания). Так же, как и память программ, память данных состоит из ячеек, в которых "лежат" слова. Слово памяти данных равно одному байту (8 бит). В PIC16F84A, объем памяти данных составляет 64 байта. Байты, хранящиеся в памяти данных, предназначены для их считывания в стандартные 8-битные регистры, речь о которых пойдет далее. Данные из этих регистров могут быть записаны в EEPROM память данных, то есть, может быть организован обмен данными между памятью данных и регистрами. Например, именно EEPROM память данных я использовал в своем частотомере для сохранения последних, перед выключением питания, настроек. Она же используется и для установки значений промежуточной частоты. Во многих программах, память данных вообще не используется, но это "вещь" исключительно полезная, и далее я расскажу о ней подробнее.
Данная статья предназначена для начинающих программистов, которые никогда не работали с потоками, и хотели бы узнать основы работы с ними. Желательно, чтоб читатель знал основы ООП и имел какой-нибудь опыт работы в Delphi.
Для начала давайте определимся, что под словом "поток" я подразумеваю именно Thread, который еще имеет название "нить". Нередко встречал на форумах мнения, что потоки не нужны вообще, любую программу можно написать так, что она будет замечательно работать и без них. Конечно, если не делать ничего серьёзней "Hello World" это так и есть, но если постепенно набирать опыт, рано или поздно любой начинающий программист упрётся в возможности "плоского" кода, возникнет необходимость распараллелить задачи. А некоторые задачи вообще нельзя реализовать без использования потоков, например работа с сокетами, COM-портом, длительное ожидание каких-либо событий, и т.д.
Всем известно, что Windows система многозадачная. Попросту говоря, это означает, что несколько программ могут работать одновременно под управлением ОС. Все мы открывали диспетчер задач и видели список процессов. Процесс - это экземпляр выполняемого приложения. На самом деле сам по себе он ничего не выполняет, он создаётся при запуске приложения, содержит в себе служебную информацию, через которую система с ним работает, так же ему выделяется необходимая память под код и данные. Для того, чтобы программа заработала, в нём создаётся поток. Любой процесс содержит в себе хотя бы один поток, и именно он отвечает за выполнение кода и получает на это процессорное время. Этим и достигается мнимая параллельность работы программ, или, как её еще называют, псевдопараллельность. Почему мнимая? Да потому, что реально процессор в каждый момент времени может выполнять только один участок кода. Windows раздаёт процессорное время всем потокам в системе по очереди, тем самым создаётся впечатление, что они работают одновременно. Реально работающие параллельно потоки могут быть только на машинах с двумя и более процессорами.
Для создания дополнительных потоков в Delphi существует базовый класс TThread, от него мы и будем наследоваться при реализации своих потоков. Для того, чтобы создать "скелет" нового класса, можно выбрать в меню File - New - Thread Object, Delphi создаст новый модуль с заготовкой этого класса. Я же для наглядности опишу его в модуле формы. Как видите, в этой заготовке добавлен один метод - Execute. Именно его нам и нужно переопределить, код внутри него и будет работать в отдельном потоке. И так, попробуем написать пример - запустим в потоке бесконечный цикл:
Запустите пример на выполнение и нажмите кнопку. Вроде ничего не происходит - форма не зависла, реагирует на перемещения. На самом деле это не так - откройте диспетчер задач и вы увидите, что процессор загружен по-полной. Сейчас в процессе вашего приложения работает два потока - один был создан изначально, при запуске приложения. Второй, который так грузит процессор - мы создали по нажатию кнопки. Итак, давайте разберём, что же означает код в Button1Click:
тут мы создали экземпляр класса TNewThread. Конструктор Create имеет всего один параметр - CreateSuspended типа boolean, который указывает, запустить новый поток сразу после создания (если false), или дождаться команды (если true).
свойство FreeOnTerminate определяет, что поток после выполнения автоматически завершится, объект будет уничтожен, и нам не придётся его уничтожать вручную. В нашем примере это не имеет значения, так как сам по себе он никогда не завершится, но понадобится в следующих примерах.
Свойство Priority, если вы еще не догадались из названия, устанавливает приоритет потока. Да да, каждый поток в системе имеет свой приоритет. Если процессорного времени не хватает, система начинает распределять его согласно приоритетам потоков. Свойство Priority может принимать следующие значения:
tpTimeCritical - критический
tpHighest - очень высокий
tpHigher - высокий
tpNormal - средний
tpLower - низкий
tpLowest - очень низкий
tpIdle - поток работает во время простоя системы
Ставить высокие приоритеты потокам не стоит, если этого не требует задача, так как это сильно нагружает систему.
Ну и собственно, запуск потока.
Думаю, теперь вам понятно, как создаются потоки. Заметьте, ничего сложного. Но не всё так просто. Казалось бы - пишем любой код внутри метода Execute и всё, а нет, потоки имеют одно неприятное свойство - они ничего не знают друг о друге. И что такого? - спросите вы. А вот что: допустим, вы пытаетесь из другого потока изменить свойство какого-нибудь компонента на форме. Как известно, VCL однопоточна, весь код внутри приложения выполняется последовательно. Допустим, в процессе работы изменились какие-то данные внутри классов VCL, система отбирает время у основного потока, передаёт по кругу остальным потокам и возвращает обратно, при этом выполнение кода продолжается с того места, где приостановилось. Если мы из своего потока что-то меняем, к примеру, на форме, задействуется много механизмов внутри VCL (напомню, выполнение основного потока пока "приостановлено"), соответственно за это время успеют измениться какие-либо данные. И тут вдруг время снова отдаётся основному потоку, он спокойно продолжает своё выполнение, но данные уже изменены! К чему это может привести - предугадать нельзя. Вы можете проверить это тысячу раз, и ничего не произойдёт, а на тысяча первый программа рухнет. И это относится не только к взаимодействию дополнительных потоков с главным, но и к взаимодействию потоков между собой. Писать такие ненадёжные программы конечно нельзя.
Синхронизации потоков
Если вы создали шаблон класса автоматически, то, наверное, заметили комментарий, который дружелюбная Delphi поместила в новый модуль. Он гласит: "Methods and properties of objects in visual components can only be used in a method called using Synchronize". Это значит, что обращение к визуальным компонентам возможно только путём вызова процедуры Synchronize. Давайте рассмотрим пример, но теперь наш поток не будет разогревать процессор впустую, а будет делать что-нибудь полезное, к примеру, прокручивать ProgressBar на форме. В качестве параметра в процедуру Synchronize передаётся метод нашего потока, но сам он передаётся без параметров. Параметры можно передать, добавив поля нужного типа в описание нашего класса. У нас будет одно поле - тот самый прогресс:
Вот теперь ProgressBar двигается, и это вполне безопасно. А безопасно вот почему: процедура Synchronize на время приостанавливает выполнение нашего потока, и передаёт управление главному потоку, т.е. SetProgress выполняется в главном потоке. Это нужно запомнить, потому что некоторые допускают ошибки, выполняя внутри Synchronize длительную работу, при этом, что очевидно, форма зависает на длительное время. Поэтому используйте Synchronize для вывода информации - то самое двигание прогресса, обновления заголовков компонентов и т.д.
Вы наверное заметили, что внутри цикла мы используем процедуру Sleep. В однопоточном приложении Sleep используется редко, а вот в потоках его использовать очень удобно. Пример - бесконечный цикл, пока не выполнится какое-нибудь условие. Если не вставить туда Sleep мы будем просто нагружать систему бесполезной работой.
Надеюсь, вы поняли как работает Synchronize. Но есть еще один довольно удобный способ передать информацию форме - посылка сообщения. Давайте рассмотрим и его. Для этого объявим константу:
В объявление класса формы добавим новый метод, а затем и его реализацию:
Используя функцию SendMessage, мы посылаем окну приложения сообщение, один из параметров которого содержит нужный нам прогресс. Сообщение становится в очередь, и согласно этой очереди будет обработано главным потоком, где и выполнится метод SetProgressPos. Но тут есть один нюанс: SendMessage, как и в случае с Synchronize, приостановит выполнение нашего потока, пока основной поток не обработает сообщение. Если использовать PostMessage этого не произойдёт, наш поток отправит сообщение и продолжит свою работу, а уж когда оно там обработается - неважно. Какую из этих функций использовать - решать вам, всё зависит от задачи.
Вот, в принципе, мы и рассмотрели основные способы работы с компонентами VCL из потоков. А как быть, если в нашей программе не один новый поток, а несколько? И нужно организовать работу с одними и теми же данными? Тут нам на помощь приходят другие способы синхронизации. Один из них мы и рассмотрим. Для его реализации нужно добавить в проект модуль SyncObjs.
Критические секции
Работают они следующим образом: внутри критической секции может работать только один поток, другие ждут его завершения. Чтобы лучше понять, везде приводят сравнение с узкой трубой: представьте, с одной стороны "толпятся" потоки, но в трубу может "пролезть" только один, а когда он "пролезет" - начнёт движение второй, и так по порядку. Еще проще понять это на примере и тем же ProgressBar'ом. Итак, запустите один из примеров, приведённых ранее. Нажмите на кнопку, подождите несколько секунд, а затем нажмите еще раз. Что происходит? ProgressBar начал прыгать. Прыгает потому, что у нас работает не один поток, а два, и каждый из них передаёт разные значения прогресса. Теперь немного переделаем код, в событии onCreate формы создадим критическую секцию:
У TCriticalSection есть два нужных нам метода, Enter и Leave, соответственно вход и выход из неё. Поместим наш код в критическую секцию:
Попробуйте запустить приложение и нажать несколько раз на кнопку, а потом посчитайте, сколько раз пройдёт прогресс. Понятно, в чем суть? Первый раз, нажимая на кнопку, мы создаём поток, он занимает критическую секцию и начинает работу. Нажимаем второй - создаётся второй поток, но критическая секция занята, и он ждёт, пока её не освободит первый. Третий, четвёртый - все пройдут только по-очереди.
Критические секции удобно использовать при обработке одних и тех же данных (списков, массивов) разными потоками. Поняв, как они работают, вы всегда найдёте им применение.
В этой небольшой статье рассмотрены не все способы синхронизации, есть еще события (TEvent), а так же объекты системы, такие как мьютексы (Mutex), семафоры (Semaphore), но они больше подходят для взаимодействия между приложениями. Остальное, что касается использования класса TThread, вы можете узнать самостоятельно, в help'е всё довольно подробно описано. Цель этой статьи - показать начинающим, что не всё так сложно и страшно, главное разобраться, что есть что. И побольше практики - самое главное опыт!
Главное о чем стоит упомянуть это, что ваш хранитель экрана будет работать в фоновом режиме и он не должен мешать работе других запущенных программ. Поэтому сам хранитель должен быть как можно меньшего объема. Для уменьшения объема файла в описанной ниже программе не используется визуальные компоненты Delphi, включение хотя бы одного из них приведет к увеличению размера файла свыше 200кб, а так, описанная ниже программа, имеет размер всего 20кб!!!
Технически, хранитель экрана является нормальным EXE файлом (с расширением .SCR), который управляется через командные параметры строки. Например, если пользователь хочет изменить параметры вашего хранителя, Windows выполняет его с параметром "-c" в командной строке. Поэтому начать создание вашего хранителя экрана следует с создания примерно следующей функции:
Поскольку нам нужно создавать небольшое окно предварительного просмотра и полноэкранное окно, их лучше объединить используя единственный класс окна. Следуя правилам хорошего тона, нам также нужно использовать многочисленные нити. Дело в том, что, во-первых, хранитель не должен переставать работать даже если что-то "тяжелое" случилось, и во-вторых, нам не нужно использовать таймер.
Процедура для запуска хранителя на полном экране - приблизительно такова:
Во-первых, мы проинициализировали некоторые глобальные переменные (описанные далее), затем прячем курсор мыши и создаем окно хранителя экрана. Имейте в виду, что важно уведомлять Windows, что это - хранителя экрана через SystemParametersInfo (это выводит из строя Ctrl-Alt-Del чтобы нельзя было вернуться в Windows не введя пароль). Создание окна хранителя:
Теперь окна созданы используя вызовы API. Я удалил проверку ошибки, но обычно все проходит хорошо, особенно в этом типе приложения.
Теперь Вы можете погадать, как мы получим handle родительского окна предварительного просмотра ? В действительности, это совсем просто: Windows просто передает handle в командной строке, когда это нужно. Таким образом:
Как Вы видите, window handle является вторым параметром (после "-p").
Чтобы "выполнять" хранителя экрана - нам нужна нить. Это создается с вышеуказанным CreateThread. Процедура нити выглядит примерно так:
Нить просто заставляет обновляться изображения в нашем окне, спит на некоторое время, и обновляет изображения снова. А Windows будет посылать сообщение WM_PAINT на наше окно (не в нить !). Для того, чтобы оперировать этим сообщением, нам нужна процедура:
Если мышь перемещается, кнопка нажала, мы спрашиваем у пользователя пароль:
Это также демонстрирует использование registry на уровне API. Также имейте в виду как мы динамически загружаем функции пароля, используюя LoadLibrary. Запомните тип функции?
TVSSFunc ОПРЕДЕЛЕН как:
Теперь почти все готово, кроме диалога конфигурации. Это запросто:
Трудная часть -это создать диалоговый сценарий (запомните: мы не используем здесь Delphi формы!). Я сделал это, используя 16-битовую Resource Workshop (остался еще от Turbo Pascal для Windows). Я сохранил файл как сценарий (текст), и скомпилированный это с BRCC32:
Почти также легко сделать диалоговое меню:
После того, как пользователь выбрал некоторые установочные параметры, нам нужно сохранить их.
Загружаем параметры так:
Легко? Нам также нужно позволить пользователю, установить пароль. Я честно не знаю почему это оставлено разработчику приложений ! Тем не менее:
Мы динамически загружаем (недокументированную) библиотеку MPR.DLL, которая имеет функцию, чтобы установить пароль хранителя экрана, так что нам не нужно беспокоиться об этом.
TPCPAFund ОПРЕДЕЛЕН как:
(Не спрашивайте меня что за параметры B и C ! :-)
Теперь единственная вещь, которую нам нужно рассмотреть, - самая странная часть: создание графики. Я не великий ГУРУ графики, так что Вы не увидите затеняющие многоугольники, вращающиеся в реальном времени. Я только сделал некоторые ящики.
И последнее - глобальные переменные:
Затем исходная программа проекта (.dpr). Красива, а!?
Ох, чуть не забыл! Если, Вы используете SysUtils в вашем проекте (например фуекцию StrToInt) вы получите EXE-файл больше чем обещанный в 20k. :) Если Вы хотите все же иметь20k, надо как-то обойтись без SysUtils, например самому написать собственную StrToInt процедуру.
Если все же очень трудно обойтись без использования Delphi-форм, то можно поступить как в случае с вводом пароля: форму изменения параметров хранителя сохранить в виде DLL и динамически ее загружать при необходимости. Т.о. будет маленький и шустрый файл самого хранителя экрана и довеска DLL для конфигурирования и прочего (там объем и скорость уже не критичны).
Те, кто устанавливают в свой компьютер источники бесперебойного питания, надеются повысить стабильность работы своего электронного монстра, а заодно и продлить ему жизнь за счёт оберегания его от скачков напряжения и работы при ненормальном режиме электроснабжения потребителей. Проще говоря, сегодня установка ИБП является синонимом повышения надёжности и никто не сомневается в том, что UPS принесёт пользу любому компьютеру. В этой маленькой статье я расскажу вам, что это не так, и прежде чем покупать источник бесперебойного питания, надо хорошо подумать, потому что он может не только не добавить стабильности вашей системе, но и наоборот - сделать работу за компьютером невозможной.
Скажу честно: я никогда не считал источник бесперебойного питания необходимой частью компьютера, а потому и не стал бы покупать его, даже если бы и имелись лишние деньги. В питании компьютера я всегда был уверен, как уверен в этом и сейчас. В моём доме напряжение практически всегда составляет 230 В, иногда поднимаясь, или опускаясь. Бывает, что напряжение скачет, это видно по миганию лампочек накаливания, или по стрелке подключённого к розетке вольтметра. Всё это никогда не отражалось ни на работе монитора, ни на работе компьютера, подключенных в розетку, без всевозможных фильтров типа "пилот", и даже без заземления. Конечно, иногда если коснуться корпуса компьютера и батареи, можно почувствовать, как через тебя проходит небольшой ток, но это не смертельно и на работу компьютера пока что никак не повлияло.
Однажды в розетке, питающей компьютер с монитором, напряжение упало почти в два раза - вольт до 120. Дело было днём, поэтому свет в комнате не горел, и определить, что упало напряжение, я смог только по замедлившему ход напольному вентилятору. Его обороты сильно упали, а когда я его выключил, а затем попытался включить, пропеллер остался неподвижен. Компьютер всё это время работал нормально. Прошло несколько минут и я его выключил. Затем включил снова, а он не включается. Тут-то я и понял, что проблема в напряжении. На щитке отключил автоматы, включил заново и напряжение в линии снова составило 230 Вольт, в чём я убедился при помощи вольтметра. Дело было в неисправности щитка, но это так, к слову. Теперь я знаю, что скачки и провалы напряжения, которыми нас так пугают производители фильтров и источников бесперебойного питания, китайскому 250 Ваттному блоку питания не страшны, ровно как и монитору LG Flatron, который тоже сделан не в Штатах. Наверное, поэтому ставить что-то защищающее компьютер по питанию домой я не хотел. Но вот недавно, во время написания очередного обзора в домеотключили электричество и тут же, где-то через секунду включили. Компьютер, естественно, этого не вынес и та часть обзора, которую я не успел сохранить, канула в лету. На личном опыте я знаю, что UPS спас бы меня и я твёрдо решился установить его в компьютер.
Какой фирмы я взял UPS, говорить не буду. Потому что никаких претензий к источнику питания я не имею, и всё, сказанное дальше будет справедливо для подавляющего большинства ИБП. В общем, компьютер был подключен к этому устройству, помогающему мне бороться с недостатками нашего электроснабжения. "Первые ласточки" появились через несколько часов после начала работы компьютера. Дело в том, что UPS действительно защищает от скачков напряжения, но делает это не выравниванием напряжения за счёт регулирования трансформатора, а за счёт переключения в Backup Mode, то есть питания компьютера от аккумуляторов. Естественно, такой способ намного дешевле, а стабилизаторы напряжения в недорогих ИБП не применяются. Дело в том, что когда источник бесперебойного питания почувствовал скачок напряжения, то он переключает компьютер в питание от батареек на некоторое время. Обычно, это несколько секунд. По истечение этого срока, если скачков напряжения, или других аномалий не было, компьютер переключается обратно, на питание от сети. В разных моделях UPS чувствительность разная. Некоторые допускают отклонение напряжения в 10 процентов, другие - в 15. Чувствительность может не совпадать с заявленной, хотя для проверки этого придётся воспользоваться измерительными приборами. Ну да разговор не об этом. Через несколько часов работы в сети начались незначительные скачки и провалы напряжения. Свет не моргал, а вот ИБП переключил компьютер в Backup режим.
Первый период запитки от аккумуляторов длился недолго - около тридцати секунд. После этого датчики источника бесперебойного питания определили, что напряжение в розетке полностью соответствует норме, и компьютер был переключён на питание от розетки, а аккумуляторные батареи стали заряжаться, восполняя частичный разряд. Прошёл час и наступило тёмное время суток, ночь. Ночью число потребителей электроэнергии значительно падает, а нагрузка на сеть сокращается за счёт прекращения работы предприятий, электротранспорта, да и обычные потребители, если они не сидят в интернете, или не работают в ночную смену, просто спят. Поэтому ночью напряжение в розетке чуть повышается. А это значит, что оно уже подходит к тому порогу, при котором источник бесперебойного питания переводит компьютер в работу от батарей аккумуляторов. И уже небольшие скачки могут запросто заставить компьютер работать от запасённой ранее энергии. Вот тут-то и началось самое интересное. UPS снова запищал, сигнализируя о том, что компьютер работает от аккумуляторов. Но на этот раз период такой запитки длился дольше - около трёх минут. UPS был слабеньким, а потому мог продержать системный блок всего несколько минут. Честно говоря, стало немного страшно. Здесь я поясню: ночью очень удобно скачивать различные большие файлы из сети, особенно по обычному модему, учитывая, что качество аналоговых линий хорошо возрастает. Тут как раз подвернулся файл размером с десяток-другой мегабайт на сервере, не поддерживающем докачку (есть ещё такие). Понятное дело, что отключение компьютера заставило бы меня заново загружать систему, устанавливать связь с провайдером и качать файл с начала. Последнее меня не пугало, так как скачено было всего процентов 10.
Шло время. Аккумуляторы источника бесперебойного питания заряжались, а я работал в интернете. И снова знакомый щелчок реле и писк источника бесперебойного питания. Но теперь я понимаю, что батареи истощены и ИБП не протянет и трёх минут. Сохраняя все данные на диск, я смотрю на статус закачки файла. Почти 90 процентов. Очень бы не хотелось качать его снова. Конечно, можно было бы заставить компьютер перейти в Sleep Mode, но винчестер бы не отключился, процессор бы стал потреблять не намного меньше. И толку это бы не дало. Всё, что остаётся - это смотреть на экран, не двигать мышь и надеяться, что напряжение восстановится раньше, чем аккумуляторы сядут. Через минуту UPS извещает, что аккумуляторы близки к разряду. Это значит, что в запасе осталась от силы минута. Самое интересное, это то, что начинаешь понимать безысходность ситуации. Напряжение в розетке есть, и оно даже нормальное, чуть выше, возможно, чем нужно, но компьютер бы от него работал как по маслу. А этот "источник" считает по-другому. И сделать ничего нельзя. Принудительной запитки от розетки в нём не предусмотрено. Переткнуть компьютер в розетку нельзя. А вытаскивание вилки UPS из розетки, а потом подключение её обратно ничего не даёт. UPS не реагирует. Примерно через минуту экран монитора гаснет. Компьютер выключился. Конечно, файл придётся качать с самого начала. Нужно ли описывать мои чувства в этот момент?
Как видно, в моей ситуации установка источника бесперебойного питания не только не повысила стабильность системы, но и наоборот - понизила её. Днём иногда ИБП также болезненно реагирует на аномалии напряжения, переключаясь на аккумуляторы. Поэтому оставлять компьютер без присмотра становится страшно. Ведь я знаю, что блоку питания ATX такие скачки не страшны, а вот UPS - вещь чувствительная, и может неправильно понять наше напряжение. Два-три переключения длительностью в две минуты, и на третьем компьютер не протянет и тридцати секунд. Вам оно надо?
Что делать?
Поэтому, прежде чем покупать источник бесперебойного питания, подумайте, так ли часто у вас отключают электричество? Именно отключают, потому что скачков напряжения вы можете и не замечать. Благо, с частотой, которую не видно даже по первому признаку - морганию света, у нас в России пока что порядок. Если свет отключают редко, прежде чем брать источник бесперебойного питания присмотритесь к напряжению. Не мигают ли лампы накаливания? Можете попросить UPS на некоторое время у друзей, живущих в другом районе. В крайнем случае, договоритесь с продавцом о возврате денег сроком на две недели. Конечно, можно найти UPS со стабилизатором напряжения, который будет стоить дороже. Можно подключить и внешний стабилизатор напряжения. Но есть и другой выход.
В источниках бесперебойного питания предусмотрена регулировка чувствительности. С помощью специальных резисторов можно выбрать нижнее и верхнее значения напряжения, при которых UPS будет срабатывать и переводить компьютер на питание от батарей. Подняв верхний предел Вольт на 10-20, и опустив нижний на столько же, можно добиться того, что ИБП не будет впустую реагировать на незначительные скачки. Лишние 10-20 Вольт компьютеру не повредят, а вот сделать вашу жизнь спокойнее смогут. Обычно, такую операцию над источниками бесперебойного питания проводят те, кто их продаёт. Вполне возможно, что покупая новый UPS, вы уже берёте себе настроенный под наши линии блок, характеристики которого отличаются от заявленных, потому что в сервис-центре фирмы-продавца над этим UPS-ом уже поработали. В случае, если вы берёте ИБП для запитки очень чувствительной к перемене напряжения электроники, вам нужно обязательно узнать, соответствует ли источник заявленным данным. Обычно, если сказать, что в случае, если что не так, то продавец будет нести ответственность за всё, они сами признаются, ковырялись в нём, или нет. Ну а напоследок хочется пожелать вам надёжного электроснабжения и качественных UPS-ов.