概述
定时器是嵌入式开发最常用的外设之一:LED 闪烁、按键扫描、超时判断、周期性数据采集等场景都离不开它。本教程通过 硬件定时器周期中断,每 100us 自动翻转一次 GPIO 输出,产生方波信号。
用大白话讲:定时器就像开发板里的一个「闹钟」。你设好时间(比如 100 微秒),闹钟一到点就自动「响铃」(触发中断),把正在做的事打断一下,去执行你安排好的小任务(翻转引脚电平),然后继续计时。本教程就是靠这个闹钟,每 100 微秒翻转一次引脚,输出方波。
本教程基于安信可官方 SDK(Ai-Thinker-Open/Ai-Thinker-WB2,版本
release_bl_iot_sdk_1.6.40)的官方示例applications/peripherals/demo_timer编写,代码可在本地 SDK 中直接找到。
按官方示例接线(见 SDK applications/peripherals/demo_timer/README.md):
| Ai-WB2 引脚 | 连接到 |
|---|---|
| IO3 | 逻辑分析仪探针(Probe) |
💡 示例通过 IO3 输出 100us 周期方波,用逻辑分析仪或示波器即可直观观察波形。没有仪器时,也可将 IO3 接 LED 观察闪烁节奏。
打开终端,进入官方 demo_timer 示例工程目录:
cd ~/Ai-Thinker-WB2/applications/peripherals/demo_timer
说明:
cd是「进入目录」命令,这里进入 demo_timer 示例工程目录;后续的make编译、make flash烧录命令都必须先在这个目录里执行。
打开 demo_timer/main.c,本步完整代码已移至文末,见:
📜 完整代码 — 位于本页「完整代码」章节,默认折叠,点击展开,与官方示例(
applications/peripherals/demo_timer/demo_timer/main.c)完全一致。
代码要点:
| 代码 | 作用 |
|---|---|
period = 100 |
定时周期 100us(单位是微秒,不是毫秒),设错单位周期就相差 1000 倍 |
reload_mode = TIMER_RELOAD_PERIODIC |
自动重载模式:响完一次自动接着计时、连续触发;选错就只响一次 |
timer_cb |
定时器中断回调(到点自动执行的函数):每次触发翻转一次 IO3 电平,不翻转就没有波形 |
hosal_timer_init(&timer0) |
初始化定时器,不初始化后面启动也无效 |
hosal_timer_start(&timer0) |
启动定时器(闹钟开始走),不启动永远不触发 |
在工程目录执行编译:
make -j8
说明:
make是「编译工程」命令,把代码变成开发板能运行的固件(程序文件);-j8表示用 8 个核并行编译,速度更快。
编译成功后生成固件 build_out/demo_timer.bin。
开发板保持 USB 连接,确认串口设备号后执行烧录:
make flash p=/dev/ttyUSB0 b=921600
说明:
make flash是「烧录」命令,把编译好的固件写进开发板芯片。p=后面是串口设备号(改成你电脑上实际的串口,可用ls /dev/ttyUSB*查看),b=是烧录波特率(传输速度)。
⏳ 烧录过程中按提示长按开发板 EN 键进入下载模式,等待进度条完成即烧录成功。
烧录完成后开发板自动重启运行,逻辑分析仪在 IO3 上可观察到周期 100us 的方波(每 50us 翻转一次,50% 占空比),与官方示例输出的波形一致。

