打印
[技术讨论]

这种任务定义方式请教高手解释一下

[复制链接]
287|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
地瓜patch|  楼主 | 2025-6-3 22:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看过教程不是很明白结构体定义任务

static TASK_COMPONENTS Task_Comps[]=
{      
{0, 300,   300,   LED0_Blink},      /* task 1 Period£º 300ms */
{0, 600,   600,   LED1_Blink},      /* task 1 Period£º 600ms */
{0, 900,   900,   LED2_Blink},      /* task 1 Period£º 600ms */  
{0, 10,    10,    KEY_Task},      /* task 1 Period£º 600ms */         
};

任务回调函数
void Task_Marks_Handler_Callback(void)
{
    u8 i;
    for(i=0; i<Tasks_Max; i++)
    {
        if(Task_Comps.TIMCount)      /* If the time is not 0 */
        {
            Task_Comps.TIMCount--;   /* Time counter decrement */
            if(Task_Comps.TIMCount == 0) /* If time arrives */
            {
                /*Resume the timer value and try again */
                Task_Comps.TIMCount = Task_Comps.TRITime;  
                Task_Comps.Run = 1;      /* The task can be run */
            }
        }
    }
}


任务函数

void LED1_Blink(void)
{
        State2 = !State2;
        P01 = State2;
}

void LED2_Blink(void)
{
        State3 = !State3;
        P02 = State3;
}


请教高手,这三者之间是什么关系,之间是怎么调用的?

使用特权

评论回复

相关帖子

沙发
zchong| | 2025-6-4 05:06 | 只看该作者
TASK_COMPONENTS这个结构体成员搞清楚就差不多了

使用特权

评论回复
板凳
zchong| | 2025-6-4 07:21 | 只看该作者
TASK_COMPONENTS这个结构体定义搞清楚就可以了

使用特权

评论回复
地板
mwxpk| | 2025-6-4 08:54 | 只看该作者
为何程序语言难理解,一是语种问题,二是各人的习惯思维表达方式。语种----英文字符,如果用拼音字符也可以。只是拼的表达方式不一样。国人依旧还是方块字表达。不可能在机器语言基础上有作为。各人习惯表达方法是个人的习性。在文学中有好多前后语的应用表达方法。比如,“你吃饭了”,也可以说“吃饭了你”
现在大数据应用能更好的回答你的问题。自己去找更详细的答案
也可以把你想要的目标程序更好的回复你。更加容易学习理解。
这段代码实现了一个基于软件定时器的任务调度系统,用于周期性执行多个任务。下面我为你详细分析:
任务组件数组
c
运行
static TASK_COMPONENTS Task_Comps[] = {
    {0, 300, 300, LED0_Blink},      /* task 1 Period:300ms */
    {0, 600, 600, LED1_Blink},      /* task 2 Period:600ms */
    {0, 900, 900, LED2_Blink},      /* task 3 Period:900ms */  
    {0, 10, 10, KEY_Task},          /* task 4 Period:10ms */         
};


这里定义了一个静态数组Task_Comps,它包含 4 个任务组件。每个任务组件的结构体包含四个成员,按顺序分别是:

任务运行标志(初始为 0)
定时器计数器(初始值等于周期)
重装载值(即任务执行周期)
任务回调函数指针
任务标记处理回调函数
c
运行
void Task_Marks_Handler_Callback(void)
{
    u8 i;
    for(i=0; i<Tasks_Max; i++)
    {
        if(Task_Comps[i].TIMCount)      /* 如果定时器不为0 */
        {
            Task_Comps[i].TIMCount--;   /* 定时器递减 */
            if(Task_Comps[i].TIMCount == 0) /* 如果定时时间到 */
            {
                /* 恢复定时器值,准备下一次计时 */
                Task_Comps[i].TIMCount = Task_Comps[i].TRITime;  
                Task_Comps[i].Run = 1;      /* 标记任务可运行 */
            }
        }
    }
}

这个回调函数是系统的核心调度器,它需要被周期性调用(通常由硬件定时器触发)。函数遍历所有任务:

对每个任务的定时器计数器进行递减操作
当某个任务的计数器减到 0 时
重新装载计数器值(恢复为周期值)
将对应任务的运行标志置为 1,表示该任务可以执行了
LED 闪烁任务函数
c
运行
void LED1_Blink(void)
{
    State2 = !State2;
    P01 = State2;
}

void LED2_Blink(void)
{
    State3 = !State3;
    P02 = State3;
}

这些是具体的任务实现函数:

LED1_Blink:翻转状态变量State2,并将其值赋给 P0.1 引脚,实现 LED1 的闪烁
LED2_Blink:翻转状态变量State3,并将其值赋给 P0.2 引脚,实现 LED2 的闪烁
系统工作原理
系统初始化时,所有任务的定时器都被设置为各自的周期值
Task_Marks_Handler_Callback函数被周期性调用(例如每 1ms 调用一次)
每次调用时,该函数会更新所有任务的定时器计数器
当某个任务的计数器到达 0 时,设置其运行标志
主循环需要定期检查这些运行标志,当发现某个任务的标志被置位时,调用对应的任务函数执行
任务执行完毕后,主循环需要清除该任务的运行标志(代码中未显示这部分,但实际系统中应该有)

这种任务调度方式属于非抢占式调度,即每个任务必须主动放弃控制权,其他任务才能执行。它的优点是实现简单,缺点是如果某个任务执行时间过长,会影响其他任务的实时性。

使用特权

评论回复
5
coody| | 2025-6-4 14:29 | 只看该作者
你贴出TASK_COMPONENTS的定义就会明白

使用特权

评论回复
6
地瓜patch|  楼主 | 2025-6-4 20:29 | 只看该作者
本帖最后由 地瓜patch 于 2025-6-4 20:45 编辑
mwxpk 发表于 2025-6-4 08:54
为何程序语言难理解,一是语种问题,二是各人的习惯思维表达方式。语种----英文字符,如果用拼音字符也可以 ...

很详细,详细高手,一直把那个数组当成结构体了,擦

使用特权

评论回复
7
dffzh| | 2025-6-5 10:08 | 只看该作者
这就是通过表驱动法+函数指针的神操作实现功能。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1605

主题

14212

帖子

28

粉丝