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

做不锈钢网站seo查询官网

做不锈钢网站,seo查询官网,wordpress的sitemap,男女做那个全面视频网站软件定时器就是"闹钟",你可以设置闹钟, 用软件定时器的话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/169953.html

相关文章:

  • 图书馆网站建设的项目报告青岛谷歌推广
  • 怎样建设网站最好百色seo关键词优化公司
  • 公职人员可以做公益网站吗百度模拟点击软件判刑了
  • 怎么自己做网站推广西安关键词网站排名
  • 北京朝阳区二手房出售信息肇庆seo外包公司
  • 如何做提卡网站搜索引擎链接
  • 烟台网站建设百度关键词快速排名
  • 做网站毕业答辩会问什么免费seo网站自动推广
  • 网站推广优化软件seo排名优化资源
  • 太原公司网站建设济南百度推广优化
  • 将网站做成logo怎么做网络营销产品的首选产品
  • 广州软件开发app淘宝seo优化
  • wordpress外贸推广seo经理招聘
  • 企业建站公司流程网站建设的重要性
  • 合肥网站建设晨飞长春模板建站代理
  • 做动态的网站的参考资料有哪些百度资源搜索平台官网
  • 旅游网站模板qq群排名优化
  • 网站正在建设模板如何快速推广网上国网
  • 中山大学精品课程网站湖南网站建设推广
  • 舟山企业网站建设批量优化网站软件
  • 网站设计怎么做毕业论文产品市场调研怎么做
  • 深圳网站制作公司多少钱开发小程序
  • 什么网站需要公安备案宁波网络推广外包
  • 贵州 政府网站建设规范网上全网推广
  • 清洁海绵的网站怎么做互联网怎么赚钱
  • 四川科隆建设有限公司网站常见的关键词
  • 每一天做网站网站点击量与排名
  • 做网站容易吧百度搜索资源
  • 杭州群游科技网站做的魔域百度关键词排名批量查询工具
  • 磁力引擎衡阳seo优化推荐