问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

如何用C语言编写定时器

创作时间:
作者:
@小白创作中心

如何用C语言编写定时器

引用
1
来源
1.
https://docs.pingcode.com/baike/1220036

在C语言中,可以使用多种方法来实现定时功能,例如使用time.h库中的函数、使用系统信号或使用操作系统提供的定时器功能。使用time.h库函数、使用系统信号、操作系统定时器功能是实现定时功能的常见方法。本文将详细介绍如何使用这些方法在C语言中实现定时功能,并探讨每种方法的具体实现和应用场景。

一、使用time.h库函数

1.1 使用clock()函数

clock()函数是C标准库中的一个函数,用于获取程序自启动以来所用的处理器时间。通过计算处理器时间的差值,可以实现简单的定时功能。以下是一个简单的示例,演示如何使用clock()函数来实现定时功能。

#include <stdio.h>
#include <time.h>

int main() {
    clock_t start_time = clock(); // 获取开始时间
    while ((clock() - start_time) < 5 * CLOCKS_PER_SEC) {
        // 等待5秒
    }
    printf("5 seconds have passed.\n");
    return 0;
}

1.2 使用time()函数

time()函数返回自1970年1月1日以来的时间(以秒为单位)。通过计算时间差,可以实现定时功能。以下是一个示例,演示如何使用time()函数来实现定时功能。

#include <stdio.h>
#include <time.h>

int main() {
    time_t start_time = time(NULL); // 获取开始时间
    while (difftime(time(NULL), start_time) < 5) {
        // 等待5秒
    }
    printf("5 seconds have passed.\n");
    return 0;
}

二、使用系统信号

2.1 使用alarm()函数

alarm()函数用于在指定的秒数后发送SIGALRM信号给调用进程。以下是一个示例,演示如何使用alarm()函数来实现定时功能。

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void handle_alarm(int sig) {
    printf("5 seconds have passed.\n");
}

int main() {
    signal(SIGALRM, handle_alarm); // 设置信号处理函数
    alarm(5); // 设置5秒定时
    pause(); // 暂停程序,等待信号
    return 0;
}

2.2 使用setitimer()函数

setitimer()函数用于设置定时器,可以指定微秒级的定时时间。以下是一个示例,演示如何使用setitimer()函数来实现定时功能。

#include <stdio.h>
#include <sys/time.h>
#include <signal.h>

void handle_timer(int sig) {
    printf("5 seconds have passed.\n");
}

int main() {
    struct itimerval timer;
    signal(SIGALRM, handle_timer); // 设置信号处理函数
    timer.it_value.tv_sec = 5; // 设置初始时间为5秒
    timer.it_value.tv_usec = 0;
    timer.it_interval.tv_sec = 0; // 设置间隔时间为0秒(一次性定时器)
    timer.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &timer, NULL); // 启动定时器
    pause(); // 暂停程序,等待信号
    return 0;
}

三、操作系统定时器功能

3.1 在Linux中使用timerfd

在Linux系统中,可以使用timerfd创建文件描述符来实现定时功能。以下是一个示例,演示如何使用timerfd来实现定时功能。

#include <stdio.h>
#include <sys/timerfd.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main() {
    int timer_fd;
    struct itimerspec new_value;
    struct timespec now;
    uint64_t expirations;
    ssize_t s;
    // 获取当前时间
    clock_gettime(CLOCK_REALTIME, &now);
    // 创建timerfd
    timer_fd = timerfd_create(CLOCK_REALTIME, 0);
    if (timer_fd == -1) {
        perror("timerfd_create");
        exit(EXIT_FAILURE);
    }
    // 设置定时时间为5秒
    new_value.it_value.tv_sec = now.tv_sec + 5;
    new_value.it_value.tv_nsec = now.tv_nsec;
    new_value.it_interval.tv_sec = 0;
    new_value.it_interval.tv_nsec = 0;
    // 启动定时器
    if (timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1) {
        perror("timerfd_settime");
        exit(EXIT_FAILURE);
    }
    // 读取定时器
    s = read(timer_fd, &expirations, sizeof(expirations));
    if (s != sizeof(expirations)) {
        perror("read");
        exit(EXIT_FAILURE);
    }
    printf("5 seconds have passed.\n");
    return 0;
}

