当前位置: 首页 > wzjs >正文

凡科网页登录西安关键词排名优化

凡科网页登录,西安关键词排名优化,没有网站可以做cpa,网站建设单位不给数据库软件定时器就是"闹钟",你可以设置闹钟, 用软件定时器的话USE_TIMER要设置为1 在30分钟后让你起床工作每隔1小时让你例行检查机器运行情况 软件定时器也可以完成两类事情: 在"未来"某个时间点,运行函数周期…

软件定时器就是"闹钟",你可以设置闹钟,

用软件定时器的话USE_TIMER要设置为1

  • 在30分钟后让你起床工作
  • 每隔1小时让你例行检查机器运行情况

软件定时器也可以完成两类事情:

  • 在"未来"某个时间点,运行函数
  • 周期性地运行函数

日常生活中我们可以定无数个"闹钟",这无数的"闹钟"要基于一个真实的闹钟。

在FreeRTOS里,我们也可以设置无数个"软件定时器",它们都是基于系统滴答中断(Tick Interrupt)。

本章涉及如下内容:

  • 软件定时器的特性
  • Daemon Task
  • 定时器命令队列
  • 一次性定时器、周期性定时器的差别
  • 怎么操作定时器:创建、启动、复位、修改周期

16.2.2 守护任务的调度(就是定时管理任务,用来唤醒其他任务的任务)

守护任务的调度,跟普通的任务并无差别。当守护任务是当前优先级最高的就绪态任务时,它就可以运行。它的工作有两类:

  • 处理命令:从命令队列里取出命令、处理
  • 执行定时器的回调函数

能否及时处理定时器的命令、能否及时执行定时器的回调函数,严重依赖于守护任务的优先级。下面使用2个例子来演示。

例子1:守护任务的优先性级较低

  • t1:Task1处于运行态,守护任务处于阻塞态。 守护任务在这两种情况下会退出阻塞态切换为就绪态:命令队列中有数据、某个定时器超时了。 至于守护任务能否马上执行,取决于它的优先级。
  • t2:Task1调用 xTimerStart() 要注意的是,xTimerStart() 只是把"start timer"的命令发给"定时器命令队列",使得守护任务退出阻塞态。 在本例中,Task1的优先级高于守护任务,所以守护任务无法抢占Task1。
  • t3:Task1执行完 xTimerStart() 但是定时器的启动工作由守护任务来实现,所以*xTimerStart()*返回并不表示定时器已经被启动了。
  • t4:Task1由于某些原因进入阻塞态,现在轮到守护任务运行。 守护任务从队列中取出"start timer"命令,启动定时器。
  • t5:守护任务处理完队列中所有的命令,再次进入阻塞态。Idel任务时优先级最高的就绪态任务,它执行。
  • 注意:假设定时器在后续某个时刻tX超时了,超时时间是"tX-t2",而非"tX-t4",从 xTimerStart() 函数被调用时算起。

例子2:守护任务的优先性级较高

  • t1:Task1处于运行态,守护任务处于阻塞态。 守护任务在这两种情况下会退出阻塞态切换为就绪态:命令队列中有数据、某个定时器超时了。 至于守护任务能否马上执行,取决于它的优先级。

  • t2:Task1调用xTimerStart() 要注意的是,*xTimerStart()只是把"start timer"的命令发给"定时器命令队列",使得守护任务退出阻塞态。 在本例中,守护任务的优先级高于Task1,所以守护任务抢占Task1,守护任务开始处理命令队列。 Task1在执行xTimerStart()*的过程中被抢占,这时它无法完成此函数。

  • t3:守护任务处理完命令队列中所有的命令,再次进入阻塞态。 此时Task1是优先级最高的就绪态任务,它开始执行。

  • t4:Task1之前被守护任务抢占,对*xTimerStart()*的调用尚未返回。现在开始继续运行次函数、返回。

  • t5:Task1由于某些原因进入阻塞态,进入阻塞态。Idel任务时优先级最高的就绪态任务,它执行。

注意,定时器的超时时间是基于调用 xTimerStart() 的时刻tX,而不是基于守护任务处理命令的时刻tY。假设超时时间是10个Tick,超时时间是"tX+10",而非"tY+10"。

16.2.3 回调函数

定时器的回调函数的原型如下:

void ATimerCallback( TimerHandle_t xTimer );

定时器的回调函数是在守护任务中被调用的,守护任务不是专为某个定时器服务的,它还要处理其他定时器。

所以,定时器的回调函数不要影响其他人:

  • 回调函数要尽快实行,不能进入阻塞状态
  • 不要调用会导致阻塞的API函数,比如 vTaskDelay()
  • 可以调用 xQueueReceive() 之类的函数,但是超时时间要设为0:即刻返回,不可阻塞

16.3 软件定时器的函数

根据定时器的状态转换图,就可以知道所涉及的函数:

16.3.1 创建

要使用定时器,需要先创建它,得到它的句柄。

有两种方法创建定时器:动态分配内存、静态分配内存。函数原型如下:

/* 使用动态分配内存的方法创建定时器* pcTimerName:定时器名字, 用处不大, 尽在调试时用到* xTimerPeriodInTicks: 周期, 以Tick为单位* uxAutoReload: 类型, pdTRUE表示自动加载, pdFALSE表示一次性* pvTimerID: 回调函数可以使用此参数, 比如分辨是哪个定时器* pxCallbackFunction: 回调函数* 返回值: 成功则返回TimerHandle_t, 否则返回NULL*/
TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks,const UBaseType_t uxAutoReload,void * const pvTimerID,TimerCallbackFunction_t pxCallbackFunction );/* 使用静态分配内存的方法创建定时器* pcTimerName:定时器名字, 用处不大, 尽在调试时用到* xTimerPeriodInTicks: 周期, 以Tick为单位
(不直观可以用pdMS_TO_TICKS()函数可以把毫秒转换为TICK)* uxAutoReload: 类型, pdTRUE表示自动加载, pdFALSE表示一次性* pvTimerID: 回调函数可以使用此参数, 比如分辨是哪个定时器* pxCallbackFunction: 回调函数* pxTimerBuffer: 传入一个StaticTimer_t结构体, 将在上面构造定时器* 返回值: 成功则返回TimerHandle_t, 否则返回NULL*/
TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,TickType_t xTimerPeriodInTicks,UBaseType_t uxAutoReload,void * pvTimerID,TimerCallbackFunction_t pxCallbackFunction,StaticTimer_t *pxTimerBuffer );

回调函数的类型是:

void ATimerCallback( TimerHandle_t xTimer );typedef void (* TimerCallbackFunction_t)( TimerHandle_t xTimer );

16.3.2 删除

动态分配的定时器,不再需要时可以删除掉以回收内存。删除函数原型如下:

/* 删除定时器* xTimer: 要删除哪个定时器* xTicksToWait: 超时时间* 返回值: pdFAIL表示"删除命令"在xTicksToWait个Tick内无法写入队列*        pdPASS表示成功
*/
BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait );

定时器的很多API函数,都是通过发送"命令"到命令队列,由守护任务来实现。

如果队列满了,"命令"就无法即刻写入队列。我们可以指定一个超时时间 xTicksToWait ,等待一会。

16.3.3 启动/停止

启动定时器就是设置它的状态为运行态(Running、Active)。

停止定时器就是设置它的状态为冬眠(Dormant),让它不能运行。

涉及的函数原型如下:

/* 启动定时器* xTimer: 哪个定时器* xTicksToWait: 超时时间* 返回值: pdFAIL表示"启动命令"在xTicksToWait个Tick内无法写入队列*        pdPASS表示成功*/
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );/* 启动定时器(ISR版本)* xTimer: 哪个定时器* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,*                            如果守护任务的优先级比当前任务的高,*                            则"*pxHigherPriorityTaskWoken = pdTRUE",*                            表示需要进行任务调度* 返回值: pdFAIL表示"启动命令"无法写入队列*        pdPASS表示成功*/
BaseType_t xTimerStartFromISR(   TimerHandle_t xTimer,BaseType_t *pxHigherPriorityTaskWoken );/* 停止定时器* xTimer: 哪个定时器* xTicksToWait: 超时时间* 返回值: pdFAIL表示"停止命令"在xTicksToWait个Tick内无法写入队列*        pdPASS表示成功*/
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait );/* 停止定时器(ISR版本)* xTimer: 哪个定时器* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,*                            如果守护任务的优先级比当前任务的高,*                            则"*pxHigherPriorityTaskWoken = pdTRUE",*                            表示需要进行任务调度* 返回值: pdFAIL表示"停止命令"无法写入队列*        pdPASS表示成功*/
BaseType_t xTimerStopFromISR(    TimerHandle_t xTimer,BaseType_t *pxHigherPriorityTaskWoken );

注意,这些函数的 xTicksToWait 表示的是,把命令写入命令队列的超时时间。命令队列可能已经满了,无法马上把命令写入队列里,可以等待一会。

xTicksToWait 不是定时器本身的超时时间,不是定时器本身的"周期"。

创建定时器时,设置了它的周期(period)。xTimerStart() 函数是用来启动定时器。假设调用 xTimerStart() 的时刻是tX,定时器的周期是n,那么在tX+n时刻定时器的回调函数被调用。

如果定时器已经被启动,但是它的函数尚未被执行,再次执行 xTimerStart() 函数相当于执行 xTimerReset() ,重新设定它的启动时间。

还有一个更简单的函数,如果你是在CubeMX里创建的定时器

osTimerStart(任务句柄,定时时间ms)

16.3.4 复位

从定时器的状态转换图可以知道,使用 xTimerReset() 函数可以让定时器的状态从冬眠态转换为运行态,相当于使用 xTimerStart() 函数。

