实现单片机简单的时间片轮询调度

时间片轮询调度

1.创建一个结构体链表

typedef struct taskMember
{
    pfuntion taskName;
    volatile uint32_t tick;
    uint32_t taskID;
    uint32_t taskStatus;
    struct taskMember *listNext;
}task_t;

2.声明一个链表头。

static task_t taskListHead;
task_t *currentTask = 0;

3.任务创建,每个任务都对应唯一id号码

uint32_t createTask(pfuntion taskName,uint32_t taskID)
{
    task_t *listHead = &taskListHead;
    task_t *temp = 0;
    uint32_t ret = 1;
       
    temp = (task_t *)malloc(sizeof(task_t));
    if(temp == 0)
    {
        free(temp);
        return 0;
    }
    
    temp->taskName = taskName;
    temp->taskStatus = 0;
    temp->taskID = taskID;
    temp->listNext = 0;
    while(listHead->listNext != 0)
    {
        listHead = listHead->listNext;
        if(listHead->taskID == taskID) 
        {
            ret = 0;
            free(temp);
            break; 
        }
    }
    if(ret == 1)
    {
        listHead->listNext = temp;
    }
    
    return ret;
}

4.任务调度,在中断定时器中调用,一般1ms一次

void taskScheduler(void)
{
    task_t *listHead = &taskListHead;
    
    while(listHead->listNext != 0)
    {
        listHead = listHead->listNext;
        if(listHead->tick > 0)
        {
            listHead->tick--;
        }   
    }
}

5.任务延时

void taskDelayMs(uint32_t tick)
{
    currentTask->tick = tick;
}

6.任务开始,在主循环调用

void taskRuning(void)
{
    task_t *listHead = taskListHead.listNext;
    
    while(1)
    {   
        if(listHead->tick == 0 && listHead->taskStatus == 0)
        {
            currentTask = listHead;
            listHead->taskName();
            if(listHead->tick < 1)
            {
                listHead->tick = 1;
            }
        }
        if(listHead->listNext != 0)
        {
            listHead = listHead->listNext;
        }
        else
        {
            listHead = taskListHead.listNext;
        }    
    }

}

7.任务挂起和恢复

void taskDelete(uint32_t taskID)
{
    task_t *listHead = &taskListHead;
    task_t *last = &taskListHead;
    
    while(listHead-> listNext != 0)
    {
        listHead = listHead->listNext; 
        if(listHead->taskID == taskID)
        {
            last->listNext = listHead->listNext;
            free(listHead);
            break;
        }
        else
        {
            last = listHead;
        }   
    } 
}


task_t * searchList(task_t * head,uint32_t taskID)
{
    task_t * temp = head;
    
    while(temp->listNext != 0)
    {
        temp = temp->listNext;
        if(temp->taskID == taskID)
        {
            break;
        }
    }
    return  currentTask;
}
//任务挂起
void taskPending(uint32_t taskID)
{
     task_t *temp = searchList(&taskListHead,taskID);
     if(temp != 0)
     {
         temp->taskStatus = 1;
     }   
}

//任务恢复
void taskResume(uint32_t taskID)
{
     task_t *temp = searchList( &taskListHead,taskID);
     if(temp != 0)
     {
         temp->taskStatus = 0;
         temp->tick = 0;
     }
}

这是一个简单的任务轮询调度,可以创建无数个,方便简单。

/****************************使用例子**********************/
void ledtask(void)//led间隔500ms翻转一次
{
	taskDelayMs(500);
	GPIO_LED = ~ GPIO_LED ;
}


int main(void)
{
	bsp_init();
	createTask(ledtask,1);
	taskRuning();
}
  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
假设单片机需要同时处理三个任务:任务A、任务B和任务C,并且这三个任务都需要在固定的时间间隔内执行。我们可以采用时间片轮询法来实现这种多任务处理。 时间片轮询法的基本思想是将时间分成若干个片段,每个片段被称为一个时间片单片机在每个时间片内依次执行每个任务,当一个任务执行完毕后,切换到下一个任务继续执行,直到所有任务都执行完毕。 下面是使用时间片轮询法处理三个任务的示例代码: ```c #define TASK_A_TIME 10 // 任务A执行时间 #define TASK_B_TIME 20 // 任务B执行时间 #define TASK_C_TIME 30 // 任务C执行时间 void taskA(){ // 任务A代码 } void taskB(){ // 任务B代码 } void taskC(){ // 任务C代码 } void main(){ int timeSlice = 50; // 时间片大小,单位为ms int timeCounter = 0; while(1){ if(timeCounter % timeSlice == 0){ // 每个时间片开始时执行任务A taskA(); } if(timeCounter % timeSlice == TASK_A_TIME){ // 时间片执行到任务A结束时执行任务B taskB(); } if(timeCounter % timeSlice == TASK_A_TIME + TASK_B_TIME){ // 时间片执行到任务B结束时执行任务C taskC(); } timeCounter++; if(timeCounter == timeSlice * 3){ // 一个完整的周期结束,重新开始计时 timeCounter = 0; } } } ``` 在上面的代码中,我们定义了三个任务:taskA、taskB和taskC,并且给每个任务分配了不同的执行时间。在主函数中,我们使用一个循环来模拟时间片轮询的过程,每个时间片开始时执行任务A,然后执行任务B和任务C,直到一个完整的周期结束。周期结束后重新开始计时,继续执行任务A、任务B和任务C。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值