单片机裸机下的应用程序模拟OS框架

时间片轮询法

  1. 设计一个结构体:// 任务结构
typedef struct _TASK_COMPONENTS 
{ 
	uint8 Run;                 // 程序运行标记:0-不运行,1运行 
	uint8 Timer;               // 计时器 
	uint8 ItvTime;             // 任务运行间隔时间 
	void (*TaskHook)(void);    // 要运行的任务函数 
} TASK_COMPONENTS;             // 任务定义这个结构体的设计非常重要,一个用4个参数,注释说的非常详细,这里不在描述。
  1. 任务运行标志出来,此函数就相当于中断服务函数,需要在定时器的中断服务函数中调用此函数,这里独立出来,便于移植和理解。初始化定时器,这里假设定时器的定时中断为1ms(当然你可以改成10ms,这个和操作系统一样,中断过于频繁效率就低,中断太长,实时性差)。
/************************************************************************************** 
 * FunctionName   : TaskRemarks() 
 * Description    : 任务标志处理 
 * EntryParameter : None 
 * ReturnValue    : None 
**************************************************************************************/ 
void TaskRemarks(void) 
{ 
	uint8 i;   
    for (i = 0; i < TASKS_MAX; i++)                            // 逐个任务时间处理 
	{ 
		if (TaskComps[i].Timer)                                // 时间不为0 
		{ 
			TaskComps[i].Timer--;                              // 减去一个节拍 
			if (TaskComps[i].Timer == 0)                       // 时间减完了 
			{ 
				TaskComps[i].Timer = TaskComps[i].ItvTime;     // 恢复计时器值,从新下一次 
				TaskComps[i].Run = 1;                          // 任务可以运行 
			} 
		} 
	} 
}
  1. 任务处理:此函数就是判断什么时候该执行哪一个任务了,实现任务的管理操作,应用者只需要在main()函数中调用此函数就可以了,并不需要去分别调用和处理任务函数。
/************************************************************************************** 
* FunctionName   : TaskProcess() 
* Description    : 任务处理 
* EntryParameter : None 
* ReturnValue    : None 
**************************************************************************************/ 
void TaskProcess(void) 
{ 
	uint8 i;    
	for (i = 0; i < TASKS_MAX; i++)        // 逐个任务时间处理 
	{ 
		if (TaskComps[i].Run)              // 时间不为0 
		{ 
			TaskComps[i].TaskHook();       // 运行任务 
			TaskComps[i].Run = 0;          // 标志清0 
		} 
	} 
}

下面就说说怎样应用吧,假设我们有三个任务:时钟显示,按键扫描,和工作状态显示。
4. 任务列表:

typedef enum _TASK_LIST 
{ 
	TASK_DISP_CLOCK,        // 显示时钟 
	TASK_KEY_SAN,           // 按键扫描 
	TASK_DISP_WS,           // 工作状态显示 
	// 这里添加你的任务……
	TASKS_MAX               // 总的可供分配的定时任务数目 
} TASK_LIST;
  1. 定义一个上面定义的那种结构体变量:
/*定义任务数*/
TASK_COMPONENTS TaskComps[TASKS_MAX];

/************************************************************************************** 
* FunctionName   : TaskRemarks() 
* Description    : 任务初始化
* EntryParameter : None 
* ReturnValue    : None 
* 时钟中断周期为 5ms
**************************************************************************************/ 
void TaskInit(void)
{
     TaskComps[TASK_DISP_CLOCK].Run = 0;
	 TaskComps[TASK_DISP_CLOCK].Timer = 4;
	 TaskComps[TASK_DISP_CLOCK].ItvTime = 4;             /*时间根据定时器中断时间而定*/
	 TaskComps[TASK_DISP_CLOCK].TaskHook = TaskKeySan;
	
	 TaskComps[TASK_KEY_SAN].Run = 0;
	 TaskComps[TASK_KEY_SAN].Timer = 6;
	 TaskComps[TASK_KEY_SAN].ItvTime = 6;               /*时间根据定时器中断时间而定*/
	 TaskComps[TASK_KEY_SAN].TaskHook = TaskDispStatus;
	
	 TaskComps[TASK_DISP_WS].Run = 0;
	 TaskComps[TASK_DISP_WS].Timer = 200;
	 TaskComps[TASK_DISP_WS].ItvTime = 200;               /*时间根据定时器中断时间而定*/
	 TaskComps[TASK_DISP_WS].TaskHook = TaskDisplayClock;
}

