OpenEdv-开源电子网

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

UCOSIII中使用什么延时不会有任务调度

[复制链接]

2

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-9-5
在线时间
21 小时
发表于 2020-2-27 10:19:55 | 显示全部楼层 |阅读模式
1金钱
在ucosiii的例程10-1中,发现在系统自带延时函数delay_ms()使用时,会发生一次任务调度。但是delay_ms()函数内部并没有任务调度函数啊,让人费解。

那在ucosiii中使用什么延时才不会发生任务调度呢。

函数代码如下
//任务1的任务函数
void task1_task(void *p_arg)
{
OS_ERR err;
u8 task1_str[]="First task Running!";
while(1)
{
  printf("\r\n任务1:\r\n");
  LCD_Fill(0,110,239,319,CYAN);
  memcpy(share_resource,task1_str,sizeof(task1_str)); //向共享资源区拷贝数据
  delay_ms(200);
  printf("%s\r\n",share_resource); //串口输出共享资源区数据
  LED0=!LED0;
  OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);   //延时1s
}
}
//任务2的任务函数
void task2_task(void *p_arg)
{
OS_ERR err;
u8 task2_str[]="Second task Running!";
while(1)
{
  printf("\r\n任务2:\r\n");
  LCD_Fill(0,110,239,319,BROWN);
  memcpy(share_resource,task2_str,sizeof(task2_str)); //向共享资源区拷贝数据
  delay_ms(200);
  printf("%s\r\n",share_resource); //串口输出共享资源区数据
  LED1=!LED1;
  OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);   //延时1s
}
}

串口输出如下:
任务1:
任务2:
Second task Running!
Second task Running!
任务1:
任务2:
Second task Running!
Second task Running!

当屏蔽掉两个delay_ms()函数后,输出正常,如下:
任务1:
First task Running!
任务2:
Second task Running!
任务1:
First task Running!
任务2:
Second task Running!
求指点迷津

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

使用道具 举报

2

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-9-5
在线时间
21 小时
 楼主| 发表于 2020-2-27 10:28:02 | 显示全部楼层
原来在delay_ms()中有任务调度的函数,但是有什么延时是不发生任务调度的吗
回复

使用道具 举报

26

主题

1533

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6369
金钱
6369
注册时间
2015-8-25
在线时间
1004 小时
发表于 2020-2-27 16:35:45 | 显示全部楼层
正点原子的UCOS的例程中的delay_ms()函数里调用了vTaskDelay()函数的,所以会导致调度,
他还有一个delay_xms()的函数,里面是for循环嵌套实现的,这个不会引起调度
He who fights with monsters should look to it that he himself does not become a monster, when you gaze long into the abyss, the abyss also gazes into you.
过于执着就会陷入其中,迷失自己,困住自己。
回复

使用道具 举报

2

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-9-5
在线时间
21 小时
 楼主| 发表于 2020-3-9 16:06:15 | 显示全部楼层
szczyb1314 发表于 2020-2-27 16:35
正点原子的UCOS的例程中的delay_ms()函数里调用了vTaskDelay()函数的,所以会导致调度,
他还有一个dela ...

你好,我在正点原子ucosiii的例程中,并未找到delay_xms()这个函数啊
回复

使用道具 举报

26

主题

1533

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6369
金钱
6369
注册时间
2015-8-25
在线时间
1004 小时
发表于 2020-3-9 16:17:47 | 显示全部楼层
本帖最后由 szczyb1314 于 2020-3-9 16:21 编辑
天海戈林 发表于 2020-3-9 16:06
你好,我在正点原子ucosiii的例程中,并未找到delay_xms()这个函数啊

里面是for循环嵌套实现的,你也可以自己写一个,
void delay_xms(u32 xms)
{
    u32 icnt = 0;
    u32 jcnt = 0;
    u32 tcnt = 0;
    DISABLE INTERRUPT;
    for(icnt=0;icnt<xms;icnt++)
    {
          for(jcnt=0;jcnt<MS;jcnt++)   //注意这里的MS,在你的系统上调整延时达到1ms即可
              tcnt++;
    }
    ENABLE INTERRUPT;
}
这里没有调用过能进行任务调度的API,还禁用了中断,可以只延时不进行系统调度
原子有个这个函数的,我回去给你找找看