如果定时器已经处于运行态,使用 xTimerReset() 函数就相当于重新确定超时时间。假设调用 xTimerReset() 的时刻是tX,定时器的周期是n,那么tX+n就是重新确定的超时时间。

复位函数的原型如下:

/* 复位定时器* xTimer: 哪个定时器* xTicksToWait: 超时时间* 返回值: pdFAIL表示"复位命令"在xTicksToWait个Tick内无法写入队列*        pdPASS表示成功*/
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );/* 复位定时器(ISR版本)* xTimer: 哪个定时器* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,*                            如果守护任务的优先级比当前任务的高,*                            则"*pxHigherPriorityTaskWoken = pdTRUE",*                            表示需要进行任务调度* 返回值: pdFAIL表示"停止命令"无法写入队列*        pdPASS表示成功*/
BaseType_t xTimerResetFromISR(   TimerHandle_t xTimer,BaseType_t *pxHigherPriorityTaskWoken );

16.3.5 修改周期

从定时器的状态转换图可以知道,使用 xTimerChangePeriod() 函数,处理能修改它的周期外,还可以让定时器的状态从冬眠态转换为运行态。

修改定时器的周期时,会使用新的周期重新计算它的超时时间。假设调用 xTimerChangePeriod() 函数的时间tX,新的周期是n,则tX+n就是新的超时时间。

相关函数的原型如下:

/* 修改定时器的周期* xTimer: 哪个定时器* xNewPeriod: 新周期* xTicksToWait: 超时时间, 命令写入队列的超时时间 * 返回值: pdFAIL表示"修改周期命令"在xTicksToWait个Tick内无法写入队列*        pdPASS表示成功*/
BaseType_t xTimerChangePeriod(   TimerHandle_t xTimer,TickType_t xNewPeriod,TickType_t xTicksToWait );/* 修改定时器的周期* xTimer: 哪个定时器* xNewPeriod: 新周期* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,*                            如果守护任务的优先级比当前任务的高,*                            则"*pxHigherPriorityTaskWoken = pdTRUE",*                            表示需要进行任务调度* 返回值: pdFAIL表示"修改周期命令"在xTicksToWait个Tick内无法写入队列*        pdPASS表示成功*/
BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer,TickType_t xNewPeriod,BaseType_t *pxHigherPriorityTaskWoken );

16.3.6 定时器ID

定时器的结构体如下,里面有一项 pvTimerID ,它就是定时器ID:

怎么使用定时器ID,完全由程序来决定:

  • 可以用来标记定时器,表示自己是什么定时器
  • 可以用来保存参数,给回调函数使用

它的初始值在创建定时器时由 xTimerCreate() 这类函数传入,后续可以使用这些函数来操作:

  • 更新ID:使用 vTimerSetTimerID() 函数
  • 查询ID:查询 pvTimerGetTimerID() 函数

这两个函数不涉及命令队列,它们是直接操作定时器结构体。

函数原型如下:

/* 获得定时器的ID* xTimer: 哪个定时器* 返回值: 定时器的ID*/
void *pvTimerGetTimerID( TimerHandle_t xTimer );/* 设置定时器的ID* xTimer: 哪个定时器* pvNewID: 新ID* 返回值: 无*/
void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID );
http://www.dtcms.com/wzjs/62162.html

相关文章:

  • 湛江网站制作搜索引擎技术包括哪些
  • 驻马店网站网站建设推广关键词排名查询
  • 上海营销型网站制作搜索引擎优化师工资
  • 网站维护的重要性百度公司有哪些部门
  • 微网站如何做微信支付宝支付宝支付接口搜索引擎营销是什么
  • 网站搭建中单页面百度统计代码安装位置
  • 佛山优化网站公司百度地图疫情实时动态
  • 中央两学一做网站行业关键词
  • 常州中环做网站多少钱一年的百度指数
  • 免费php外贸网站模板快速整站优化
  • flash怎么做电子书下载网站网络营销的5种营销方式
  • 大气简约企业网站模板企业类网站有哪些例子
  • 青岛html5网站制作网络营销推广方案策划
  • 官方网站免费建设汕头seo外包平台
  • 企业做网站大数据精准营销系统
  • 杭州 企业 建网站windows优化大师靠谱吗
  • 设计asp网站惠州seo全网营销
  • 济南想做网站网络营销怎么做
  • 太原疫情最新信息国内seo公司排名
  • wordpress 自带评论武汉seo计费管理
  • 网站内容建设的核心和根本是太原做网站的
  • 怎么建造网站合肥网站建设程序
  • 新公司如何做网站怎么寻找网站关键词并优化
  • dw2019怎么做网站seo研究
  • 绍兴市政府门户网站怎么才能让百度收录网站
  • 日本做a的动画视频在线观看网站经典的软文广告
  • 这个网站中有网名做会计的吗 了解一下排名公式
  • dw网页制作成品代码加图片惠州seo计费
  • 免费网站是如何盈利的国内新闻最新消息今天
  • 建筑公司网站页面图片百度下载正版