STC8H库函数使用(2)——任务调度主循环

文章介绍了如何利用定时器0设定1ms的时间基准进行任务调度。每个任务在结构体数组中定义状态、计数器、周期和执行函数。当定时器0中断时,调用任务标记回调函数,更新任务状态并决定何时执行任务。任务处理回调函数检查任务状态,如果为1则执行相应函数。
摘要由CSDN通过智能技术生成

 上图是官方的说明,系统通过定时器0设定1ms的时间作为各个任务的调度基准时钟,在任务的组件数组里面定义每个任务的的状态、计数器、周期、执行函数

首先咱们看第一句话,定时器0作为任务调度的基准时钟。定时器0是在系统初始化的时候就开启了一个1ms一次的中断。

第二句话任务组件数组里定义里面定义每个任务的的状态、计数器、周期、执行函数。这句话告诉我们Task_Comps[]是一个任务组件数组。查看TASK_COMPONENTS的定义是一个结构体,实际上Task_Comps[]就是一个结构体数组。

typedef struct 
{
	u8 Run;               //任务状态:Run/Stop
	u16 TIMCount;         //定时计数器
	u16 TRITime;          //重载计数器
	void (*TaskHook) (void); //任务函数
} TASK_COMPONENTS;       

      通过typedef struct 方式声明结构体TASK_COMPONENTS,然后用TASK_COMPONENTS创建 Task_Comps[]结构体数组并赋值。注意通过typedef struct 方式声明的结构体TASK_COMPONENTS使用时相当于struct TASK_COMPONENTS。结构体里面的void (*TaskHook) (void)是一个函数指针,需要传一个无参无返回值的函数地址进去,因为函数名本身就是指针,所以直接传进去函数名就可以了。

static TASK_COMPONENTS Task_Comps[]=
{
//状态  计数  周期  函数
	{0, 250, 250, Sample_Lamp},				/* task 1 Period: 250ms */
	{0, 500, 500, Sample_ADtoUART},		/* task 2 Period: 500ms */
	/* Add new task here */
};

下面这句话是算出有几个任务

u8 Tasks_Max = sizeof(Task_Comps)/sizeof(Task_Comps[0]);

然后看下一句, 计数器每ms减1,为0时设置状态位,并将周期时间重载到计数器里。我们看一下是怎么实现的,首先计数器每ms减1上面说了是通过定时器0中断实现的,我们看一下定时器0的中断函数。

void Timer0_ISR_Handler (void) interrupt TIMER0_VECTOR		//进中断时已经清除标志
{
  Task_Marks_Handler_Callback();	//任务标记回调函数
}

定时器0调用了Task_Marks_Handler_Callback()任务标记回调函数,因为定时器0   1ms产生一次中断,所以这个任务标记回调函数就是1ms运行一次。下面看一下任务回调函数:

void Task_Marks_Handler_Callback(void)
{
	u8 i;
	for(i=0; i<Tasks_Max; i++)
	{
		if(Task_Comps[i].TIMCount)    /* If the time is not 0 */
		{
			Task_Comps[i].TIMCount--;  /* Time counter decrement */
			if(Task_Comps[i].TIMCount == 0)  /* If time arrives */
			{
				/*Resume the timer value and try again */
				Task_Comps[i].TIMCount = Task_Comps[i].TRITime;  
				Task_Comps[i].Run = 1;    /* The task can be run */
			}
		}
	}
}

 任务回调函数每次运行,通过for(i=0; i<Tasks_Max; i++)循环每个任务结构体,如果这个任务的定时计数器不是0,定时计数器减1,如果定时计数器为0了,那就把重载计数器的值赋给定时计数器,然后把任务状态置1,表示这个任务需要运行一下了。

最后一句话,任务处理函数检查每个任务的状态,如果置位的话执行对应函数。需要运行的任务在任务处理回调函数void Task_Pro_Handler_Callback(void)中处理,我们先看一下主函数

void main(void)
{
	SYS_Init();

	while (1)
	{
    Task_Pro_Handler_Callback();
	}
}

进入主函数后,先运行系统初始化SYS_Init()来初始化定时器0,开启1ms一次的定时器中断和总中断,然后进入while循环调用任务处理回调函数。也就是说这个任务处理函数是只要任务状态置1了,就可以马上去处理这个任务,下面看一下任务处理函数:

void Task_Pro_Handler_Callback(void)
{
	u8 i;
	for(i=0; i<Tasks_Max; i++)
	{
		if(Task_Comps[i].Run) /* If task can be run */
		{
			Task_Comps[i].Run = 0;    /* Flag clear 0 */
			Task_Comps[i].TaskHook();  /* Run task */
		}
	}
}

任务处理函数很好理解,每个人任务循环一边,只要任务状态 Task_Comps[i].Run为1,清零状态位Task_Comps[i].Run = 0,然后运行任务Task_Comps[i].TaskHook()。

STC32库函数是指适用于STC32单片机的库函数集合,通过这些库函数,可以方便地实现各种功能。以下是关于STC32库函数使用说明。 1. 引用库函数:在使用STC32库函数之前,需要在代码中包含相应的头文件。例如,要使用ADC功能,需要包含"stc15f2k60s2.h"头文件。 2. 初始化设置:在使用某个功能之前,需要进行初始化设置。例如,使用ADC前需要确保ADC的引脚和模式设置正确。 3. 函数调用:通过调用库函数实现特定的功能。不同的功能需要调用不同的函数。例如,要实现ADC测量,需要调用ADC_Start函数来开始测量,然后通过ADC_GetResult函数获取测量结果。 4. 函数参数:函数调用时可能需要传入一些参数。这些参数会影响函数的行为和结果。例如,ADC_Init函数用来初始化ADC模块,其中可能需要设置采样率、参考电压等参数。 5. 函数返回值:有些函数会返回一个值,用来表示函数执行的结果或返回的数据。例如,ADC_GetResult函数会返回测量结果。 6. 注意事项:在使用STC32库函数时,需要注意一些事项。例如,在使用定时器时,可能需要关闭中断以避免操作的同时发生中断。 总结:STC32库函数是一组适用于STC32单片机的函数集合,通过这些函数可以实现各种功能。使用时需要引用头文件,进行初始化设置,并通过调用函数来实现特定的功能。需要注意参数的设置和返回值的处理。在使用过程中需要注意一些事项,以确保正确的功能实现。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老赵aaa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值