一个基于 Apollo3 芯片 和 FreeRTOS 的软件定时器应用实例,结合低功耗特性实现周期性任务。代码详细适配 Apollo3 的硬件环境,并包含详细注释。
场景描述
假设我们需要在 Apollo3 上实现一个 每秒读取一次温度传感器 的任务,并通过串口发送数据。同时,在空闲时进入低功耗模式(Sleep Mode)。
完整代码示例
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "am_mcu_apollo.h" // Apollo3 硬件库
#include "am_util.h" // Apollo3 工具库
// 定义定时器参数
#define TEMP_READ_TIMER_NAME "TempTimer"
#define TEMP_READ_PERIOD_MS 1000 // 1秒周期
#define TIMER_AUTO_RELOAD pdTRUE // 自动重载
#define TIMER_ID 123 // 自定义定时器ID(用于传递参数)
// 全局变量
TimerHandle_t xTempTimer = NULL;
//-----------------------------------------------------------------------------
// 温度传感器模拟读取函数(实际需替换为硬件操作)
//-----------------------------------------------------------------------------
static float read_temperature_sensor(void)
{
// Apollo3 内置温度传感器读取示例(需根据实际硬件调整)
float temp;
am_hal_tsen_read(&temp); // 使用Ambiq HAL库读取温度
return temp;
}
//-----------------------------------------------------------------------------
// 定时器回调函数:读取温度并打印
//-----------------------------------------------------------------------------
void vTempTimerCallback(TimerHandle_t xTimer)
{
// 获取用户数据(通过ID传递)
UBaseType_t timer_id = (UBaseType_t)pvTimerGetTimerID(xTimer);
if (timer_id != TIMER_ID) return; // 验证ID
// 1. 读取温度
float temperature = read_temperature_sensor();
// 2. 通过串口发送数据(Apollo3 UART示例)
am_util_stdio_printf("Temperature: %.2f°C\n", temperature);
// 3. 可在此处添加低功耗唤醒后的处理逻辑
}
//-----------------------------------------------------------------------------
// 硬件初始化:配置温度传感器和串口
//-----------------------------------------------------------------------------
static void hardware_init(void)
{
// 1. 初始化Apollo3核心硬件
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();
// 2. 初始化温度传感器
am_hal_tsen_config_t tsen_config =
{
.eClock = AM_HAL_TSEN_CLKSEL_HFRC_3MHZ,
.ePrecision = AM_HAL_TSEN_ADC_14BIT,
.eTrigger = AM_HAL_TSEN_TRIG_SOFT
};
am_hal_tsen_initialize(0, &tsen_config);
am_hal_tsen_power_ctrl(0, AM_HAL_TSEN_POWER_ON);
// 3. 初始化串口(以UART0为例)
am_util_stdio_uart_init(0); // 使用默认引脚和波特率
}
//-----------------------------------------------------------------------------
// 主函数
//-----------------------------------------------------------------------------
int main(void)
{
// 1. Apollo3 硬件初始化
hardware_init();
// 2. 创建软件定时器
xTempTimer = xTimerCreate(
TEMP_READ_TIMER_NAME, // 定时器名称
pdMS_TO_TICKS(TEMP_READ_PERIOD_MS), // 转换为Tick数
TIMER_AUTO_RELOAD, // 自动重载
(void*)TIMER_ID, // 传递用户数据(ID)
vTempTimerCallback // 回调函数
);
if (xTempTimer == NULL)
{
am_util_stdio_printf("Failed to create timer!\n");
while(1); // 错误处理
}
// 3. 启动定时器
if (xTimerStart(xTempTimer, 0) != pdPASS)
{
am_util_stdio_printf("Failed to start timer!\n");
while(1);
}
// 4. 启动FreeRTOS调度器
vTaskStartScheduler();
// 程序不应执行到这里
while(1);
}
关键代码解析
1. 定时器创建与配置
xTempTimer = xTimerCreate(
"TempTimer",
pdMS_TO_TICKS(1000), // Apollo3的Tick频率需在FreeRTOSConfig.h中配置
pdTRUE, // 自动重载
(void*)TIMER_ID, // 用户数据(可用于区分多个定时器)
vTempTimerCallback // 严格匹配TimerHandle_t参数的回调函数
);
pdMS_TO_TICKS:将毫秒转换为 FreeRTOS Tick 数,需确保 configTICK_RATE_HZ 在 FreeRTOSConfig.h 中正确定义(例如 1000Hz 对应 1ms/Tick)。
2. 低功耗优化(Apollo3 特性)
在 FreeRTOSConfig.h 中启用 Tickless Idle 模式:
#define configUSE_TICKLESS_IDLE 1 // 启用低功耗Tickless模式
Tickless Idle:当系统空闲时,Apollo3 会停止时钟中断,显著降低功耗。
传感器唤醒:可通过 Apollo3 的 GPIO 中断或 RTC 唤醒系统。
3. 温度传感器读取
am_hal_tsen_read(&temp); // 使用Ambiq HAL库操作内置温度传感器
实际开发中需根据 Apollo3 的数据手册配置传感器精度和时钟源。
4. 串口输出
am_util_stdio_printf("Temperature: %.2f°C\n", temperature); // 使用Ambiq简化UART API
am_util_stdio_printf 是 Apollo3 SDK 提供的简化串口输出函数,底层依赖 UART 硬件。
适配 Apollo3 的注意事项
时钟配置:
在 hardware_init() 中通过 am_hal_clkgen_control 设置系统时钟。
根据功耗需求选择 HFRC(高频内部时钟)或 LFRC(低频时钟)。
低功耗模式:
在 vTempTimerCallback 中尽量减少处理时间,使系统尽快回到空闲状态。
使用 am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP); 手动进入深度睡眠。
FreeRTOS 配置:
在 FreeRTOSConfig.h 中为 Apollo3 优化栈大小和优先级:
#define configTIMER_TASK_STACK_DEPTH 512 // 定时器守护任务栈
#define configMAX_PRIORITIES 8 // 合理规划优先级
运行结果
系统会每秒打印一次温度值,空闲时进入低功耗模式:
Temperature: 25.60°C
Temperature: 25.62°C
Temperature: 25.58°C
...
扩展场景
多定时器协作:创建多个定时器处理不同任务(如传感器校准、无线通信)。
动态修改周期:通过 xTimerChangePeriod() 实现自适应采样率。
错误恢复:在回调函数中添加硬件异常检测,重启定时器或系统。
此示例展示了 Apollo3 芯片与 FreeRTOS 软件定时器的深度集成,兼顾实时性和低功耗需求。