STM32工作笔记0073---UCOSIII任务管理(上)

技术交流QQ群【JAVA,C++,Python,.NET,BigData,AI】:170933152

先去看这几个函数,原来在system文件夹中也有delay.c,也有sys.c,也有usart.c这几个文件

咱们先来看一下,现在用了系统以后,这个delay.c中的函数是这一些.

打开着个工程看,delay.c

可以看到这里#if是条件宏定义,就是说,当满足#if后面的部分,才能被系统编译

不满足的部分就不会被编译.

这也就是说#define这个 SYSTEM_SUPPORT_OS把这个设置为1就可以了.

只有这里设置为1,以后,对应的#if后面的内容才能被编译.

可以看到针对UCOSII ,UCOSIII有些定义是不一样的,也就是说,根据当前系统是UCOSII ,还是UCOSIII来选择性的编译

代码.

任务调度加锁.可以看到UCOSII,UCOSIII是不一样的,一个有参数,一般没参数.

任务恢复调度,解锁,也是一个有参数,一个没参数.

这里是延时的节拍数,这里设置的每个节拍是1ms,如果设置为5,那么

这里就是延时5个节拍,就是5毫秒.

这个是中断服务函数,这里要注意,要是系统运行的时候,

才进入中断,否则的话,调用可能有些变量还没初始化,可能会有问题.

这个delay_init这个就很重要了,可以看到,这里

系统要运行,肯定需要,时钟提供节拍,那么UCOSIII的,节拍,是由

定时器这样的硬件产生的,然后

在UCOIII中,还有一个叫滴答定时器的东西.

这个东西用来给系统提供节拍.

这个文档中也有介绍的滴答定时器.

可以看到他有4个定时器.

这里这个CTRL控制器,是获取状态,

然后LOAD放重装载值,比如放了100,这个时候会从100开始倒数到0,然后

再重装载100进去,然后又开始从100倒数.

然后VAL这个是倒数到几了,当前值

然后CALIB这个一般不用,不用管.

这里,首先看第一个控制器CTRL控制器,

主要看第0位第1位,这里的第0位是,滴答定时器的使能位.

第1位,是开启中断的位.,这两个位挺重要.

第二个是LOAD寄存器,重装载寄存器,

当倒数到0的时候,这个值就会被重装载

然后

当前值VAL寄存器,这个是当前读取出来的值,如果写的话就会清零这个寄存器.

最后一个校准寄存器,占时没用就不管了.

 然后去看一下初始化delay_init这函数

 //1.这里首先是比如如果是STM32F4系列的开发版,这个HCLK是168mhz
    //那么这里时钟频率就是21mhz 168/8
    //如果这里HCLK是72mhz的话,那么
    //这里的时钟频率就是9mhz
    //

//2.第二个地方,这个reload,如果这里

1微妙,跳21次,因为21mhz是时钟源,那么这里1ms就会跳21次,

如果是STM32F4系列的开发版的话,那么

168000 000 /8 =21 000 000 1秒钟震荡21 000 000次

那么1毫秒震荡21 000 次

那么1微妙震荡21次

这一句是根据delay_ostickspersec设定的溢出的时间

去看一下定义的地方

可以看到是200u

这个意思是1秒钟跳200次

那么一次就是5毫秒.

那么跳一次要用1/200=秒

然后是多少微妙呢?

1/200 * 1000 000 应该是,跳一次需要这么多微妙.

就相当于代码中写的:

1000 000 /200 这个时间了,这个时间就是跳一次需要的微妙数.

这里设定了1秒跳200次,那么

1次就是1000 000 / 200 =5000 微妙 也就是5毫秒.

所以,如果想跳一次花1毫秒,那么

就需要把上面的200u改成1000就可以了

1000 000 /1000=1000微妙,也就是1毫秒

然后这里,就把计算出的,1微妙跳多少次,这个放到LOAD寄存器中,让它去倒数就可以了.

然后就是

这里再去初始化CTRL控制器的第1位,也就是开启中断,

然后再去初始化CTRL控制器的第0位,也就是使能滴答定时器.

注意,这里有个delay nus,也就是延时微妙.

然后

还有一个是延时毫秒,然后可以看看

这里有个delay_us,延时微妙这个函数