💡 把
period改为1000000(1 秒)并接 LED,即可看到 LED 每 1 秒闪烁一次——定时器相比vTaskDelay阻塞延时,不占用 CPU,且定时精度由硬件保证。
看到逻辑分析仪上 IO3 输出周期 100us 的方波即为成功;如果看不到波形或频率不对,说明还没成功,对照文末「常见问题与踩坑提示」排查。
代码执行流程
例程从启动到运行的完整流程如下(图中的循环箭头表示反复执行):
本文 API 汇总
hosal_timer_init(tim)
按 dev 结构体中的周期、重载模式、回调等配置硬件定时器(本教程 100us 周期触发)。
参数:
tim:hosal_timer_dev_t结构体指针,必填。关键字段:config.period(周期,单位微秒 us,本教程100)、config.reload_mode(可选值:TIMER_RELOAD_PERIODIC自动重载周期触发 /TIMER_RELOAD_ONCE单次触发)、config.cb(到期回调函数指针,形如void cb(void *arg))、config.arg(回调参数,无参传NULL)
返回值:成功返回 0;失败返回负值错误码
hosal_timer_start(tim)
开始计时,到期触发回调(周期模式下自动重复)。
参数:
tim:hosal_timer_dev_t结构体指针(需先hosal_timer_init)
返回值:成功返回 0;失败返回负值错误码
hosal_timer_stop(tim)
停止计时,不再触发回调(再次 start 可重新计时)。
参数:
tim:hosal_timer_dev_t结构体指针
返回值:成功返回 0;失败返回负值错误码
hosal_timer_finalize(tim)
注销定时器并释放占用的硬件资源(不再使用前调用)。
参数:
tim:hosal_timer_dev_t结构体指针
返回值:成功返回 0;失败返回负值错误码
bl_gpio_enable_output(pin, pullup, pulldown)
把指定引脚配置为推挽输出模式,可驱动 LED、蜂鸣器等负载(本教程用于输出方波)。
参数:
pin:引脚号,可选值:0~22(GPIO0~GPIO22),本教程用3pullup:是否使能内部上拉,可选值:1使能 /0关闭(推挽输出无需上拉,传0)pulldown:是否使能内部下拉,可选值:1使能 /0关闭
返回值:成功返回 0;失败返回负值错误码
bl_gpio_output_set(pin, value)
向已配置为输出的引脚输出高电平或低电平(本教程在定时器回调中翻转 IO3)。
参数:
pin:引脚号,可选值同bl_gpio_enable_output(0~22)value:输出电平,可选值:1高电平(3.3V)/0低电平(0V)
返回值:成功返回 0;失败返回负值错误码
完整代码
以下为 demo_timer/main.c 完整源码,与官方示例(applications/peripherals/demo_timer/demo_timer/main.c)完全一致:
📜 点击展开 demo_timer/main.c 完整代码
#include <stdio.h>
#include <FreeRTOS.h>
#include <task.h>
#include <hosal_timer.h>
#include <bl_gpio.h>
#include <blog.h>
static void timer_cb(void *arg)
{
static int i = 0;
if (i % 2) {
bl_gpio_output_set(3, 0);
} else {
bl_gpio_output_set(3, 1);
}
i++;
}
int main(void)
{
bl_gpio_enable_output(3, 1, 0);
static hosal_timer_dev_t timer0 = {
.config = {
.arg = NULL,
.cb = timer_cb,
.period = 100, /// 100us
.reload_mode = TIMER_RELOAD_PERIODIC,
},
.port = 0,
};
hosal_timer_init(&timer0);
hosal_timer_start(&timer0);
return 0;
}常见问题与踩坑提示
⚠️ 波形频率与预期不符
原因:period 单位是 us,误按 ms 换算会导致周期相差 1000 倍
解决:1ms 定时应写 period = 1000;周期=2×period,方波周期 200us 时 period 应设 100
⚠️ 定时器只触发一次就停止
原因:reload_mode 误配置为 TIMER_RELOAD_ONCE(单次模式)
解决:需要周期触发时使用 TIMER_RELOAD_PERIODIC
⚠️ 定时器回调中耗时操作导致波形失真
原因:回调内执行 printf 等耗时操作,占用时间超过周期
解决:回调中只做轻量操作(置标志位、翻转 IO),耗时处理放主循环;如需打印日志使用 blog_info(非阻塞 LOG)
⚠️ 烧录一直卡住等待,进度条不动
原因:未进入下载模式,或数据线只能充电不能传数据
解决:烧录时按提示长按 EN 键进入下载模式;换一根能传数据的 Type-C 数据线后重试
⚠️ 找不到串口设备或提示无权限
原因:Linux 下 /dev/ttyUSB0 不存在或权限不足,Windows 下未安装 USB 转串口驱动
解决:Linux 用 ls /dev/ttyUSB* 确认设备号,权限不足执行 sudo usermod -aG dialout $USER 后重新登录;Windows 在设备管理器安装驱动并确认 COM 口号
运行自检
逻辑分析仪在 IO3 上观察到周期 100us 的方波,即定时器功能验证通过。
遇到问题?
如有其他问题,请到统一的提问与讨论区:Ai-Thinker Discussions

