uCOSIII实时操作系统 八 软件定时器

news2025/7/19 14:29:26

目录

软件定时器概述

使用步骤:

创建软件定时器:

启动软件定时器:

停止软件定时器:

删除软件定时器:

单次定时器:

​编辑周期定时器:

无初始化延时:

有初始化延时:

软件定时器实验:


软件定时器概述

在学习单片机的的时候,会使用定时器来做很多事情,这个定时器时单片机自带的也就是硬件定时器,而UCOSIII内核提供了一个模拟定时器的机制类似于任务,但是占用资源少,只能做一些简单的定时控制,如可以定时器喂狗控灯。在软件定时器中绝对不能添加事件管理函数,阻塞等待函数。

使用步骤:

创建软件定时器:

利用OSTmrCreate()函数,函数原型如下:

参数:

 p_tmr,                软件定时器对象

p_name,              软件定时器的名字

dly,                      启动定时器后,延迟多长时间执行,默认隐含dly10ms

period,                 定时周期,默认隐含period10ms

opt:                      模式

OS_OPT_TMR_ONE_SHOT,软件定时器执行一遍

OS_OPT_TMR_PERIODIC,软件定时器周期性执行

p_callback,          软件定时器执行的回调函数 void MyCallback (OS_TMR *p_tmr, void *p_arg);

p_callback_arg,   传递参数给软件定时器的回调函数

p_err,                   返回错误码,没有错误的就返回OS_ERR_NONE

启动软件定时器:

函数原型如下:

参数:

p_tmr :软件定时器对象

p_err  :返回错误码,没有错误就返回OS_ERR_NONE

返回值:

 DEF_TRUE is the timer was started

DEF_FALSE if not or upon an error

停止软件定时器:

函数原型如下:

参数:

p_tmr 软件定时器对象

os_opt 默认参数,OS_OPT_TMR_NONE

p_callback_arg 填写OSTmrCreate创建时传递给软件定时器arg的参数

p_err 返回错误码,没有错误就返回OS_ERR_NONE

删除软件定时器:

函数原型:

参数:

 p_tmr,软件定时器对象

 p_err,返回错误码,没有错误的就返回OS_ERR_NONE

单次定时器:

使用OSTmrCreate()函数创建定时器参数时候把参数opt设置为OS_OPT_TMR_ONE_SHOT,就是创建的单次定时器。创建一个单次定时器以后,我们一旦调用OSTmrStart()函数定时器就会是从创建定义的dly开始倒计时直到减为0调用回调函数。

上图展示了单次定时器的运行,dly减到0的时候调用回调函数,到这里定时器就停止运行了不再做任何事,我们可以调用OSTmrStop()函数来删除这个运行完成的定时器,也可以重新调用OSTmrStart()函数来重新开启,如下图

周期定时器:

无初始化延时:

使用OSTmrCreate()函数创建定时器时把参数opt设置为OS_OPT_TMR_PERIODIC ,就是创建周期定时器。当计时器倒计数完成之后,定时器就会调用周期函数,并重置计数器开始下一轮定时,这样一直循环下去。如果使用OSTmrCreate函数创建定时器的时候,参数dly为0的话,那么定时器在每个周期开始时计数器的初始值就是period,如下图

有初始化延时:

在创建任务的时候可以创建带有初始化延时,初始化初始化延时就是使用OSTmrCreate()函数中的参数dly就是初始化延时,定时器的第一个周期是dly。当第一个周期完成后就用参数period作为周期值,主要流程如下图:

软件定时器实验:

任务要求:先两个任务,任务A和任务B,任务A用于创建两个定时器:是定时器1和定时器2,任务A还创建了另一个任务B。其中定时器 1 为周期定时器,初始延时为 200ms,以后的定时器周期为 1000ms,定时器 2 为单次定时器,延时为2000ms。

任务 B 作为按键检测任务,当 KEY_UP 键按下的时候,打开定时器 1;当 KEY0 按下的时候打开定时器 2;当 KEY1 按下的时候,同时关闭定时器 1 和 2;任务 B 还用来控制 LED0,使其闪烁,提示系统正在运行。

定时器 1 定时完成以后调用回调函数串口输出定时器1进入一次。定时器 2 是单次定时器,我们通过串口打印来观察单次定时器的运行情况。

实验效果:

代码历程:

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "includes.h"
#include "os_app_hooks.h"
#include "key.h"
//UCOSIII中以下优先级用户程序不能使用,ALIENTEK
//将这些优先级分配给了UCOSIII的5个系统内部任务
//优先级0:中断服务服务管理任务 OS_IntQTask()
//优先级1:时钟节拍任务 OS_TickTask()
//优先级2:定时任务 OS_TmrTask()
//优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask()
//优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask()

//创建任务A
//定义任务优先级
#define TASK_A_PRIO 3
//定义任务控制块
OS_TCB TASK_A_TCB;
//定义任务堆栈大小
#define TASK_A_STK_SIZE 128
//定义任务堆栈
CPU_STK TASK_A_STK[TASK_A_STK_SIZE];
//定义任务函数
void TASK_A(void *arg);

//创建任务B
//定义任务优先级
#define TASK_B_PRIO 4
//定义任务控制块
OS_TCB TASK_B_TCB;
//定义任务堆栈大小
#define TASK_B_STK_SIZE 128
//定义任务堆栈
CPU_STK TASK_B_STK[TASK_B_STK_SIZE];
//定义任务函数
void TASK_B(void *arg);

/
OS_TMR tmr1;//定时器1
OS_TMR tmr2;//定时器1
void tmr1_callback(void *p_tmr, void *p_arg); //定时器1回调函数
void tmr2_callback(void *p_tmr, void *p_arg); //定时器1回调函数



int main(void)
{
	OS_ERR err1;//错误码变量
	CPU_SR_ALLOC();//定义临界区需要的变量
	
	//硬件初始化
	delay_init();       //延时初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置
	uart_init(115200);    //串口波特率设置
	LED_Init();
	KEY_Init();
	
	OSInit(&err1);//初始化UCOSIII
	OS_CRITICAL_ENTER();//进入临界区代码
	
	//创建定时器1
	
	//创建开始任务1
	OSTaskCreate((OS_TCB 	* )&TASK_A_TCB,		//任务控制块
				 (CPU_CHAR	* )"main TASKA", 		//任务名字
                 (OS_TASK_PTR )TASK_A, 			//任务函数
                 (void		* )0,					//传递给任务函数的参数
                 (OS_PRIO	  )TASK_A_PRIO,     //任务优先级
                 (CPU_STK   * )&TASK_A_STK[0],	//任务堆栈基地址
                 (CPU_STK_SIZE)TASK_A_STK_SIZE/10,	//任务堆栈深度限位
                 (CPU_STK_SIZE)TASK_A_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 	* )&err1);				//存放该函数错误时的返回值
	
	OS_CRITICAL_EXIT();//退出临界区代码
	OSStart(&err1);//开启UCOSIII

	while(1);
}

//开始任务函数
void TASK_A(void *arg)
{
	OS_ERR err2_3;//错误码变量
	CPU_SR_ALLOC();//定义临界区需要的变量
	arg = arg;
	
	CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
   OSStatTaskCPUUsageInit(&err2_3);  	//统计任务                
#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,&err2_3);  
#endif	
	
//#if OS_CFG_APP_HOOKS_EN				//使用钩子函数
//	App_OS_SetAllHooks();			
//#endif
	
#if OS_CFG_SCHED_ROUND_ROBIN_EN
	//使用时间片轮转调度功能,时间片长度为一个时钟节拍即1*5=5ms
	OSSchedRoundRobinCfg(DEF_ENABLED,1,&err2_3);
#endif
	
	//创建定时器1 
	OSTmrCreate((OS_TMR		*)&tmr1,		//定时器1
                (CPU_CHAR	*)"tmr1",		//定时器名字
                (OS_TICK	 )20,			//20*10=200ms
                (OS_TICK	 )100,          //100*10=1000ms
                (OS_OPT		 )OS_OPT_TMR_PERIODIC, //周期模式
                (OS_TMR_CALLBACK_PTR)tmr1_callback,//定时器1回调函数
                (void	    *)0,			//参数为0
                (OS_ERR	    *)&err2_3);		//返回的错误
	//创建定时器2
	OSTmrCreate((OS_TMR		*)&tmr2,		//定时器1
                (CPU_CHAR	*)"tmr2",		//定时器名字
                (OS_TICK	 )200,			//200*10=2000ms
                (OS_TICK	 )0,          //
                (OS_OPT		 )OS_OPT_TMR_ONE_SHOT, //单次延时
                (OS_TMR_CALLBACK_PTR)tmr2_callback,//定时器2回调函数
                (void	    *)0,			//参数为0
                (OS_ERR	    *)&err2_3);		//返回的错误码
				

	OS_CRITICAL_ENTER();//进入临界区代码
	//创建开始任务B
	OSTaskCreate((OS_TCB 	* )&TASK_B_TCB,		//任务控制块
				 (CPU_CHAR	* )"main TASKB", 		//任务名字
                 (OS_TASK_PTR )TASK_B, 			//任务函数
                 (void		* )0,					//传递给任务函数的参数
                 (OS_PRIO	  )TASK_B_PRIO,     //任务优先级
                 (CPU_STK   * )&TASK_B_STK[0],	//任务堆栈基地址
                 (CPU_STK_SIZE)TASK_B_STK_SIZE/10,	//任务堆栈深度限位
                 (CPU_STK_SIZE)TASK_B_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 	* )&err2_3);				//存放该函数错误时的返回值
			 
								 
	OS_CRITICAL_EXIT();//退出临界区代码
	
	//任务一执行完函数之后删掉自身
	OSTaskDel((OS_TCB *)0,&err2_3);			 
}