可以看到这里,如果要延时的数大于系统的(滴答定时器)一个周期需要的时间的话,

那么这里就使用系统的中断来延时,delay_ostimedly()

但是这里延时只能延时一整个周期的,剩余的,余数,就是还剩下没有延时的部分

这个时候,就要采用普通延时来做了,可以看到是调用的

delay_us,延时微妙这个函数

这里要注意:

使用

delay_us延时微妙,是不能发起任务调度的,

使用

delay_ms延时毫秒,如果时间小于任务周期的话,也是不能发起任务调度的.

然后下面的部分,是以前基础部分的延时方法,这里先不说了.

看我delay.c然后再看

usart.c和sys.c

可以看到这里

使用ucos的时候调用OSInEnter

然后下面是,要在中断里实现的自己的代码

然后使用中断以后,然后调用去退出中断.

可以去看看代码:

然后

如果咱们自己写UCOS的中断的实际上就是上面这样写,

中间写自己的代码

看看代码的部分,这里可以看到

然后看看,这里的这个函数led0_task,这个就是咱们说的实实在在干活的.

那么怎么把这些组合再一起呢?

就是在前面调用这个OSTaskCreate这个函数,进行创建的.

然后这个创建任务后面具体的还会说.

这里一般的都有死循环,除非是,只要求这个任务执行一次

然后这里

可以回去看看led的任务函数

这里,如果while死循环的话,那么,系统再怎么去执行其他的任务呢>?

可以看到这里有个

OSTimeDlyHMSM()这个函数,这个函数执行的时候,系统就会把CPU的资源,切换到给其他的任务去用了

就去执行其他任务了.系统是可以从这个死循环中切换到其他任务的,这个管理就不用咱们做了.

如果这样写,也就是没有任务切换的代码,那么程序很可能就死在这里了

这是新手会犯的错误.

当然如果是只需要执行一次的话,那么就不需要写while循环了.

当然首先咱们要写一个start_task这个是一个初始化的任务,用来,开启其他的

所有的任务.

可以看到这个任务很长,然后,这个任务咱们只希望他执行一次,也就是初期的时候

开启其他的任务,以后,后面就不运行了,这样的话

可以看到这个任务,在最后的时候,把自己挂起了.也就是这个任务只执行一次就可以了.

这里可以看到第一个1,2任务是必须要的,系统自动创建

其他的可以选择使用.

这里先看1,休眠态,这个意思是,比如我们写了一个函数,然后这个函数,没有再start_task这个函数

中去注册,调用,也就是说,这个函数就是不受,UCOSIII管理的,那么

这种的就是,只是编译的时候把这个函数,放到了cpu的flash中了,但是没有

被UCOSIII管理,所以是休眠态.

然后就绪态,这个是在start_task函数中注册了,也就是被UCOSIII管理的,并可以运行的函数任务

运行态就好说了,在运行的就是

然后等待态,也就是比如这里led0_tast这个函数

OSTimeDlyHMSM()

这个函数如果执行的时候,其实这个函数就是处于等待态的.

然后是中断服务态,也就是当函数执行的过程中,有中断打断了,就是中断服务态.

然后来看一下这个各种态的图

可以看到当通过OSTaskCreate()这个函数去把任务添加到UCOSIII的管理中的时候,休眠态的任务函数,就变成了就绪态了.

然后就绪态的函数可以通过OSTaskDel()这个函数来删除,也就是从UCOSIII的管理中删除这个任务.

这样他就又变成了休眠态了.

然后就绪态的任务还可以通过OS_TASK_SW()这个函数进行切换的时候,

或者其他的一些事件发生的时候,把这个任务函数变成运行态

然后运行态的任务函数,通过调用上面的那一堆的函数,可以变成等待态

可以看到其中一个就是OSTimeDly()这个函数.

然后等待态的这个任务函数,就可以通过调用OSTaskQPost()等下面的这些函数,再进入到就绪态.

然后运行态的函数,还可以通过被中断打断,变成中断服务态

中断服务态的任务函数,可以通过中断结束,变成运行态,也可以通过调用OSInitExit()这个函数

变成就绪状态

这个是整个的一个图

可以看到上面是一些参考的学习书籍.


 

猜你喜欢

转载自blog.csdn.net/lidew521/article/details/108456160
今日推荐