esp32s3 周期性定时器demo
时间: 2025-07-01 17:02:43 浏览: 10
以下是一个基于 **ESP32-S3** 的 **周期性定时器** 示例代码,使用 **FreeRTOS 软件定时器** 和 **硬件定时器** 两种方式实现周期性任务。
---
## **1. FreeRTOS 软件定时器示例**
适用于低精度、任务调度的周期性操作(如状态检查、数据上报)。
### **代码实现**
```c
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
#include "esp_log.h"
#define TIMER_PERIOD_MS 1000 // 定时器周期(1秒)
#define TIMER_ID 123 // 自定义定时器ID
static const char *TAG = "SW_TIMER";
// 定时器回调函数
void timer_callback(TimerHandle_t xTimer) {
uint32_t id = (uint32_t)pvTimerGetTimerID(xTimer);
ESP_LOGI(TAG, "Timer %d triggered! Tick: %d", id, xTaskGetTickCount());
}
void app_main() {
// 创建软件定时器
TimerHandle_t sw_timer = xTimerCreate(
"PeriodicTimer", // 定时器名称
pdMS_TO_TICKS(TIMER_PERIOD_MS), // 周期(转换为Tick)
pdTRUE, // 自动重载(周期性)
(void *)TIMER_ID, // 用户ID
timer_callback // 回调函数
);
if (sw_timer == NULL) {
ESP_LOGE(TAG, "Failed to create timer!");
return;
}
// 启动定时器
xTimerStart(sw_timer, 0);
ESP_LOGI(TAG, "Software timer started (period: %d ms)", TIMER_PERIOD_MS);
// 主循环(可执行其他任务)
while (1) {
vTaskDelay(pdMS_TO_TICKS(100)); // 避免主循环占用CPU
}
}
```
### **关键点**
- **`xTimerCreate()`** 创建定时器,`pdTRUE` 表示周期性触发。
- **`pdMS_TO_TICKS()`** 将毫秒转换为 FreeRTOS 的 Tick 单位。
- **`xTimerStart()`** 启动定时器。
- **`pvTimerGetTimerID()`** 在回调函数中获取用户定义的 ID。
---
## **2. 硬件定时器(HW Timer)示例**
适用于高精度、硬件中断触发的周期性操作(如 PWM、精确计时)。
### **代码实现**
```c
#include "driver/timer.h"
#include "esp_log.h"
#define TIMER_GROUP TIMER_GROUP_0
#define TIMER_IDX TIMER_0
#define TIMER_PERIOD_US 1000000 // 1秒(单位:微秒)
static const char *TAG = "HW_TIMER";
// 硬件定时器中断回调
void IRAM_ATTR timer_isr(void *arg) {
static int count = 0;
count++;
ESP_LOGI(TAG, "HW Timer triggered! Count: %d", count);
// 清除中断标志
TIMERG0.int_clr_timers.t0 = 1;
}
void app_main() {
// 配置硬件定时器
timer_config_t config = {
.alarm_en = true,
.counter_en = true,
.intr_type = TIMER_INTR_LEVEL,
.counter_dir = TIMER_COUNT_UP,
.auto_reload = true,
.divider = 80, // 80MHz / 80 = 1MHz(1us分辨率)
};
timer_init(TIMER_GROUP, TIMER_IDX, &config);
// 设置定时器周期
timer_set_counter_value(TIMER_GROUP, TIMER_IDX, 0);
timer_set_alarm_value(TIMER_GROUP, TIMER_IDX, TIMER_PERIOD_US);
// 注册中断回调
timer_enable_intr(TIMER_GROUP, TIMER_IDX);
timer_isr_register(TIMER_GROUP, TIMER_IDX, timer_isr, NULL, ESP_INTR_FLAG_IRAM, NULL);
// 启动定时器
timer_start(TIMER_GROUP, TIMER_IDX);
ESP_LOGI(TAG, "Hardware timer started (period: %d us)", TIMER_PERIOD_US);
// 主循环(可执行其他任务)
while (1) {
vTaskDelay(pdMS_TO_TICKS(100));
}
}
```
### **关键点**
- **`timer_config_t`** 配置定时器参数(如分频、计数方向)。
- **`timer_set_alarm_value()`** 设置周期(单位:微秒)。
- **`timer_isr_register()`** 注册中断回调(需标记为 `IRAM_ATTR`)。
- **`TIMERG0.int_clr_timers.t0`** 清除中断标志(避免重复触发)。
---
## **3. 两种定时器的对比**
| 特性 | FreeRTOS 软件定时器 | 硬件定时器(HW Timer) |
|---------------------|-----------------------------|-----------------------------|
| **精度** | 低(受 FreeRTOS Tick 影响) | 高(硬件直接驱动) |
| **适用场景** | 任务调度、延迟操作 | PWM、精确中断、高频计时 |
| **资源占用** | 依赖 FreeRTOS 任务 | 独立硬件资源 |
| **是否支持休眠模式** | 否 | 是(可配置唤醒) |
---
## **4. 常见问题**
### **Q1: 如何修改定时器周期?**
- **软件定时器**:调用 `xTimerChangePeriod()`。
- **硬件定时器**:调用 `timer_set_alarm_value()` 并重新启动。
### **Q2: 硬件定时器回调能否调用 FreeRTOS API?**
- **不能直接调用**(中断上下文受限),需通过 `xTimerPendFunctionCall()` 委托给任务。
### **Q3: 如何停止定时器?**
- **软件定时器**:`xTimerStop(sw_timer, 0)`。
- **硬件定时器**:`timer_pause(TIMER_GROUP, TIMER_IDX)`。
### **Q4: 硬件定时器分频系数如何计算?**
- 公式:`分频系数 = (APB时钟频率 / 目标频率)`
(ESP32-S3 默认 APB 时钟 = 80MHz)
---
## **5. 总结**
- **FreeRTOS 软件定时器**:适合低精度周期性任务,与任务调度集成。
- **硬件定时器**:适合高精度、硬件驱动的周期性操作(如 PWM、精确中断)。
你可以根据需求选择合适的定时器类型!🚀
阅读全文
相关推荐


















