Цитата(evgen2 @ Dec 2 2015, 11:11)

Продвинутый школьник может написать только гуано и первое во что он упрется - "как поспать N секунд".
Ну прямо так и только
Вот делал много лет назад для своего первого ПЛК на АВР!
Сорри за многобукав, но чтоб было понятно...
RTCS – Real time Sheduler
Данный модуль позволяет задать до 16 событий с заданной длительностью от 1сек до нескольких лет! По наступлению события, устанавливается соотв. бит в регистре статуса.
Параметры задания находятся в энергонезависимой части ПГП, поэтому не стираются при выключении питания, как и часы реального времени.
Выдержка времени может быть задана как в абсолютном выражении (сек.мин.часы и т.д.)
так и относительно т.е. можно задать через сколько секунд, минут, часов или дней относительно текущего времени и даты, должно наступить событие. Это удобно например, для задания каких-либо сроков годности или сроков техобслуживания.
Время рассчитывается с учетом високосных лет и кол-ва дней в месяце.
Для работы RTCS необходимо задать текущее время и дату:
Например так
DATETIME[0]=10;DATETIME[1]=20;DATETIME[2]=10; //задаем сек,мин, часы соотв.
DATETIME[3]=29;DATETIME[4]=12;DATETIME[5]=12; //задаем день, месяц, год соотв.
blockwrite(RTC_DateTime,DATETIME); //задать время во внутренних часах
Для задания только времени можно использовать параметр RTC_Time, только даты - RTC_Date. Массив при этом состоит только из 3х элементов.
out (RTCS_Addr,15); //Задаем стартовый адрес в ПГП.
Внимание! Если адрес не задан, то считается равным 0!
Теперь можно задавать времена наступления событий:
blockwrite(RTCS_SetAbs,0,52,20,15,9,12);
В этом случае время события №1 задается абсолютно, а именно, сработает в 20часов 52мин 00сек 15сентября 2012года.
Если данные по событию представлены в виде массива из 6 элементов, то можно использовать параметр - RTCS_SetArr.
blockwrite(RTCS_SetArr,AlarmArray);
Если в условии задачи сказано, что событие должно наступить через N дней, то удобнее задавать относительным методом.
Например, зададим событие №2 на сработку через 10 дней:
blockwrite(RTCS_DayRel+1,10);
Сработка произойдет ровно в то же время, равное текущему, но через 10 дней.
Аналогично задаются:
RTCS_SecRel – секунды
RTCS_MinRel – минуты
RTCS_HrsRel – часы
Диапазон чисел (1-65535)
Данные события считаются наступившими, если текущая дата или время, более поздние, чем установлены. Но если нужна сработка только по совпадению дат и времени? Система позволяет это сделать!
Можно задать такой тип события, которое будет выполнятся циклически.
Например, нужно что-то включать каждые сутки в определенное время:
blockwrite(RTCSE_SetAbs,sec,min,hrs,0xff, 0xff,0xff,0xff);
Здесь мы задали событие во время sec,min,hrs, а остальные параметры нам неважны
По наступлению события, мы сбрасываем его флаг, и делаем паузу, хотябы на 1 сек, чтобы флаг события не взвелся вновь. После этого, следуюшее событие наступит ровно в эти же час минуту и секунду, как задано.
Аналогичным образом устанавливаются относительные интервалы времени.
Например: blockwrite(RTCSE_DayRel,10);
Запись «RTCS_DayRel+1» означает, что мы задаем событие №2
Например, событие №5 будет задано как «RTCS_DayRel+4»
Аналогично выбирается номер события в абсолютном и других относительных методах.
После задания всех событий, нужно разрешить работу обработчика:
out (RTCS_Enable,0b0000000000000011); //разрешили работу первых 2х событий, остальные не обрабатываются. Как видно, можно задавать опрос только тех событий, бит которых =1.
Чтение текущего времени осуществляется аналогично записи, с использованием параметров RTC_Time, RTC_Date или RTC_DateTime.
blockread(RTC_Time,TIME); //read sec[0] min[1] hour[2]
blockread(RTC_Date,DATE); //read day[0] month[1] year[2]
Чтение статуса RTCS производится так: res=in(RTCS_Status);
получаем 16бит, где 0й бит соответствует первому событию 15й- шестнадцатому. Если бит=1 событие произошло.
Сбросить статус можно заданием новой уставки по событию, при этом бит статуса соотв. номеру события, стирается. Если задано время которое уже является прошедшим по сравнению с текущим, то бит будет снова установлен.
По наступлению события можно задать системное прерывание:
SEI (RTCS_IntrVect);
ВНИМАНИЕ! Если в одну секунду происходит сработка сразу нескольких событий, прерывание будет вызвано ОДНО, общее для них.