This sample read and show the system date and time from the CMOS. The program will terminate when user press any key from the key board.
timer.h
#ifndef TIMER_H #define TIMER_H #define SecIndex 0 #define AlarmSecIndex 1 #define MinIndex 2 #define AlarmMinIndex 3 #define HourIndex 4 #define AlarmHourIndex 5 #define DayIndex 7 #define MonthIndex 8 #define YearIndex 9 struct Time { unsigned char sec; unsigned char min; unsigned char hr; }; struct Date { unsigned long year; unsigned char month; unsigned char day; }; void readTime(struct Time *getTime); void readDate(struct Date *getDate); unsigned char readCmos(unsigned char _cmosIndex); unsigned char BCDtoInt(unsigned char BCDNum); void wait(); #endiftimer.c
#include "timer.h" void readTime(struct Time *getTime) { getTime->sec = readCmos(SecIndex); getTime->min = readCmos(MinIndex); getTime->hr = readCmos(HourIndex); } void readDate(struct Date *getDate) { getDate->year = readCmos(YearIndex); getDate->month = readCmos(MonthIndex); getDate->day = readCmos(DayIndex); } unsigned char readCmos(unsigned char _cmosIndex) { unsigned char _getByte,UIP; UIP = 1; /* Status Register A (Hex 00A) +--------------------------------------------------------+ | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |------+--------------+-------+--------------------------| | UIP | SDIV | BC | Rate | +--------------------------------------------------------+ UIP: Update in progress SDIV: Select divider BC: Bank control */ /* When the UIP bit is 1, an update is in progress. When it is set to 0, the current date and time can be read. */ while(UIP) { _asm { mov al, 0ah out 70h, al out 0edh, al ;delay a moment to avoid the error. in al, 71h test al, 80h jz Set jmp Exit Set: mov UIP, 0 Exit: }; } _asm { mov al, _cmosIndex out 70h, al ;output the index to the index port. out 0edh, al ;delay a moment to avoid the error. in al, 71h ;read the data from the cmos data port. mov _getByte, al }; return _getByte; } void writeCmos(unsigned char _cmosIndex,unsigned char _byteData) { _asm { mov al, _cmosIndex out 70h, al ;output the index to the index port. out 0edh, al ;this is used to delay a moment to avoid the error. mov al, _byteData out 71h, al ;write the data to the cmos through the data port. } } unsigned char BCDtoInt(unsigned char BCDNum) { unsigned char intNum; intNum = ((BCDNum >> 4) * 10) + (BCDNum & 0x0f); return intNum; } unsigned char intToBCD(unsigned char intNum) { unsigned BCDNum; BCDNum = ((intNum / 10) << 4) + (intNum % 10); return BCDNum; } void wait() { struct Time currentTime, nextTime; readTime(¤tTime); readTime(&nextTime); while(nextTime.sec == currentTime.sec) readTime(&nextTime); }main.c
#include "timer.h" #include <stdio.h> #include <stdlib.h> int main() { struct Time cmosTime; struct Date cmosDate; char _keyin = 0; readDate(&cmosDate); readTime(&cmosTime); printf("20%02d/%02d/%02d %02d:%02d:%02d\n",\ BCDtoInt(cmosDate.year),BCDtoInt(cmosDate.month),BCDtoInt(cmosDate.day),BCDtoInt(cmosTime.hr),\ BCDtoInt(cmosTime.min),BCDtoInt(cmosTime.sec)); while(1) { wait(); system("cls"); readDate(&cmosDate); readTime(&cmosTime); printf("CMOS Time: 20%02d/%02d/%02d %02d:%02d:%02d\n",\ BCDtoInt(cmosDate.year),BCDtoInt(cmosDate.month),BCDtoInt(cmosDate.day),BCDtoInt(cmosTime.hr),\ BCDtoInt(cmosTime.min),BCDtoInt(cmosTime.sec)); printf("Press Any Key to Exit\n"); //detect keyboard _asm { mov ah, 06h mov dl, -1 int 21h; maybe this interrupt will not available in the future. mov _keyin, al } if(_keyin) break; } return 0; }
Fig.1 Execution Result |
Note: you can read CMOS through 70,71,72 and 73 (72, 73's content may same as 70, 71's, it's depend on your system BIOS) port.
Reference:
1. Open Watcom Download
2. Open Watcom C/C++ User's Guide
3. CMOS Registers
沒有留言:
張貼留言