3.2 在Windows中使用CreateWaitableTimer

在Windows系统中,可以使用CreateWaitableTimer和SetWaitableTimer函数来实现定时功能。以下是一个示例,演示如何使用这些函数来实现定时功能。

#include <stdio.h>
#include <windows.h>

int main() {
    HANDLE timer;
    LARGE_INTEGER due_time;
    // 创建可等待的定时器
    timer = CreateWaitableTimer(NULL, TRUE, NULL);
    if (timer == NULL) {
        printf("CreateWaitableTimer failed (%d)\n", GetLastError());
        return 1;
    }
    // 设置定时时间为5秒(单位为100纳秒)
    due_time.QuadPart = -50000000LL;
    // 启动定时器
    if (!SetWaitableTimer(timer, &due_time, 0, NULL, NULL, FALSE)) {
        printf("SetWaitableTimer failed (%d)\n", GetLastError());
        return 1;
    }
    // 等待定时器
    if (WaitForSingleObject(timer, INFINITE) != WAIT_OBJECT_0) {
        printf("WaitForSingleObject failed (%d)\n", GetLastError());
        return 1;
    }
    printf("5 seconds have passed.\n");
    return 0;
}

四、在嵌入式系统中使用硬件定时器

在嵌入式系统中,通常会使用硬件定时器来实现精确的定时功能。以下是一个示例,演示如何在STM32微控制器上使用硬件定时器来实现定时功能。

4.1 配置定时器

首先,需要配置STM32微控制器的定时器。以下是一个示例,演示如何配置定时器TIM2。

#include "stm32f4xx_hal.h"

TIM_HandleTypeDef htim2;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_TIM2_Init();
    HAL_TIM_Base_Start_IT(&htim2); // 启动定时器中断
    while (1) {
    }
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM2) {
        // 定时器中断处理函数
        printf("1 second has passed.\n");
    }
}

static void MX_TIM2_Init(void) {
    __HAL_RCC_TIM2_CLK_ENABLE();
    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 8399;
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 9999;
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_Base_Init(&htim2);
    HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
}

4.2 配置系统时钟和GPIO

在STM32微控制器上,需要配置系统时钟和GPIO。以下是一个示例,演示如何配置系统时钟和GPIO。

void SystemClock_Config(void) {
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 8;
    RCC_OscInitStruct.PLL.PLLN = 336;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    RCC_OscInitStruct.PLL.PLLQ = 7;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                  | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}

static void MX_GPIO_Init(void) {
    __HAL_RCC_GPIOC_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

通过以上配置,可以在STM32微控制器上使用定时器来实现定时功能。

五、实际应用中的考虑

5.1 精度要求

在实际应用中,定时功能的精度要求是一个重要的考虑因素。对于一些实时系统,可能需要高精度的定时功能。在这种情况下,可以使用操作系统提供的高精度定时器或硬件定时器。

5.2 系统资源消耗

实现定时功能的方法可能会消耗系统资源。例如,使用clock()函数和time()函数实现定时功能时,会占用CPU资源。对于资源受限的系统,需要选择合适的方法来实现定时功能。

5.3 可移植性

不同的操作系统和硬件平台可能提供不同的定时器接口。在实际应用中,需要考虑代码的可移植性。例如,使用标准库函数实现定时功能的方法具有较好的可移植性,而使用操作系统提供的定时器接口的方法可能需要进行移植工作。

5.4 定时器的选择

在实际应用中,选择合适的定时器是一个重要的考虑因素。例如,对于需要精确控制定时时间的应用,可以选择使用硬件定时器。对于简单的定时功能,可以使用标准库函数实现。

结论

通过本文的介绍,我们详细探讨了在C语言中实现定时功能的多种方法,包括使用time.h库函数、使用系统信号、操作系统定时器功能以及在嵌入式系统中使用硬件定时器。每种方法都有其优缺点和适用的场景。在实际应用中,可以根据具体需求选择合适的方法来实现定时功能。无论是简单的定时功能还是需要高精度的定时功能,都可以找到合适的实现方法。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号