在定义变量时,我们已经初始化了值,这些值的初始化,非常重要,跟具体的执行时间优先级等都有关系,这个需要自己掌握。
①大概意思是,我们有三个任务,每1s执行一下时钟显示,因为我们的时钟最小单位是1s,所以在秒变化后才显示一次就够了。
②由于按键在按下时会产生抖动,而我们知道一般按键的抖动大概是20ms,那么我们在顺序执行的函数中一般是延伸20ms,而这里我们每20ms扫描一次,是非常不错的处理,即达到了消抖的目的,也不会漏掉按键输入。
③为了能够显示按键后的其他提示和工作界面,我们这里设计每30ms显示一次,如果你觉得反应慢了,你可以让这些值小一点。
后面的名称是对应的函数名,必须在应用程序中编写这函数名称和这三个一样的任务。

  1. 编写任务函数:
/************************************************************************************** 
* FunctionName   : TaskDisplayClock() 
* Description    : 显示任务* EntryParameter : None 
* ReturnValue    : None 
**************************************************************************************/ 
void TaskDisplayClock(void) 
{ 
}
/************************************************************************************** 
* FunctionName   : TaskKeySan() 
* Description    : 扫描任务 
* EntryParameter : None 
* ReturnValue    : None 
**************************************************************************************/ 
void TaskKeySan(void) 
{
}
/************************************************************************************** 
* FunctionName   : TaskDispStatus() 
* Description    : 工作状态显示 
* EntryParameter : None 
* ReturnValue    : None 
**************************************************************************************/ 
void TaskDispStatus(void) 
{
} 
  1. 主函数:
/************************************************************************************** 
* FunctionName   : main() 
* Description    : 主函数 
* EntryParameter : None 
* ReturnValue    : None 
**************************************************************************************/ 
int main(void) 
{ 
    TaskInit();                 /*任务初始化*/
	InitSys();                  // 初始化   
	while (1) 
	{ 
		TaskProcess();         // 任务处理 
	} 
}

注意任务之间进行数据传递时,需要采用全局变量,除此之外还需要注意划分任务以及任务的执行时间,在编写任务时,尽量让任务尽快执行完成。

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单片机的C语言应用程序设计下载通常是指从互联网上下载相关的开发工具和编程软件,以便进行单片机的C语言程序编写和调试。 在进行单片机的C语言应用程序设计前,首先需要下载与目标单片机兼容的编程软件或开发环境。针对不同的单片机和开发商,常用的开发工具有Keil、IAR、MPLAB和Arduino等。这些软件通常可以从官方网站上下载,也可以通过第三方提供的下载链接获取。 下载完成后,需要安装并配置相应的开发工具。安装时,按照软件提供的安装向导进行操作,选择合适的安装目录和组件,完全安装后即可使用。安装完成后,需要根据具体的单片机型号和芯片架构进行配置,包括选择编译器、链接器和调试工具等。 完成安装和配置后,就可以开始进行单片机的C语言应用程序设计了。首先需要创建一个新的工程或项目,然后在工程中添加源文件和头文件。编写C语言程序时,可以使用相应的开发工具提供的编辑器、终端窗口和调试器等功能。编写完成后,通过编译、链接和下载等步骤将程序烧录到目标单片机中。 在进行单片机的C语言应用程序设计时,需要掌握一定的C语言基础知识和单片机的硬件特性。同时,还需要了解具体的单片机型号和技术文档,以便正确地使用开发工具和编程接口。 总之,单片机的C语言应用程序设计下载是为了获取相应的开发工具和软件,方便进行C语言程序的编写和调试。通过下载并配置好开发环境后,即可进行单片机的C语言应用程序设计工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值