OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8858|回复: 11

UCOSIII使用OSTimeDlyHMSM延时,延时时间未到就切换了

[复制链接]

11

主题

30

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
394
金钱
394
注册时间
2018-8-28
在线时间
69 小时
发表于 2018-12-24 15:30:55 | 显示全部楼层 |阅读模式
1金钱
main.c代码如下,想要task1(LCD蓝底白字显示)和task2(LCD红底白字显示)以5秒的周期循环交替执行,但是烧录后发现大部分时候都在task2状态,偶尔可以看到LCD显示蓝底白字(task1),而且是一闪即逝,我把task1里面的OSTimeDlyHMSM的延时参数不管修改成多少,现象都一样,另外#define  OS_CFG_TICK_RATE_HZ            200u               /* Tick rate in Hertz (10 to 1000 Hz)                     */。请问这是什么情况?:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "includes.h"
#include "os_app_hooks.h"

//任务优先级
#define START_TASK_PRIO                3
//任务堆栈大小       
#define START_STK_SIZE                 128
//任务控制块
OS_TCB StartTaskTCB;
//任务堆栈       
CPU_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *p_arg);

//任务优先级
#define TASK1_TASK_PRIO                4
//任务堆栈大小       
#define TASK1_STK_SIZE                 128
//任务控制块
OS_TCB Task1_TaskTCB;
//任务堆栈       
CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];
void task1_task(void *p_arg);

//任务优先级
#define TASK2_TASK_PRIO                5
//任务堆栈大小       
#define TASK2_STK_SIZE                 128
//任务控制块
OS_TCB Task2_TaskTCB;
//任务堆栈       
CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE];
//任务函数
void task2_task(void *p_arg);


//主函数
int main(void)
{
        OS_ERR err;
        CPU_SR_ALLOC();
       
        delay_init(168);  //时钟初始化
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组配置
//        uart_init(115200);   //串口初始化
//        LED_Init();         //LED初始化       
        LCD_Initializtion();                        //LCD初始化       
               
        OSInit(&err);                    //初始化UCOSIII
        OS_CRITICAL_ENTER();        //进入临界区                         
        //创建开始任务
        OSTaskCreate((OS_TCB         * )&StartTaskTCB,                //任务控制块
                                 (CPU_CHAR        * )"start task",                 //任务名字
                 (OS_TASK_PTR )start_task,                         //任务函数
                 (void                * )0,                                        //传递给任务函数的参数
                 (OS_PRIO          )START_TASK_PRIO,     //任务优先级
                 (CPU_STK   * )&START_TASK_STK[0],        //任务堆栈基地址
                 (CPU_STK_SIZE)START_STK_SIZE/10,        //任务堆栈深度限位
                 (CPU_STK_SIZE)START_STK_SIZE,                //任务堆栈大小
                 (OS_MSG_QTY  )0,                                        //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
                 (OS_TICK          )0,                                        //当使能时间片轮转时的时间片长度,为0时为默认长度,
                 (void           * )0,                                        //用户补充的存储区
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
                 (OS_ERR         * )&err);                                //存放该函数错误时的返回值
        OS_CRITICAL_EXIT();        //退出临界区         
        OSStart(&err);      //开启UCOSIII
}


//开始任务任务函数
void start_task(void *p_arg)
{
        OS_ERR err;
        CPU_SR_ALLOC();
        p_arg = p_arg;

        CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
   OSStatTaskCPUUsageInit(&err);          //统计任务               
#endif
       
#ifdef CPU_CFG_INT_DIS_MEAS_EN                //如果使能了测量中断关闭时间
    CPU_IntDisMeasMaxCurReset();       
#endif
       
#if        OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候
         //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
        OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif       
       
        OS_CRITICAL_ENTER();        //进入临界区
        //创建TASK1任务
        OSTaskCreate((OS_TCB         * )&Task1_TaskTCB,               
                                 (CPU_CHAR        * )"Task1 task",                
                 (OS_TASK_PTR )task1_task,                        
                 (void                * )0,                                       
                 (OS_PRIO          )TASK1_TASK_PRIO,     
                 (CPU_STK   * )&TASK1_TASK_STK[0],       
                 (CPU_STK_SIZE)TASK1_STK_SIZE/10,       
                 (CPU_STK_SIZE)TASK1_STK_SIZE,               
                 (OS_MSG_QTY  )0,                                       
                 (OS_TICK          )0,                                       
                 (void           * )0,                                       
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR         * )&err);                               
                                 
        //创建TASK2任务
        OSTaskCreate((OS_TCB         * )&Task2_TaskTCB,               
                                 (CPU_CHAR        * )"task2 task",                
                 (OS_TASK_PTR )task2_task,                        
                 (void                * )0,                                       
                 (OS_PRIO          )TASK2_TASK_PRIO,            
                 (CPU_STK   * )&TASK2_TASK_STK[0],       
                 (CPU_STK_SIZE)TASK2_STK_SIZE/10,       
                 (CPU_STK_SIZE)TASK2_STK_SIZE,               
                 (OS_MSG_QTY  )0,                                       
                 (OS_TICK          )0,                                       
                 (void           * )0,                               
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR         * )&err);                         
        OS_CRITICAL_EXIT();        //退出临界区
        OSTaskDel((OS_TCB*)0,&err);        //删除start_task任务自身
}


