[Назад] [Далее]

5.10.7. Часы реального времени и CMOS-память

В каждом компьютере есть микросхема, отвечающая за поддержку текущей даты и времени. Для того чтобы они не сбрасывались при каждом выключении питания, на микросхеме расположена небольшая область памяти (от 64 до 128 байт), выполненная по технологии CMOS, позволяющей снизить энергопотребление до минимума (фактически энергия в таких схемах затрачивается только на зарядку паразитных емкостей при изменении состояния ячеек памяти). Вся эта микросхема получает питание от аккумулятора, расположенного на материнской плате, и не отключается при. выключении компьютера. Для хранения собственно времени достаточно всего четырнадцати байт такой энергонезависимой памяти, и остальная ее часть используется BIOS для хранения различной информации, необходимой для корректного запуска компьютера. Для общения с CMOS и регистрами RTC выделяются порты ввода-вывода от 70h до 7Fh, но только назначение портов 70h и 71h одинаково для всех материнских плат:

После записи в порт 70h обязательно надо выполнить запись или чтение из порта 71h, иначе RTC окажется в неопределенном состоянии. Содержимое регистров CMOS варьируется для разных BIOS, но первые 33h регистра обычно выполняют следующие функции:

Данные о конфигурации, хранящиеся в защищенной контрольной суммой области, бывают нужны достаточно редко, а для простых операций с часами реального времени и будильником удобно использовать прерывание BIOS 1Ah. Однако, программируя RTC на уровне портов, можно активизировать периодическое прерывание — режим, в котором RTC вызывает прерывание IRQ8 с заданной частотой, что позволит оставить IRQ0 для работы системы, если вас удовлетворяет ограниченный выбор частот периодического прерывания. В качестве примера посмотрим, как выполняются чтение и запись в CMOS-память.

; rtctime,asm
; Вывод на экран текущей даты и времени из RTC
;
        .model     tiny
        .code
        .186                            ; для shr al,4
        org        100h                 ; СОМ-программа
start:
        mov        al,0Bh               ; CMOS OBh - управляющий регистр В
        out        70h,al               ; порт 70h - индекс CMOS
        in         al,71h               ; порт 71h - данные CMOS
        and        al,11111011b         ; обнулить бит 2 (форма чисел - BCD)
        out        71h,al               ; и записать обратно
        mov        al,32h               ; CMOS 32h - две старшие цифры года
        call       print_cmos           ; вывод на экран
        mov        al,9                 ; CMOS 09h - две младшие цифры года
        call       print_cmos
        mov        al,'-'               ; минус
        int        29h                  ; вывод на экран
        mov        al,8                 ; CMOS 08h - текущий месяц
        call       print_cmos
        mov        al,'-'               ; еще один минус
        int        29h
        mov        al,7                 ; CMOS 07h - день
        call       print_cmos
        mov        al,' '               ; пробел
        int        29h
        mov        al,4                 ; CMOS 04h - час
        call       print_cmos
        mov        al,'h'               ; буква "h"
        int        29h
        mov        al,' '               ; пробел
        int        29h
        mov        al,2                 ; CMOS 02h - минута
        call       print_cmos
        mov        al,':'               ; двоеточие
        int        29h
        mov        al,0h                ; CMOS 00h - секунда
        call       print_cmos
        ret

; процедура print_cmos
; выводит на экран содержимое ячейки CMOS с номером в AL
; считает, что число, читаемое из CMOS, находится в формате BCD
print_cmos proc near
        out        70h,al               ; послать AL в индексный порт CMOS
        in         al,71h               ; прочитать данные
        push       ax
        shr        al,4                 ; выделить старшие четыре бита
        add        al,'0'               ; добавить ASCII-код цифры 0
        int        29h                  ; вывести на экран
        pop        ax
        and        al,0Fh               ; выделить младшие четыре бита
        add        al,30h               ; добавить ASCII-код цифры 0
        int        29h                  ; вывести на экран
        ret
print_cmos endp
        end        start

п»ї
"target=_blank><\/a>") //-->