Работа с часами реального времени
Пользователи, просматривающие топик: none
|
Зашли как: Guest
|
Имя |
Сообщение |
<< Старые топики Новые топики >> |
|
|
Работа с часами реального времени - 2007-10-27 03:45:21.290000
|
|
|
weak spirit
Сообщений: 56
Оценки: 0
Присоединился: 2007-09-30 18:40:25.726666
|
как правильно считать показания часов реального времени и задать время срабатывания будильника? пробовал через прерывания BIOS:
void GetTime(char *s, char *m, char *h) {
char sec, min, hour;
_asm {
mov ah, 0x02
int 0x1A
mov sec, dh
mov min, cl
mov hour, ch
}
(*s) = sec / 16 * 10 + sec % 10; //переводим значение из BCD в десятичное число
(*m) = min / 16 * 10 + min % 10;
(*h) = hour / 16 * 10 + hour % 10;
}
и напрямую через CMOS-память:
void WriteCMOS(int adr, int value) {
outp(0x70, adr);
outp(0x71, value);
}
void ReadCMOS(int adr, int &value) {
outp(0x70, adr);
value = inp(0x71);
}
void GetTimeByCMOS(int *s, int *m, int *h) {
int seс, min, hour;
ReadCMOS(0, sec);
ReadCMOS(2, min);
ReadCMOS(4, hour);
(*s) = sec / 16 * 10 + sec % 10;
(*m) = min / 16 * 10 + min % 10;
(*h) = hour / 16 * 10 + hour % 10;
}
в обоих случаях: во-первых время чуть-чуть отличалось от системного в винде (причём чем больше показания, тем больше и отличие), а во-вторых происходили скачки, например за 11-тью секундами следовали 18, а за 29-тью - 20. грешу на BCD числа (кто-нибудь знает как их грамотно переводить в десятичную систему и обратно?), но такие "скачки" времени всё равно остаются загадкой.
|
|
|
RE: Работа с часами реального времени - 2007-10-27 08:40:22.303333
|
|
|
JD_WERT
Сообщений: 117
Оценки: 0
Присоединился: 2007-07-12 06:59:16.613333
|
Попробуй так (это кусок из ядра, выбери то, что нужно):
#define BCD_INT(bcd) (((bcd & 0xF0) >> 4) * 10 + (bcd &0x0F))
BYTE _QueryCMOS(USHORT reg)
{
BYTE Result;
WRITE_PORT_UCHAR(0x70, reg | 0x80);
Result = READ_PORT_UCHAR(0x71);
WRITE_PORT_UCHAR(0x70, 0);
return Result;
}
BYTE hal::time::QueryCMOS(USHORT reg)
{
while(_QueryCMOS(0x0A) & 0x80);
return _QueryCMOS(reg);
}
void hal::time::getTime(TIME_FIELDS* Time)
{
Time->Second = BCD_INT(QueryCMOS(0));
Time->Minute = BCD_INT(QueryCMOS(2));
Time->Hour = BCD_INT(QueryCMOS(4));
Time->Weekday = BCD_INT(QueryCMOS(6));
Time->Day = BCD_INT(QueryCMOS(7));
Time->Month = BCD_INT(QueryCMOS(8));
Time->Year = BCD_INT(QueryCMOS(9));
if (Time->Year > 80) // Y2K :)
{
Time->Year += 1900;
}
else
{
Time->Year += 2000;
}
Time->Millisecond = 0;
}
|
|
|
RE: Работа с часами реального времени - 2007-10-27 17:10:38.443333
|
|
|
weak spirit
Сообщений: 56
Оценки: 0
Присоединился: 2007-09-30 18:40:25.726666
|
первая строчка, там где макрос перевода из BCD в INT очень помогла, спасибо. а может кто ещё подкинет обратный макрос или формулу (нужно для установки будильника)?
|
|
|
RE: Работа с часами реального времени - 2007-10-27 17:27:20.260000
|
|
|
rgo
Сообщений: 7170
Оценки: 281
Присоединился: 2004-09-25 05:14:25
|
quote:
ORIGINAL: weak spirit первая строчка, там где макрос перевода из BCD в INT очень помогла, спасибо. а может кто ещё подкинет обратный макрос или формулу (нужно для установки будильника)? ну а в гугле спросить на счёт binary coded decimal?
|
|
|
RE: Работа с часами реального времени - 2007-10-27 18:51:59.303333
|
|
|
weak spirit
Сообщений: 56
Оценки: 0
Присоединился: 2007-09-30 18:40:25.726666
|
quote:
ORIGINAL: rgo ну а в гугле спросить на счёт binary coded decimal? гугль - он как бабка на базаре: говорит много, а по теме совсем чуть-чуть. много написано про перевод в ASCII, какие-то общие советы по переводу в двоичный код, но то ли я туплю, то ли советы ни ахти. а в гугль я и так как на исповедь регулярно хожу.
|
|
|
RE: Работа с часами реального времени - 2007-10-27 19:46:20.163333
|
|
|
weak spirit
Сообщений: 56
Оценки: 0
Присоединился: 2007-09-30 18:40:25.726666
|
простой пример из гугля: функция перевода из двоичного числа в BCD
void bin1bcd(int bin, char *bcd) {
int i;
i = bin / 10;
(*bcd) = (i << 4) + (bin - (i * 10));
}
встраиваю эту функцию в свой код:
int d;
char b = 60;
d = BCD_INT(b); // макрос, описанный выше
printf("bcd -> dec\n");
printf("bcd = %d\ndec = %d\n\n", b, d);
bin1bcd(d, &b);
printf("dec -> bcd\n");
printf("dec = %d\nbcd = %d\n", d, b);
на экране получаю: quote:
bcd -> dec bcd = 60 dec = 42 dec -> bcd dec = 42 bcd = 66 вот вам и гугль…
|
|
|
RE: Работа с часами реального времени - 2007-10-27 20:29:46.306666
|
|
|
rgo
Сообщений: 7170
Оценки: 281
Присоединился: 2004-09-25 05:14:25
|
quote:
ORIGINAL: weak spirit простой пример из гугля: функция перевода из двоичного числа в BCD […] вот вам и гугль… это не "нам гугль", а тебе надо учиться читать. во-первых, неплохо было бы работая с bcd, понять что это за формат хранения чисел. во-вторых, читая код макроса и код вытащенной из гугля функции хотя бы попытаться понять как они работают. и, наконец, в-третьих: если ты уж нашёл эту функцию, описание к ней прочитать сложно? спорим что в этом описании написано что она int переводит в bcd, а не наоборот, как это делает приведённый макрос. update извиняюсь, но я не совсем в тему попал ;) объяснять, в чём моя ошибка долго и муторно. кто знает что есть бцд уже понял, кто не знает – пускай читает доки. я уж не буду их здесь цитировать. вкратце, дело в том, что 60 в bcd получиться не может. вот и глючит всё. воткни в формат хранения чисел, а затем пользуйся. зы. и макрос и функция рабочие. хотя я бы функцию несколько переписал бы: char bin1bcd(int bin) {
int hi, low;
hi = bin / 10;
low = bin % 10;
return (hi << 4) + low;
}
|
|
|
RE: Работа с часами реального времени - 2007-10-27 23:01:10.683333
|
|
|
weak spirit
Сообщений: 56
Оценки: 0
Присоединился: 2007-09-30 18:40:25.726666
|
quote:
ORIGINAL: rgo 60 в bcd получиться не может. вот и глючит всё. точно, это уже я туплю. спасибо за переписанную функцию, в той пытался разобраться, но как то очень уж по-ассемблерному непонятно она написана =)
|
|
|
RE: Работа с часами реального времени - 2007-12-13 18:47:37.736666
|
|
|
crbunny
Сообщений: 223
Оценки: 0
Присоединился: 2006-06-22 21:20:01
|
А зачем BIOS и BCD если есть GetTickCount и иже с ним (или я что-то прослушал)?
|
|
|
|
|