//task1任务函数
void task1_task(void *p_arg)
{
        u8 task1_num=0;
        OS_ERR err;
        CPU_SR_ALLOC();
        p_arg = p_arg;
       
        OS_CRITICAL_ENTER();
        //LCD_Clear(Blue);
        OS_CRITICAL_EXIT();
        while(1)
        {
                LCD_Clear(Blue);
                GUI_Text(132,104,"Open407I",White,Red);
                OSTimeDlyHMSM(0,0,5,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时5s
                //delay_ms(1000);
        }
}

//task2任务函数
void task2_task(void *p_arg)
{
        u8 task2_num=0;
        OS_ERR err;
        CPU_SR_ALLOC();
        p_arg = p_arg;
       
        OS_CRITICAL_ENTER();
        //LCD_Clear(Red);
        OS_CRITICAL_EXIT();
        while(1)
        {
                LCD_Clear(Red);
                GUI_Text(76,120,"Development Board V2.0",White,Blue2);
                OSTimeDlyHMSM(0,0,5,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时5s
        }
}


最佳答案

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

11

主题

30

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
394
金钱
394
注册时间
2018-8-28
在线时间
69 小时
 楼主| 发表于 2018-12-24 15:30:56 | 显示全部楼层
MH居士 发表于 2018-12-26 17:15
你想实现的功能涉及到任务间的行为同步了,建议加上信号量进行同步。

好像是的,感谢
回复

使用道具 举报

10

主题

778

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6681
金钱
6681
注册时间
2017-4-12
在线时间
1254 小时
发表于 2018-12-24 16:02:10 | 显示全部楼层
这是5ms
回复

使用道具 举报

11

主题

30

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
394
金钱
394
注册时间
2018-8-28
在线时间
69 小时
 楼主| 发表于 2018-12-24 16:04:07 | 显示全部楼层

是5秒呢,而且就算我改成OSTimeDlyHMSM(0,1,5,0,OS_OPT_TIME_HMSM_STRICT,&err);也一样
void  OSTimeDlyHMSM (CPU_INT16U   hours,
                     CPU_INT16U   minutes,
                     CPU_INT16U   seconds,
                     CPU_INT32U   milli,
                     OS_OPT       opt,
                     OS_ERR      *p_err)
回复

使用道具 举报

11

主题

30

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
394
金钱
394
注册时间
2018-8-28
在线时间
69 小时
 楼主| 发表于 2018-12-24 17:08:09 | 显示全部楼层
我顶!!!!
回复

使用道具 举报

11

主题

30

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
394
金钱
394
注册时间
2018-8-28
在线时间
69 小时
 楼主| 发表于 2018-12-25 11:57:21 | 显示全部楼层
我再顶!!!
回复

使用道具 举报

0

主题

5

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2018-3-2
在线时间
7 小时
发表于 2018-12-25 17:43:41 | 显示全部楼层
本帖最后由 lhb292 于 2018-12-25 17:47 编辑

OSTimeDlyHMSM(0, 0,5, 0,OS_OPT_TIME_HMSM_NON_STRICT,&err);//看你延时调用的函数应该没问题
回复

使用道具 举报

2

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
86
金钱
86
注册时间
2018-12-26
在线时间
24 小时
发表于 2018-12-26 17:13:02 | 显示全部楼层
OSTimeDlyHMSM延时中,相当于把当前任务挂起了,然后执行任务切换,执行task2,在5S内大多数时间都在task2里,task1执行每次只是一下,之后显示屏会执行tash2的操作。   虽然task2在他的延时函数里也挂起,但是,即使此时task2挂起,屏幕也是task2设置的样子。
琐碎时光,悄悄溜走
回复

使用道具 举报

2

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
86
金钱
86
注册时间
2018-12-26
在线时间
24 小时
发表于 2018-12-26 17:15:37 | 显示全部楼层
你想实现的功能涉及到任务间的行为同步了,建议加上信号量进行同步。
琐碎时光,悄悄溜走
回复

使用道具 举报

13

主题

62

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1007
金钱
1007
注册时间
2016-8-1
在线时间
157 小时
发表于 2019-1-8 11:44:03 | 显示全部楼层
你还是要去了解任务之间的切换以及延时函数源代码里都做了什么,这个出现你描述的现象是正常的;要想来回切换要弄到任务之间的同步了,有信号量消息邮箱等机制可以实现。
回复

使用道具 举报

28

主题

294

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1790
金钱
1790
注册时间
2018-3-26
在线时间
294 小时
发表于 2019-8-27 14:05:21 | 显示全部楼层
这是正常的,task1的任务优先级教高,所以进入task1任务之后,显示一瞬间就OSTimeDlyHMSM释放了,再进入task2任务显示,task2任务也是进入一瞬间就释放了,但是此时task1任务还在延时中,要过5s才进入就绪列表,所以就一直显示task2的状态,直到task1的延时过完,再切换task1。
茵茵猪头
回复

使用道具 举报

8

主题

185

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2019-7-15
在线时间
47 小时
发表于 2019-8-28 13:41:34 | 显示全部楼层
明确任务调度需求,单纯靠延时是不能均匀调度的,像信号量的使用达到同步作用。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 22:52

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表