bit [6:7] 准备对那个定时器通道进行操作,timer0 or timer1 or timer2
bit [4:5] 读/写当前计数值
00:读当前计数值,先读低8位,后读高8位,要两次in指令
01:只写高8位,一次out指令
10:只写低8位,一次out指令
11:先写低8位,后写高8位,要两次out指令
bit [1:3] 工作模式,有6种工作模式,其中模式0(000)为计数结束后产生中断;
模式3(003)为方波频率发声器,这两种模式后面要用
bit 0 写入值得格式,0--二进制格式,1--BCD码格式
011 #define IRQ0 0x8 // 8254 time interrupt
012 #define IRQ8 0x70 // Real time interrupt
013 #define PIT0 0x40 // 8254 timer0
014 #define PITMODE 0x43 // 8254 control word
/* 8254 controll word
bit 7:6 timer number 00--timer0 01--timer1 10--timer2
bit 5:4 latch,read format;
00--latch current count;
01--write low byte(no latching);
10--write high byte(no latching);
11--write low,then high byte
bit 3:1 mode number;
000--interrupt on terminal count;
001--programmable one-shot;
010--rate generator
011--sequare wave generator;
100--software triggered strobe;
101--hardware triggered strobe
bit 0 count byte; 0--binary 1--bcd
*/
015 #define IMR0 0x21 // IMR of 8259-0
016 #define IMR1 0xa1 // IMR of 8259-1
017 #define RTC_ADDR 0x70
018 #define RTC_DATA 0x71
019 #define PITCONST 1193180L // Frequence of 8254
020 #define PIT0DEF 18.2067597 // ticks per sec of previous int
021 #define RT_MS_PER_TICK 0.9765625
022 #define NEW8H 1 // flag. new int 8h valiable.
023 static float tick_per_ms = 0.0182068; // ticks per ms
024 static float ms_per_tick = 54.9246551; // interval between two ticks
025 static float freq8h = 18.2067597; // frequency of system timer
026 static unsigned char flag8h = 0;
027 static _go32_dpmi_seginfo old_handler_8h, new_handler_8h;
028 static _go32_dpmi_seginfo old_handler_70h, new_handler_70h;
029 static _go32_dpmi_registers r;
030 unsigned long int ticks_8h = 0;
031 unsigned long int ticks_70h = 0;
/***********************************************
* New int 8h initialization
* It chains int routine of protected mode and
* real mode
***********************************************/
032 void pctimer_init(unsigned int Hz) {
033 unsigned int pit0_set, pit0_value;
034 if (flag8h != NEW8H) { // Current int 8h is old.
035 disable(); // Disable interrupts
036 lock_pm_new8h(); // Lock int routine in protected mode
037 lock_pm_new70h(); // Lock int routine in protected mode
// Lock some var that will be used in int routine
038 _go32_dpmi_lock_data(&ticks_8h, sizeof(ticks_8h));
039 _go32_dpmi_lock_data(&ticks_70h, sizeof(ticks_70h));
040 _go32_dpmi_lock_data(&r, sizeof(r));
// Get the previous int routine in protected mode
// and chain a new routine
041 _go32_dpmi_get_protected_mode_interrupt_vector(IRQ0, &old_handler_8h);
042 new_handler_8h.pm_offset = (int)pm_new8h;
043 new_handler_8h.pm_selector = _go32_my_cs();
044 _go32_dpmi_chain_protected_mode_interrupt_vector(IRQ0, &new_handler_8h);
045 _go32_dpmi_get_protected_mode_interrupt_vector(IRQ8, &old_handler_70h);
046 new_handler_70h.pm_offset = (int)pm_new70h;
047 new_handler_70h.pm_selector = _go32_my_cs();
048 _go32_dpmi_allocate_iret_wrapper(&new_handler_70h);
049 _go32_dpmi_set_protected_mode_interrupt_vector(IRQ8, &new_handler_70h);
// initial RTC
050 outportb(RTC_ADDR, 0x0b);
051 outportb(RTC_DATA, 0x42);
// initial 8259-2
052 outportb(IMR1, 0x0c);
// initial Timer0 of 8254
053 outportb(PITMODE, 0x36); // 8254 command register
// 00110110b.timer0,write low and high
// sequare wave generator,binary
054 pit0_value = PITCONST / Hz;
055 pit0_set = (pit0_value & 0x00ff);
056 outportb (PIT0, pit0_set);
057 pit0_set = (pit0_value >> 8);
058 outportb (PIT0, pit0_set);
059 // initial vars for int
060 ticks_8h = 0;
061 flag8h = NEW8H; // new int 8h
062 freq8h = Hz; // frequence of new int
063 tick_per_ms = freq8h / 1000; // ticks per ms
064 ms_per_tick = 1000 / freq8h; // ms of per tick
065 enable(); // enable interrupts
066 }
067 }
068 void pctimer_exit(void) {
069 unsigned int pit0_set, pit0_value;
070 unsigned long tick;
071 char *cmostime;
134 return(buff);
135 }
// Main program
136 int main(void) {
137 int i;
138 unsigned long int start, finish;
139 int elapsedtime[20];
140 float average_error, sum = 0;
141 printf("Press any key to begin the test. ");
142 printf("(It lasts for 20 seconds.)\n\n");
143 getch();
144 printf("Test in progress. Please wait...\n");
145 pctimer_init(1000); // 1000Hz, 1000 ticks per sec
146 for (i = 0; i < 10; i++) {
147 start = ticks_70h;
148 pctimer_sleep(1000);
149 finish = ticks_70h;
150 elapsedtime = (int)(finish - start);
151 }
152 pctimer_exit();
153 printf("Test finished.\n");
154 printf("Press any key to display the result...\n");
155 getch();
156 for (i = 0; i < 10; i++) {
157 sum += (float)((elapsedtime - 1024) * RT_MS_PER_TICK);
158 printf("iteration:%2d expected:1024 observed:%d difference:%d\n",
i + 1, elapsedtime, elapsedtime - 1024);
159 }
160 average_error = (float)sum / 10;
161 printf("\ntotal error:%.2f ms average error:%.2f ms\n",
sum, average_error);
162 return 0;
163 }