C语言定时器中断
前提提要:
电脑端运行的系统不同于单片机运行的系统,电脑端为软实时系统,对于中断的到来,可能会受到其他进程或线程的调度所影响,从而CPU无法及时响应,所以电脑端的定时器仅做模拟作用。
SetTimer触发定时器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#include <windows.h>
void CALLBACK timer_callback(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
// 中断回调函数
// 在这里实现每秒钟执行的操作
printf("Timer callback\n");
}
int main()
{
UINT_PTR timerid = SetTimer(NULL, 0, 1000, timer_callback);
// 在这里执行其他操作
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
printf("msg??\n");
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
SetTimer()
是 Windows API 中的一个函数,用于创建一个计时器,让程序在指定的时间间隔内重复执行指定的回调函数。
该函数的声明如下:
1
2
3
4
5
6
UINT_PTR SetTimer(
HWND hWnd,
UINT_PTR nIDEvent,
UINT uElapse,
TIMERPROC lpTimerFunc
);
各个参数的含义如下:
hWnd
: 与计时器相关联的窗口句柄。如果计时器与任何窗口无关,则此参数应为NULL。nIDEvent
: 计时器ID。如果计时器ID为0,则系统将为计时器分配一个唯一的ID。uElapse
: 计时器时间间隔,以毫秒为单位。每隔uElapse
毫秒后,系统会触发计时器事件,调用回调函数。lpTimerFunc
: 回调函数指针。当计时器事件触发时,系统将调用此函数。
该函数返回一个 UINT_PTR
类型的值,表示计时器ID。如果调用失败,则返回值为0。
需要注意的是,Windows API 中的计时器时间间隔的最小值为15毫秒。如果需要更高的精度,则可以使用 timeSetEvent()
函数创建高精度定时器。
:loudspeaker::以上这个示例代码中,SetTimer
函数用来创建一个定时器,其中 TimerProc
是定时器回调函数,每当定时器事件被触发时都会调用它。在主函数中,使用 GetMessage
函数等待消息队列中的消息,并使用 TranslateMessage
函数和 DispatchMessage
函数处理消息。由于 GetMessage
函数是一个阻塞函数,它会等待消息到来,因此可以保证程序不会退出。最后使用 KillTimer
函数来停止定时器。
timeSetEvent触发定时器
timeSetEvent()
函数需要包含头文件#include <mmsystem.h>
,该文件为windows平台SDK的一个头文件,估计是没有正确的安装Windows平台SDK,无法体验到。
CreateTimerQueueTimer创建定时器队列
CreateTimerQueueTimer
函数是用于创建一个定时器的 Windows API 函数。它的参数如下:
1
2
3
4
5
6
7
8
9
BOOL CreateTimerQueueTimer(
PHANDLE phNewTimer,
HANDLE TimerQueue,
WAITORTIMERCALLBACK Callback,
PVOID Parameter,
DWORD DueTime,
DWORD Period,
ULONG Flags
);
下面是各个参数的详细解释:
phNewTimer
:一个指向HANDLE
类型的指针,用于接收创建的定时器的句柄。定时器句柄用于标识定时器,可以用于删除定时器。TimerQueue
:一个HANDLE
类型的句柄,指定定时器所属的定时器队列。定时器队列是一个系统级别的对象,用于管理多个定时器的触发和回调函数的执行。Callback
:一个指向回调函数的指针,用于指定定时器事件发生时要执行的函数。回调函数的参数类型为PVOID
。Parameter
:一个指向任意数据的指针,用于向回调函数传递参数。DueTime
:一个DWORD
类型的值,指定定时器首次触发的时间间隔(以毫秒为单位)。如果设置为0
,表示定时器立即触发。Period
:一个DWORD
类型的值,指定定时器下一次触发的时间间隔(以毫秒为单位)。如果设置为0
,表示定时器只触发一次。Flags
:一个ULONG
类型的值,表示定时器的行为标志。可以设置为WT_EXECUTEINTIMERTHREAD
或WT_EXECUTEONLYONCE
。其中,WT_EXECUTEINTIMERTHREAD
表示在定时器线程上执行回调函数,WT_EXECUTEONLYONCE
表示定时器只触发一次。
需要注意的是,CreateTimerQueueTimer
函数创建的定时器只能用于在 Windows 线程池环境下工作,不能用于单线程或多线程环境。如果您的程序是单线程或多线程环境,请使用 SetTimer
函数或其他定时器库。
Period
参数指定了定时器的时间间隔,也就是每隔多少时间触发一次定时器。它的最小值是 0,表示定时器只会触发一次。如果设置为非 0 的值,表示定时器会每隔一定时间触发一次,直到定时器被取消为止。
Period
参数的取值范围是 0 到 MAXDWORD
(4294967295)之间的任意值,单位为毫秒。需要注意的是,如果 Period
的值过小,会对系统性能产生影响,因此应该谨慎设置。一般来说,建议将 Period
设置为 100 毫秒以上,以免对系统性能产生过大影响。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h>
#include <windows.h>
HANDLE timer_queue = NULL;
void CALLBACK TimerCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
{
printf("Timer event\n");
}
int main()
{
// 创建定时器队列
timer_queue = CreateTimerQueue();
if (timer_queue == NULL)
{
printf("Failed to create timer queue\n");
return 1;
}
// 创建定时器
HANDLE timer_handle = NULL;
if (!CreateTimerQueueTimer(&timer_handle, timer_queue, TimerCallback, NULL, 1000, 1000, 0))
{
printf("Failed to create timer\n");
DeleteTimerQueue(timer_queue);
return 1;
}
// 等待一段时间
Sleep(5000);
// 删除定时器
if (!DeleteTimerQueueTimer(timer_queue, timer_handle, NULL))
{
printf("Failed to delete timer\n");
}
// 删除定时器队列
if (!DeleteTimerQueue(timer_queue))
{
printf("Failed to delete timer queue\n");
}
return 0;
}
在这个示例代码中,首先使用 CreateTimerQueue
函数创建一个定时器队列,然后使用 CreateTimerQueueTimer
函数创建一个定时器,并在定时器回调函数中输出一条信息。接下来等待一段时间,最后删除定时器和定时器队列。
需要注意的是,CreateTimerQueue
函数和 CreateTimerQueueTimer
函数都可以返回一个 BOOL
类型的值,表示函数调用是否成功。在实际使用时,需要根据返回值来判断函数是否成功。同时,使用 DeleteTimerQueueTimer
函数删除定时器时需要指定定时器句柄,这个句柄是在调用 CreateTimerQueueTimer
函数时返回的。
另外,需要注意的是,定时器队列需要在程序退出前使用 DeleteTimerQueue
函数删除,否则会导致资源泄露。