void TASK_B(void *arg)
{
	u8 key,num;
	OS_ERR err_B;
	while(1)
	{
		key = KEY_Scan(0);
		switch(key)
		{
			case WKUP_PRES: //当key_up按下的话打开定时器1
					OSTmrStart(&tmr1,&err_B); //开启定时器1
					printf("开启定时器1\r\n");
			break ;
			
			case KEY0_PRES://当key0按下的话打开定时器2
					OSTmrStart(&tmr2,&err_B); //开启定时器2
					printf("开启定时器2\r\n");
			break ;
			
			case KEY1_PRES:
					OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err_B); //关闭定时器1
					OSTmrStop(&tmr2,OS_OPT_TMR_NONE,0,&err_B); //关闭定时器2
					printf("关闭定时器1和2\r\n");
			break ;	
		}
		num++;
		if(num==50)//每500msled闪烁一次
		{
			num=0;
			LED0 = ~LED0;
		}
		OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err_B);//延时10ms
	}
	
}


//定时器1回调函数
void tmr1_callback(void *p_tmr, void *p_arg)
{
	static u8 tmr1_num=0;
	tmr1_num++; //定时器1执行次数加1
	printf("定时器1进入一次\r\n");
}


//定时器2回调函数
void tmr2_callback(void *p_tmr, void *p_arg)
{
	static u8 tmr2_num = 0;
	tmr2_num++; //定时器2执行次数加1
	LED1 = ~LED1;
	printf("定时器2运行结束\r\n");
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1102697.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LabVIEW中使用Get LV Class Default Value 出现错误1498

LabVIEW中使用Get LV Class Default Value 出现错误1498 在LabVIEW中开发了一个应用程序,其中包含可以在执行时动态配置插件的基类。生成可执行文件后,当应用程序要执行子类时,收到以下错误信息。 Error1498 occurred at Gen LV Class Defa…

Sandboxie+Buster Sandbox Analyzer打造个人沙箱

一、运行环境和需要安装的软件 实验环境:win7_x32或win7_x64 用到的软件:WinPcap_4_1_3.exe、Sandboxie-3-70.exe、Buster Sandbox Analyzer 重点是Sandboxie必须是3.70版本。下载地址:https://github.com/sandboxie-plus/sandboxie-old/blo…

Linux性能优化--使用性能工具发现问题

9.0 概述 本章主要介绍综合运用之前提出的性能工具来缩小性能问题产生原因的范围。阅读本章后,你将能够: 启动行为异常的系统,使用Linux性能工具追踪行为异常的内核函数或应用程序。启动行为异常的应用程序,使用Linux性能工具追…

浪子带你【25天】玩转Python——期中福利

人生苦短,我用Python! 目录 回顾上文 正文 最后的话 回顾上文 浪子带你【25天】玩转Python——5.面向对象编程(类和对象)-CSDN博客 正文 哈喽,不知不觉中,浪子的【25天】玩转Python已经开播13天啦&#xff01…

【c++智能指针】

目录 一、智能指针的使用及原理二、auto_ptr三、unique_ptr三、shared_ptr四、weak_ptr五、定制删除器 一、智能指针的使用及原理 RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网…

新型的终端复用器 tmux

以前遇到长时间执行任务时,一般是使用nohup加后台运行,但是涉及到少量代码编写。 同事介绍了一个screen命令,根据文档,此命令已经过时,最新的命令是tmux。 tmux的介绍文档,RedHat的这一篇非常不错。 在文…

vue ref和$refs获取dom元素

vue ref和$refs获取dom元素 **创建 工程: H:\java_work\java_springboot\vue_study ctrl按住不放 右键 悬着 powershell H:\java_work\java_springboot\js_study\Vue2_3入门到实战-配套资料\01-随堂代码素材\day04\准备代码\14-ref和$refs获取dom对象 vue --ve…

Kotlin中的数值类型

在Kotlin中,Byte、Short、Int、Long、Float和Double是基本数据类型,用于表示不同范围和精度的数值。 Byte(字节):Byte类型是8位有符号整数类型,取值范围为-128到127。在Kotlin中,可以使用字面值…

《深入浅出OCR》第三章:OCR文字检测

✨专栏介绍: 经过几个月的精心筹备,本作者推出全新系列《深入浅出OCR》专栏,对标最全OCR教程,具体章节如导图所示,将分别从OCR技术发展、方向、概念、算法、论文、数据集等各种角度展开详细介绍。 👨‍💻面向对象: 本篇前言知识主要介绍深度学习知识,全面总结知知识…

Linux Zabbix企业级监控平台+cpolar实现远程访问

文章目录 前言1. Linux 局域网访问Zabbix2. Linux 安装cpolar3. 配置Zabbix公网访问地址4. 公网远程访问Zabbix5. 固定Zabbix公网地址 前言 Zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。能监视各种网络参数,保证服务器系…

C++stack和queue模拟实现以及deque的介绍

stack和queue介绍以及模拟实现 1.stack1.1stack的介绍1.2stack的使用 2.queue2.1queue的介绍2.2queue的使用 3.容器适配器3.1什么是适配器 4.stack模拟实现5.queue的模拟实现6.deque(双端队列) 1.stack 1.1stack的介绍 stack的文档介绍 stack是一种容…

软信天成:流程管理是企业精细化管理的一大利器

流程管理(BPM)是指组织和管理内部或跨部门的工作流程,主要包括设计、建模、执行、监控和优化业务流程,确保工作按照标准化的步骤进行,从而提高效率、降低成本,促进业务增长。 一、流程管理生命周期五大步骤…

xml文件报错 ORA-00907: 缺失右括号

原来的sql 更改之后 加一个select * from ()

VScode platformio的使用

一、platformio 工程创建 打开vscode界面你会发现左下多了个家的小图标,点击这里就可以进入platformio。 在右侧Quick Access栏中,有4个选项。可以看得出来,我们这里直接点击创建一个新的工程。 点击New Project打开project配置界面&#x…

Android---自定义View

当 Android SDK 中提供的系统 UI 控件无法满足业务需求时,需要考虑自己实现 UI 控件。掌握自定义控件,是理解整套 Android 渲染体系的基础。自定义 UI 控件有2种方式: 继承系统提供的成熟控件(比如 LinearLayout、RelativeLayout、…

美国跨境金融科技公司【Zolve】完成1亿美元融资

来源:猛兽财经 作者:猛兽财经 猛兽财经获悉,总部位于美国纽约的跨境金融科技公司Zolve近期宣布已经完成1亿美元融资。 本轮融资由CIM投资 该公司打算将这笔资金用于在英国、加拿大和澳大利亚的进一步扩张。 Zolve由创始人Raghunandan G领导&…

自由程序员想接私活?那你还不得知道这几个接单平台!最后一个就是宝藏!!

相信喜欢搞钱的程序员都知道,平常在平台上接点私活,利用闲暇时间接单是搞钱的常用套路,可是你确定你选对平台了吗?不管你是刚准备接单的小白,还是已经干了一段时间的老油条,都建议你看完本期文章&#xff0…

Spring框架(三)

1、代理模式: 二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标…

【译】快速开始 Compose 跨平台项目

原文: Compose Multiplatform application 作者:JetBrains 注意 Compose Multiplatform 中的 iOS 部分目前处于 Alpha 状态。以后可能会有不兼容的更改,届时也许需要手动进行迁移。 你可以使用这个模板来开发同时支持桌面、安卓和 iOS 的跨平…

极品三国新手攻略之进阶篇

尊敬的主公大人您好,首先恭喜您在游戏中取得的不俗成绩,相信您已经熟练掌握了不少玩法。今天,我们给大家奉上一份极品三国新手攻略之进阶篇,希望能为您提供有力的帮助。本篇攻略将为您深入分析游戏中武将、装备、试炼塔以及神兵等…