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();
#endif
timer.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

沒有留言:
張貼留言