Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Аппаратное обеспечение IBM PC

© Александр Фролов, Григорий Фролов
Том 2, книга 1, М.: Диалог-МИФИ, 1992.

[Назад] [Содеожание] [Дальше]

4.7. Использование часов реального времени

Вы можете использовать часы реального времени для решения двух задач. Во-первых, часы позволяют определить текущую дату и время с точностью до секунды. Во-вторых, будильник можно использовать для выполнения каких-либо действий в заданное время или периодически.

Так как установленное время срабатывания будильника хранится в КМОП-памяти, питающейся от аккумулятора, будильник не будет сброшен при случайном выключении компьютера.

Для работы с часами реального времени мы подготовили следующую функцию:

/**
*.Name         timer
*.Title        Работа с часами реального времени
*
*.Descr        Эта функция предназначена для обслуживания
*              системных часов реального времени через
*              прерывание INT 1Ah.
*
*.Proto        int timer(char fn, SYSTIMER *tm)
*
*.Params       char     fn - выполняемая функция:
*
*              RTC_GET_TIME      - прочитать показания часов;
*              RTC_SET_TIME      - установить часы;
*              RTC_GET_DATE      - прочитать дату;
*              RTC_SET_DATE      - установить дату;
*              RTC_SET_ALARM     - установить будильник;
*              RTC_CLEAR_ALARM   - сбросить будильник.
*
*                 Все эти константы описаны в файле sysp.h
*
*              SYSTIMER tm - структура, содержащая данные
*                            для установки часов или
*                            показания часов:
*
*              typedef struct _SYSTIMER_ {
*
*                 char hour;     // часы
*                 char min;      // минуты
*                 char sec;      // секунды
*                 unsigned year; // год
*                 char month;    // месяц
*                 char day;      // число
*                 char daylight_savings; // флаг
*                                       // использование
*                        // летнего времени
*                        // (для включения режима
*                        // должен быть равен 1)
*
*              } SYSTIMER;
*
*.Return       0   - успешное выполнение функции;
*              -1  - часы реального времени отсутствуют
*                    в компьютере;
*
*.Sample       setalarm.c
**/

#include <stdio.h>
#include <dos.h>
#include "sysp.h"

union REGS reg;

int timer(char fn, SYSTIMER *tm) {

        reg.h.ah = fn;

        switch (fn) {

                case RTC_SET_TIME:

                        reg.h.ch = tm->hour;
                        reg.h.cl = tm->min;
                        reg.h.dh = tm->sec;
                        reg.h.dl = tm->daylight_savings;

                        break;

                case RTC_SET_DATE:

                        reg.x.cx = tm->year;
                        reg.h.dh = tm->month;
                        reg.h.dl = tm->day;

                        break;

                case RTC_SET_ALARM:

                        reg.h.ch = tm->hour;
                        reg.h.cl = tm->min;
                        reg.h.dh = tm->sec;

                        break;

        }

        int86(0x1a,&reg,&reg);

        if(reg.x.cflag == 1) return(-1);

        switch (fn) {

                case RTC_GET_TIME:

                        tm->hour = reg.h.ch;
                        tm->min = reg.h.cl;
                        tm->sec = reg.h.dh;

                        break;

                case RTC_GET_DATE:

                        tm->year = reg.x.cx;
                        tm->month = reg.h.dh;
                        tm->day = reg.h.dl;

                        break;
        }

        return(0);
}



Эта функция выполняет все виды обслуживания часов реального времени, которые поддерживаются BIOS.

Для иллюстрации основных приемов работы с часами мы подготовили программу, которая выводит на экран текущие дату и время. Затем устанавливается будильник. Он должен сработать через одну минуту и подать звуковой сигнал.

Перед установкой будильника программа подключает свой обработчик прерывания 4Ah. Это прерывание вызывается при срабатывании будильника. Перед завершением работы программа сбрасывает будильник и восстанавливает вектор прерывания 4Ah.

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include "sysp.h"

// Выключаем проверку стека и указателей

