📄 可编程间隔定时器.htm
字号:
<TD><FONT face=Tahoma>2</FONT></TD>
<TD width=185><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">速率发生器</SPAN></TD></TR>
<TR>
<TD><FONT face=Tahoma>3</FONT></TD>
<TD width=185><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">方波模式</SPAN></TD></TR>
<TR>
<TD><FONT face=Tahoma>4</FONT></TD>
<TD width=185><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">软件门</SPAN></TD></TR>
<TR>
<TD><FONT face=Tahoma>5</FONT></TD>
<TD width=185><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">硬件门</SPAN></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><B><SPAN
lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">8253</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">和</SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">8254</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">芯片位于</SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">0x43</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">的指令寄存器的位定义</SPAN></B><FONT
face=Tahoma> </FONT>
<P><SPAN style="FONT-FAMILY: Tahoma">要设置通道</SPAN><FONT face=Tahoma><SPAN
lang=EN-US>0</SPAN></FONT><SPAN
style="FONT-FAMILY: Tahoma">的数据寄存器,我们先需要选择计数器</SPAN><FONT face=Tahoma><SPAN
lang=EN-US>0</SPAN></FONT><SPAN
style="FONT-FAMILY: Tahoma">和指令寄存器的一些模式。我们想要写入数据寄存器的除数值是一个</SPAN><FONT
face=Tahoma><SPAN lang=EN-US>16</SPAN></FONT><SPAN
style="FONT-FAMILY: Tahoma">位的值,所以我们需要传输</SPAN><FONT face=Tahoma><SPAN
lang=EN-US>MSB</SPAN></FONT><SPAN
style="FONT-FAMILY: Tahoma">(最大有效字节)和</SPAN><FONT face=Tahoma><SPAN
lang=EN-US>LSB</SPAN></FONT><SPAN
style="FONT-FAMILY: Tahoma">(最小有效字节)到数据寄存器。这是一个</SPAN><FONT face=Tahoma><SPAN
lang=EN-US>16</SPAN></FONT><SPAN
style="FONT-FAMILY: Tahoma">位的值,我们并不是以</SPAN><FONT face=Tahoma><SPAN
lang=EN-US>BCD</SPAN></FONT><SPAN
style="FONT-FAMILY: Tahoma">(十进制数的二进制编码)的形式传送数据,所以</SPAN><FONT face=Tahoma><SPAN
lang=EN-US>BCD</SPAN></FONT><SPAN style="FONT-FAMILY: Tahoma">域应该设置为</SPAN><FONT
face=Tahoma><SPAN lang=EN-US>0</SPAN></FONT><SPAN
style="FONT-FAMILY: Tahoma">。最后,我们想要产生一个方波:模式</SPAN><FONT face=Tahoma><SPAN
lang=EN-US>3</SPAN></FONT><SPAN
style="FONT-FAMILY: Tahoma">。我们应该设置到指令寄存器的合成字节是</SPAN><FONT face=Tahoma><SPAN
lang=EN-US>0x36</SPAN></FONT><SPAN
style="FONT-FAMILY: Tahoma">。前两段和表可以总结到这个函数中。你可以使用它,但是在本指南中不这样用,这样过于简单了。为了精确和简单地保持时间,我建议在实际内核中设置为</SPAN><FONT
face=Tahoma><SPAN lang=EN-US>100Hz</SPAN></FONT><SPAN
style="FONT-FAMILY: Tahoma">。</SPAN></P>
<TABLE id=table4 style="BORDER-COLLAPSE: collapse" width="100%" border=1>
<TBODY>
<TR>
<TD><FONT color=#800000 size=2>void timer_phase(int
hz)<BR>{<BR> int divisor = 1193180 / hz; /* 计算我们的除数。
*/<BR> outportb(0x43, 0x36); /* 设置我们的指令字节x36。
*/<BR> outportb(0x40, divisor & 0xFF); /*
设置除数的低字节。*/<BR> outportb(0x40, divisor >> 8); /*
设置除数的高字节。*/<BR>}</FONT></TD></TR>
<TR>
<TD><B><FONT size=2>不错吧?呵呵。</FONT></B></TD></TR></TBODY></TABLE>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">创建名为“</SPAN><SPAN
lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">timer.c</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”的文件,就想本指南的前面章节提到的一样把它加入你的“</SPAN><SPAN
lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">build.bat</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”。如果你分析下面的代码,你就会发现我们记录了计时器所激发的嘀哒数。这在你的内核变得复杂的时候可以作为“系统正常运行时间计数”。这里的时钟中断简单地使用默认值</SPAN><SPAN
lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">18.222Hz</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">来计算什么时候应该显示一段简单的信息:“一秒已经过去”,并且每秒都显示一次。如果你决定在你的代码中使用“</SPAN><SPAN
lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">timer_phase</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”函数,你应该将“</SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">timer_handler</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”中的“</SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">timer_ticks % 18 == 0</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”行改为“</SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">timer_ticks % 100 == 0</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”。你可以在内核中的任何函数里设置计时器相位,但是我建议在“</SPAN><SPAN
lang=EN-US
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">'timer_install'</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”里设置它,这样做让代码更有组织。</SPAN></P>
<TABLE id=table5 style="BORDER-COLLAPSE: collapse" width="100%" border=1>
<TBODY>
<TR>
<TD><FONT color=#800000 size=2>#include < system.h ><BR> <BR>/*
这将记录系统运行已经产生了多少次嘀哒 */<BR>int timer_ticks = 0;<BR> <BR>/*
处理计时器。在本例中,这非常简单:每当计时器激活时,我们就让变量<BR>*
“timer_ticks”加1。默认情况下,计时器每秒激活18.222次。谁<BR>*
也说不清楚为什么会是18.222Hz。<BR>*/<BR>void timer_handler(struct regs
*r)<BR>{<BR> /* 增加我们的“嘀哒计数”。 */<BR>
timer_ticks++;<BR> <BR> /*
每18个时钟周期(大约是1秒),我们就在屏幕上显示一段信息。 */<BR> if (timer_ticks %
18 == 0)<BR> {<BR> puts("One second
has passed\n");<BR> }<BR>}<BR> <BR>/*
安装计时器处理程序到IRQ0,设置系统时钟。 */<BR>void
timer_install()<BR>{<BR> /* 安装“timer_handler”到IRQ0。
*/<BR> irq_install_handler(0,
timer_handler);<BR>}</FONT></TD></TR>
<TR>
<TD><B><FONT face=Tahoma
size=2>使用系统计时器的例子:“timer.c”</FONT></B></TD></TR></TBODY></TABLE>
<P> </P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">记住把“</SPAN><SPAN
lang=EN-US
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">timer_install</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”添加到“</SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">main.c</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”的“</SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">main</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”函数中。有问题?记住把“</SPAN><SPAN
lang=EN-US
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">timer_install</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”的原型添加到“</SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">system.h</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”!下面的代码是进一步的示例,说明你可以用系统计时器做什么。如果你仔细地看,这个简单的函数不断循环,直到经过“</SPAN><SPAN
lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">ticks</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”时间或计时器相位。这几乎与</SPAN><SPAN
lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">C</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">函数库中的函数“</SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">delay</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">”相同,只取决于你设置的计时器相位:</SPAN></P>
<TABLE id=table6 style="BORDER-COLLAPSE: collapse" width="100%" border=1>
<TBODY>
<TR>
<TD><FONT color=#800000 size=2>/* 这将不断地循环直至到达给定的时间。 */<BR>void
timer_wait(int ticks)<BR>{<BR> unsigned long
eticks;<BR> <BR> eticks = timer_ticks
+ ticks;<BR> while(timer_ticks <
eticks);<BR>}</FONT></TD></TR>
<TR>
<TD><B><SPAN style="FONT-FAMILY: Tahoma"><FONT
size=2>如果你愿意,可以把它添加到“</FONT></SPAN><FONT size=2><FONT face=Tahoma><SPAN
lang=EN-US>timer.c</SPAN></FONT><SPAN
style="FONT-FAMILY: Tahoma">”,并在“</SPAN><FONT face=Tahoma><SPAN
lang=EN-US>system.h</SPAN></FONT></FONT><SPAN
style="FONT-FAMILY: Tahoma"><FONT
size=2>”里添加原型</FONT></SPAN></B></TD></TR></TBODY></TABLE>
<DIV style="TEXT-ALIGN: left"><PRE style="FONT-SIZE: 10pt; MARGIN: 0cm 0cm 0pt; FONT-FAMILY: Courier New"> </PRE></DIV>
<P><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">下一步,我们将讨论如何使用键盘。这涉及到在硬件</SPAN><SPAN
lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">I/O </SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">上为每个中断安装一个定制的</SPAN><SPAN
lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">IRQ</SPAN><SPAN
style="FONT-SIZE: 12pt; FONT-FAMILY: Tahoma">处理程序。</SPAN></P>
<TABLE cols=150 width="100%">
<TBODY>
<TR>
<TD align=left width=150><FONT face=Tahoma><A
href="http://rammaker.cosoft.org.cn/store/bkerndev_zh_CN_beta/Docs/irqs.htm"><<
中断请求和可编程中断控制器</A> </FONT></TD>
<TD align=middle width=*><FONT face=Tahoma><A
href="mailto:friesenb@gmail.com">联系 Brandon F.</A> </FONT></TD>
<TD align=right width=150><FONT face=Tahoma><A
href="http://rammaker.cosoft.org.cn/store/bkerndev_zh_CN_beta/Docs/keyboard.htm">键盘
>></A> </FONT></TD></TR></TBODY></TABLE></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -