/*
    你的代码描述在这里
    (c) 你, 20XX
    保留所有权利。

    功能描述: 
    
    版本日志:
    
    20XX-MM-DD:
        v1.0.0  - 初始版本发布
        
*/
// ==== 宏定义 ===================================================================================

// ==== 调试和测试选项 ==================
#define _DEBUG_  // 启用调试模式
//#define _TEST_   // 启用测试模式

//===== 调试宏定义 ========================
#ifdef _DEBUG_
#define SerialD Serial  // 定义调试串口
#define _PM(a) SerialD.print(millis()); SerialD.print(": "); SerialD.println(a)  // 打印带时间戳的消息
#define _PP(a) SerialD.print(a)  // 打印内容
#define _PL(a) SerialD.println(a)  // 打印并换行
#define _PX(a) SerialD.println(a, HEX)  // 以十六进制格式打印
#else
#define _PM(a)   // 空定义，不执行任何操作
#define _PP(a)   // 空定义，不执行任何操作
#define _PL(a)   // 空定义，不执行任何操作
#define _PX(a)   // 空定义，不执行任何操作
#endif




// ==== 包含文件 ==================================================================================

// ==== 取消注释需要的编译选项 =================================
// ----------------------------------------
// 以下"宏定义"在编译时控制库的功能，
// 应该根据需要的功能在主程序中使用
// 必须在 #include <TaskScheduler.h> 之前定义！！！
// 在PlatformIO中 - 最好在platformio.ini文件中作为build_flags定义
//
// #define _TASK_TIMECRITICAL       // 启用调度超时监控
// #define _TASK_SLEEP_ON_IDLE_RUN  // 如果在运行过程中没有调用回调方法，启用1ms SLEEP_IDLE省电模式
// #define _TASK_STATUS_REQUEST     // 编译时支持状态请求功能 - 除了时间触发外，还支持状态改变事件触发任务
// #define _TASK_WDT_IDS            // 编译时支持看门狗控制点和任务ID
// #define _TASK_LTS_POINTER        // 编译时支持本地任务存储指针
// #define _TASK_PRIORITY           // 支持分层调度优先级
// #define _TASK_MICRO_RES          // 支持微秒级分辨率
// #define _TASK_STD_FUNCTION       // 支持 std::function 
// #define _TASK_DEBUG              // 为了调试目的，使所有方法和变量公开
// #define _TASK_INLINE             // 使所有方法"内联" - 需要支持某些多标签、多文件实现
// #define _TASK_TIMEOUT            // 支持整体任务超时
// #define _TASK_OO_CALLBACKS       // 通过继承支持回调
// #define _TASK_EXPOSE_CHAIN       // 访问任务链中任务的方法
// #define _TASK_SCHEDULING_OPTIONS // 支持多种调度选项
// #define _TASK_SELF_DESTRUCT      // 启用任务在禁用后"自毁"
// #define _TASK_TICKLESS           // 在FreeRTOS上启用无节拍睡眠支持
// #define _TASK_DO_NOT_YIELD       // 对于ESP芯片，在execute()中禁用yield()方法
// #define _TASK_ISR_SUPPORT        // 对于esp芯片 - 将控制方法放在IRAM中
// #define _TASK_NON_ARDUINO        // 用于非Arduino环境
// #define _TASK_HEADER_AND_CPP     // 编译CPP文件（非Arduino IDE平台）
// #define _TASK_THREAD_SAFE        // 启用线程安全的额外检查

#include <TaskScheduler.h>  // 包含TaskScheduler库



// ==== 全局变量 ===================================================================================
// ==== 调度器 ==============================
Scheduler ts;  // 创建调度器对象

void task1Callback();  // 任务1回调函数声明
void task2Callback();  // 任务2回调函数声明

// ==== 调度宏定义（速查表） =====================
/*
  TASK_MILLISECOND  - 一毫秒，以毫秒/微秒为单位
  TASK_SECOND       - 一秒，以毫秒/微秒为单位
  TASK_MINUTE       - 一分钟，以毫秒/微秒为单位
  TASK_HOUR         - 一小时，以毫秒/微秒为单位
  TASK_IMMEDIATE    - 尽快调度任务运行
  TASK_FOREVER      - 无限期运行任务
  TASK_ONCE         - 运行任务一次
  TASK_NOTIMEOUT    - 设置超时间隔为无超时
  
  TASK_SCHEDULE     - 调度优先，带"追赶"（默认）
  TASK_SCHEDULE_NC  - 调度优先，不带"追赶"
  TASK_INTERVAL     - 间隔优先，不带"追赶"
  
  TASK_SR_OK        - 状态请求触发，返回OK代码（一切正常）
  TASK_SR_ERROR     - 状态请求触发，返回ERROR代码
  TASK_SR_CANCEL    - 状态请求被取消
  TASK_SR_ABORT     - 状态请求被中止
  TASK_SR_TIMEOUT   - 状态请求超时
*/

// ==== 任务定义 ========================
Task t1 (100 * TASK_MILLISECOND, TASK_FOREVER, &task1Callback, &ts, true);  // 任务1：每100毫秒运行一次，永久运行
Task t2 (TASK_IMMEDIATE, 100 /* 次数 */, &task2Callback, &ts, true);         // 任务2：立即运行，运行100次



// ==== CODE ======================================================================================

/**************************************************************************/
/*!
    @brief    标准Arduino初始化方法 - 初始化程序
    @param    无
    @returns  无
*/
/**************************************************************************/
void setup() {
  // 在这里放置初始化代码，运行一次：
#if defined(_DEBUG_) || defined(_TEST_)
  Serial.begin(115200);  // 初始化串口通信，波特率115200
  delay(2000);           // 延时2秒，等待串口稳定
  _PL("Scheduler Template: setup()");  // 打印调试信息
#endif
}


/**************************************************************************/
/*!
    @brief    标准Arduino循环方法 - 使用TaskScheduler时
              这里应该只有ts.execute()
    @param    无
    @returns  无
*/
/**************************************************************************/
void loop() {
  ts.execute();  // 执行调度器，运行所有已安排的任务
}


/**************************************************************************/
/*!
    @brief    任务1的回调方法 - 请解释功能
    @param    无
    @returns  无
*/
/**************************************************************************/
void task1Callback() {
_PM("task1Callback()");  // 打印调试信息：任务1被调用
//  任务代码写在这里
}


/**************************************************************************/
/*!
    @brief    任务2的回调方法 - 请解释功能
    @param    无
    @returns  无
*/
/**************************************************************************/
void task2Callback() {
_PM("task2Callback()");  // 打印调试信息：任务2被调用
//  任务代码写在这里
}