#pragma check_stack( off )
#pragma check_pointer( off )

// Макро для выдачи звукового сигнала

#define BEEP() _asm { \
        _asm mov bx,0 \
        _asm mov ax, 0E07h \
        _asm int 10h \
}

void main(void);

// Описание программы-обработчика прерывания
// будильника

void _interrupt _far alarm(void);

// Переменная для хранения старого
// вектора будильника

void (_interrupt _far *old_4a)(void);


void main(void) {

char *month_to_text[] = {

        "январь",
        "февраль",
        "март",
        "апрель",
        "май",
        "июнь",
        "июль",
        "август",
        "сентябрь",
        "октябрь",
        "ноябрь",
        "декабрь"

};

SYSTIMER tmr;

// Определяем текущие дату и время

        timer(RTC_GET_DATE, &tmr);
        timer(RTC_GET_TIME, &tmr);

// Выводим дату и время на экран

        printf("\nСейчас %d год, %s, %d число."
                 "\n",
                 bcd2bin(&(tmr.year)),
                 month_to_text[bcd1bin(&(tmr.month)) - 1],
                 bcd1bin(&(tmr.day)));

        printf("\nВремя - %02.2d:%02.2d:%02.2d"
                 "\n",
                 bcd1bin(&(tmr.hour)),
                 bcd1bin(&(tmr.min)),
                 bcd1bin(&(tmr.sec)));

// Для установки будильника увеличиваем
// счетчик минут на единицу. Для упрощения
// программы мы не проверяем счетчик на
// переполнение, поэтому если текущее
// значение счетчика минут равно 59,
// будильник не сработает. Вы можете сами
// немного усовершенствовать программу для
// проверки переполнения.

        bin1bcd(bcd1bin(&(tmr.min)) + 1,
                                                 &(tmr.min));

// Выводим на экран время, когда сработает
// будильник.

        printf("\nВремя срабатывания будильника"
                                "- %02.2d:%02.2d:%02.2d"
                 "\n",
                 bcd1bin(&(tmr.hour)),
                 bcd1bin(&(tmr.min)),
                 bcd1bin(&(tmr.sec)));

// Подключаем свой обработчик прерывания
// будильника, старое значение вектора
// 0x4a сохраняем

        old_4a = _dos_getvect(0x4a);

        _dos_setvect(0x4a, alarm);

// Устанавливаем будильник

        timer(RTC_SET_ALARM, &tmr);

        printf("\nБудильник установлен. Для отмены "
                         "и завершения программы нажмите"
                         "\nлюбую клавишу...");

        getch();

// Сбрасываем будильник и восстанавливаем
// вектор прерывания будильника

        timer(RTC_CLEAR_ALARM, &tmr);

        _dos_setvect(0x4a, old_4a);

        exit(0);
}

// ----------------------------------
// Преобразование однобайтового
// числа из формата BCD в двоичный
// формат.
// ----------------------------------

int bcd1bin(char *bcd) {

        return( ((*bcd) & 0x0f) +
                  10 * (((*bcd) & 0xf0) >> 4) );

}

// ----------------------------------
// Преобразование двухбайтового
// числа из формата BCD в двоичный
// формат.
// ----------------------------------

int bcd2bin(char *bcd) {

        return( bcd1bin(bcd) + 
                        100 * bcd1bin(bcd + 1) );

}

// ----------------------------------
// Преобразование однобайтового
// числа из двоичного формата
// формат BCD.
// ----------------------------------

int bin1bcd(int bin, char *bcd) {

        int i;

        i = bin / 10;

        *bcd = (i << 4) + (bin - (i * 10));

}

// ----------------------------------
// Программа получает управление
// при срабатывании будильника.
// Ее назначение - выдать звуковой сигнал.
// ----------------------------------

void _interrupt _far alarm(void) {

        BEEP();
        BEEP();
        BEEP();
        BEEP();
        BEEP();
        BEEP();
        BEEP();

}


[Назад] [Содеожание] [Дальше]