He who fights with monsters should look to it that he himself does not become a monster, when you gaze long into the abyss, the abyss also gazes into you.
过于执着就会陷入其中,迷失自己,困住自己。
回复

使用道具 举报

2

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-9-5
在线时间
21 小时
 楼主| 发表于 2020-3-9 16:48:10 | 显示全部楼层
szczyb1314 发表于 2020-3-9 16:17
里面是for循环嵌套实现的,你也可以自己写一个,
void delay_xms(u32 xms)
{

谢过了
回复

使用道具 举报

26

主题

1533

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6369
金钱
6369
注册时间
2015-8-25
在线时间
1004 小时
发表于 2020-3-9 20:07:08 | 显示全部楼层

原子的FreeRTOS有这个不引起任务调度的delay_ms

#include "delay.h"
#include "sys.h"
//////////////////////////////////////////////////////////////////////////////////          
//如果使用OS,则包括下面的头文件即可
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h"                                        //FreeRTOS使用                  
#include "task.h"
#endif
//////////////////////////////////////////////////////////////////////////////////  
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F407开发板
//使用SysTick的普通计数模式对延迟进行管理(支持OS)
//包括delay_us,delay_ms
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2014/5/2
//版本:V1.3
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved
//********************************************************************************
//修改说明
//////////////////////////////////////////////////////////////////////////////////

static u8  fac_us=0;                                                        //us延时倍乘数                          
static u16 fac_ms=0;                                                        //ms延时倍乘数,在os下,代表每个节拍的ms数


extern void xPortSysTickHandler(void);

//systick中断服务函数,使用OS时用到
void SysTick_Handler(void)
{       
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
    {
        xPortSysTickHandler();       
    }
}
                          
//初始化延迟函数
//SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
//这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!
//SYSCLK:系统时钟频率
void delay_init(u8 SYSCLK)
{
        u32 reload;
        SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
        fac_us=SYSCLK;                                                        //不论是否使用OS,fac_us都需要使用
        reload=SYSCLK;                                                        //每秒钟的计数次数 单位为M          
        reload*=1000000/configTICK_RATE_HZ;                //根据delay_ostickspersec设定溢出时间
                                                                                        //reload为24位寄存器,最大值:16777216,在168M下,约合0.0998s左右       
        fac_ms=1000/configTICK_RATE_HZ;                        //代表OS可以延时的最少单位          
        SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启SYSTICK中断
        SysTick->LOAD=reload;                                         //每1/configTICK_RATE_HZ断一次       
        SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK     
}                                                                    

//延时nus
//nus:要延时的us数.       
//nus:0~204522252(最大值即2^32/fac_us@fac_us=168)                                                                              
void delay_us(u32 nus)
{               
        u32 ticks;
        u32 told,tnow,tcnt=0;
        u32 reload=SysTick->LOAD;                                //LOAD的值                     
        ticks=nus*fac_us;                                                 //需要的节拍数
        told=SysTick->VAL;                                        //刚进入时的计数器值
        while(1)
        {
                tnow=SysTick->VAL;       
                if(tnow!=told)
                {            
                        if(tnow<told)tcnt+=told-tnow;        //这里注意一下SYSTICK是一个递减的计数器就可以了.
                        else tcnt+=reload-tnow+told;            
                        told=tnow;
                        if(tcnt>=ticks)break;                        //时间超过/等于要延迟的时间,则退出.
                }  
        };                                                                                    
}  
//延时nms
//nms:要延时的ms数
//nms:0~65535
void delay_ms(u32 nms)
{       
        if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
        {               
                if(nms>=fac_ms)                                                //延时的时间大于OS的最少时间周期
                {
                           vTaskDelay(nms/fac_ms);                         //FreeRTOS延时
                }
                nms%=fac_ms;                                                //OS已经无法提供这么小的延时了,采用普通方式延时   
        }
        delay_us((u32)(nms*1000));                                //普通方式延时
}

//延时nms,不会引起任务调度
//nms:要延时的ms数
void delay_xms(u32 nms)
{
        u32 i;
        for(i=0;i<nms;i++) delay_us(1000);
}

你可以看看,                         



































He who fights with monsters should look to it that he himself does not become a monster, when you gaze long into the abyss, the abyss also gazes into you.
过于执着就会陷入其中,迷失自己,困住自己。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-22 17:37

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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