http://wiki.allegro.cc/AllegroExamples 以上是英文例子站点。
by Shawn Hargreaves,allegro的作者
目录: 1 Allegro 例子
1.1 exhello
1.2 exmem
1.3 expat
1.4 expal
1.5 exflame
1.6 exbuf
1.7 exflip
1.8 exfixed
1.9 exfont
1.10exmouse
1.11extimer
这个例子展示了如何使用时钟中断
可能会有一点小痛(麻烦),因为你必须锁住所有在你的中断中使用的内存。
在例子的第1个部分展示了基本的计时函数rest()的用法(相当于delay();)
在例子的第2个部分展示了如何使用3个频率不同的用户时钟
* This program demonstrates how to use the timer routines.
* These can be a bit of a pain, because you have to be sure
* you lock all the memory that is used inside your interrupt
* handlers. The first part of the example shows a basic use of
* timing using the blocking function rest(). The second part
* shows how to use three timers with different frequencies in
* a non blocking way.
*/
#include <allegro.h>
/* 这些变量应当用volatile声明,这样优化器就不会搞错了 */
volatile int x = 0;
volatile int y = 0;
volatile int z = 0;
/* 时钟中断句柄 */
void inc_x(void)
{
x++;
}
END_OF_FUNCTION(inc_x)
/* 时钟中断句柄 */
void inc_y(void)
{
y++;
}
END_OF_FUNCTION(inc_y)
/* 时钟中断句柄 */
void inc_z(void)
{
z++;
}
END_OF_FUNCTION(inc_z)
int main(void)
{
int c;
if (allegro_init() != 0)
return 1;
install_keyboard();
install_timer();
if (set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0) != 0) {
if (set_gfx_mode(GFX_SAFE, 320, 200, 0, 0) != 0) {
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("Unable to set any graphic mode/n%s/n", allegro_error);
return 1;
}
}
set_palette(desktop_palette);
clear_to_color(screen, makecol(255, 255, 255));
textprintf_centre_ex(screen, font, SCREEN_W/2, 8, makecol(0, 0, 0),
makecol(255, 255, 255), "Driver: %s",
timer_driver->name);
/* 使用rest()来延迟给定的时间(毫秒级) */
textprintf_centre_ex(screen, font, SCREEN_W/2, 48, makecol(0, 0, 0),
makecol(255, 255, 255), "Timing five seconds:");
for (c=1; c<=5; c++) {
textprintf_centre_ex(screen, font, SCREEN_W/2, 62+c*10,
makecol(0, 0, 0), makecol(255, 255, 255), "%d", c);
rest(1000);
}
textprintf_centre_ex(screen, font, SCREEN_W/2, 142, makecol(0, 0, 0),
makecol(255, 255, 255),
"Press a key to set up interrupts");
readkey();
/* 所有在时钟中断中使用的变量和函数都应该锁起来 */
LOCK_VARIABLE(x);
LOCK_VARIABLE(y);
LOCK_VARIABLE(z);
LOCK_FUNCTION(inc_x);
LOCK_FUNCTION(inc_y);
LOCK_FUNCTION(inc_z);
/* 速度可以由毫秒级的数字给定(在这里是1秒一次中断)*/
install_int(inc_x, 1000);
/* 或者使用每秒的节拍率(BPS) (在这里是每秒10拍) */
install_int_ex(inc_y, BPS_TO_TIMER(10));
/* 或者使用秒 (这里是10秒一个周期) */
install_int_ex(inc_z, SECS_TO_TIMER(10));
/* 这些中断在这里被激活... */
while (!keypressed())
textprintf_centre_ex(screen, font, SCREEN_W/2, 176, makecol(0, 0, 0),
makecol(255, 255, 255), "x=%d, y=%d, z=%d", x, y, z);
return 0;
}
END_OF_MAIN()
---------------------------------------------------------------------
1、volatile声明
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值(From Memory),而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
1) 并行设备的硬件寄存器(如:状态寄存器)
2) 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3) 多线程应用中被几个任务共享的变量
详细的可以访问http://blog.csdn.net/gaoteng1984/archive/2007/07/27/1711924.aspx
2、Allegro中的时钟中断
你的函数将被 Allegro 中断处理程序调用而不是被处理器直接调用, 所以它能够 按正常的 C 函数来写而不需要特别的包装. 然而, 你必须知道,它将在一个中断中 被调用,而这给你希望在函数中做的事增加了许多约束.它不能使用大数量的堆栈, 不能调用任何 DOS 例程和使用调用了 DOS 例程的 C 库函数, 而且它必须被很快 的执行.不要在时钟处理程序里写太多的复杂代码: 一个基本的规则是你应该设置 一些标志然后在你的主控制循环里来回应它们.
在象 djgpp 这样的保护模式环境里, 内存被虚拟化并可以向磁盘交换. 由于 DOS 的不可重入, 如果磁盘交换发生在中断处理程序内部,系统将痛苦的死机, 所以你 需要确认你锁住了所有时钟例程中触及的所有内存 (包括代码和数据). Allegro 将锁住它用的所有东西,但是你有责任锁住你自己处理程序的. 宏 LOCK_VARIABLE (变量), END_OF_FUNCTION(函数名), 和 LOCK_FUNCTION(函数名) 可以被用来简化 这项任务.例如, 你想用一个中断处理程序来增加一个记数变量, 就应该这样写:
volatile int counter;
void my_timer_handler()
{
counter++;
}
END_OF_FUNCTION(my_timer_handler);
在你的初始化代码里,应该锁住内存:
LOCK_VARIABLE(counter);
LOCK_FUNCTION(my_timer_handler);
很明显,如果你使用了复杂的数据结构并且在这个处理程序中调用了其它的 函数,这就显得很笨拙,所以你应该使你的中断处理程序尽量简洁.
3、设置时钟中断的频率
SECS_TO_TIMER(secs) - 给出两次触发间的秒数
MSEC_TO_TIMER(msec) - 给出两次触发间的万分之一秒数
BPS_TO_TIMER(bps) - 给出每秒触发多少次
BPM_TO_TIMER(bpm) - 给出每分钟触发多少次
4、/* 这些中断在这里被激活... */
Allegro的用户时钟中断貌似都在whlie(true)循环里起作用。如果你有写过“XX引擎”的话,应该对此有更深的体会。