#include "SN_DDQ.h" #include "common.h" /* 文件名:SN_DDQ.c/.h 作者: SN_FAE_黄泽洪 免责声明:无版权,可随意传播和篡改,该代码仅供开发参考,如需使用请自行验证 本人不担负商业使用上带来的风险。 */ /* SN_DDQ模块全名: 调度器 (DIAO _DU_QI) //注意这不是嵌入式系统 该模块的原理非常简单: 给每个任务倒计数,计数到0,就马上执行该任务函数 用户可以自行添加控制, 比如禁止运行等功能 使用方法; void a(void){.........} //任务函数a void b(void){.........} //任务函数b int main(){ SN_DDQ_init(); //初始或定时器 SN_DDQ_TASK_t MY_TASK1 = {25000,a}; //声明一个任务a SN_DDQ_TASK_ADD(&MY_TASK1); //添加任务 SN_DDQ_TASK_t MY_TASK2 = {5000, b}; //声明一个任务b SN_DDQ_TASK_ADD(&MY_TASK2); //添加任务 while(1){ SN_DDQ_RUN(); //调度器运行 } } 注意:声明任务结构体参数说明: SN_DDQ_TASK_t MY_TASK1 = {25000,a}; 是声明一个任务结构参数主要填入两个 25000 是实现数 (具体时间是25000*20us = 500ms) //时间越短,越优先执行 任务函数名 必须是没有返回值和参数值的函数 void fun (void) */ //调度器列表 struct SN_DDQ_t SN_DDQ_TASK = {0}; /* 函数;任务调度器初始化 默认使用20us的定时调度单位 默认使用内核的滴答定时器,使用了SN_DDQ 调度模块后 不能使用华大的 std_delay_init(); 延时接口 */ void SN_DDQ_init(void){ SN_DDQ_TASK.TASK_LEN = 0; //任务数量为0 //初始化滴答定时器 SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk; //使用内核时钟 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //使能滴答定时器 SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; //使能滴答定时器中断 SysTick->LOAD = TASK_TIME_ATOM ; //定时时间20ua } /* 函数:void SN_DDQ_TASK_ADD( SN_DDQ_TASK_t * MY_TASK ,uint8_t time ,void (*SN_DDQ_TASK)(void) ) 参数: MY_TASK 任务句柄(任务对应的结构体) 返回:无 */ void SN_DDQ_TASK_ADD( SN_DDQ_TASK_t * MY_TASK){ MY_TASK ->counter = MY_TASK ->counter_arr; //给任务的计数器填装计数值 SN_DDQ_TASK.SN_TASK_ARR[SN_DDQ_TASK.TASK_LEN++] = MY_TASK ; //添加任务到调度列表内部 } /* 函数:void SN_DDQ_RUN(void) 任务调度器运行(请放置在while内部) 返回:无 */ void SN_DDQ_RUN(void){ uint8_t i ; for(i = 0; i < SN_DDQ_TASK.TASK_LEN ; i++){ if(SN_DDQ_TASK.SN_TASK_ARR[i]->counter == 0){ SN_DDQ_TASK.SN_TASK_ARR[i]->SN_DDQ_TASK(); //调用任务函数 SN_DDQ_TASK.SN_TASK_ARR[i]->counter = SN_DDQ_TASK.SN_TASK_ARR[i]->counter_arr; //进行任务计数器进行重装 } } } /* 滴答定时器中断函数 */ void SysTick_Handler(void){ uint8_t i ; if(SN_DDQ_TASK.TASK_LEN != 0){ for(i = 0; i < SN_DDQ_TASK.TASK_LEN ; i++){ SN_DDQ_TASK.SN_TASK_ARR[i] -> counter--; } } }