硬件——STM32 , 软件框架
单片机应用程序的框架大概有三种:
1,简单的前后台顺序执行程序.
2,时间片轮询法.
3,应用操作系统.
下面我们主要来讲解时间片轮询法:
在这里我们先介绍一下定时器的复用功能。就是使用1个定时器,可以是任意的定时器,这里不做特殊说明,下面假设有3个任务,那么我们应该做如下工作:
1. 初始化定时器,这里假设定时器的定时中断为1ms(当然你可以改成10ms,这个和操作系统一样,中断过于频繁效率就低,中断太长,实时性差)。
2. 定义一个数值:
#define TASK_NUM (3) // 这里定义的任务数为3,表示有三个任务会使用此定时器定时
uint16 TaskCount[TASK_NUM] ; // 这里为三个任务定义三个变量来存放定时值,用于存放每个任务需要的时间
uint8 TaskMark[TASK_NUM]; // 同样对应三个标志位,为0表示时间没到,为1表示定时时间到
3. 在定时器中断服务函数中添加:
/**************************************************************************************
* FunctionName : TimerInterrupt()
* Description : 定时中断服务函数
* EntryParameter : None
* ReturnValue : None
**************************************************************************************/
void TimerInterrupt(void) //定时器溢出之后就会进入到这里,可以是1ms,也可以是10ms
{
uint8 i;
for (i=0; i<TASKS_NUM; i++) //分别去查看每个任务,这里TASKS_NUM是表示任务的个数,这里是3个
{
if (TaskCount[i]) //TaskCount[i],这个是代表第i个任务当前延迟的时间,如果没有到延迟时间到0,就继续延迟
{
TaskCount[i]--; //减少一个刻度
if (TaskCount[i] == 0) //如果TaskCount[i]为0,说明我们指定的时间到了
{
TaskMark[i] = 0x01; //TaskMark[i],表示第i个任务的延迟已经完成,可以执行了
}
}
}
}
4. 在我们的应用程序中,在需要的应用 [延迟] 的地方添加如下代码:
TaskCount[0] = 20; // 延时20ms,比如按键程序,需要我们每20ms检测一次,并不需要实时查看
TaskMark[0] = 0x00; // 启动此任务的定时器
到此我们只需要在任务中判断TaskMark[0] 是否为0x01即可。其他任务添加相同,至此一个定时器的复用问题就实现了。在等待一个定时的到来的同时我们可以循环判断标志位,同时也可以去执行其他函数。 [即:在一个函数运行的间隙中我们可以运行其他的函数]
那么如果我们在一个函数延时的时候去执行其他函数,充分利用CPU时间,是不是和操作系统有些类似了呢?但是操作系统的任务管理和切换是非常复杂的。下面我们就将利用此方法架构一个新的应用程序。
时间片轮询法的架构:
1.设计一个结构体:这个是定义的一个 模子, 用于扣蛋糕用的, 实际上是定义任务包括几个要素,我们把任务的要素都列出来,
这样就可以使每个任务都有规定格式的要素了
typedef struct _TASK_COMPONENTS //任务结构体,任务的几个要素 [这个是很重要的]
{
uint8 Run; // 程序运行标记:0-不运行,1-运行 ,这里是程序会不会运行
uint8 Timer; // 计时器, 这个是用于在定时器中减减的
uint8 ItvTime; // 任务运行间隔时间, 这个是用于更新参数的
void (*TaskHook)(void); // 要运行的任务函数
} TASK_COMPONENTS; // 任务定义
2. 任务运行标志出来,此函数就相当于中断服务函数,需要在定时器的中断服务函数中调用此函数,这里独立出来,便于移植和理解。
/**************************************************************************************
* FunctionName : TaskRemarks() //放到定时器中
* Description : 任务标志处理
* EntryParameter : None
* ReturnValue : None
**************************************************************************************/
void TaskRemarks(void) //要放到 timer中断中
{
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; // 任务可以运行, 任务的延迟已经过了, 可以继续运行了
}
}
}
}
3. 任务处理:实现任务管理操作, 用于循环判断哪个任务需要运行了
/**************************************************************************************
* FunctionName : TaskProcess()
* Description : 任务处理
* EntryParameter : None
* ReturnValue : None
**************************************************************************************/
void TaskProcess(void)
{
uint8 i;
for (i=0; i<TASKS_MAX; i++) // 逐个任务时间处理
{
if (TaskComps[i].Run) // 这个标志不为0, 标志为0, 标志置1是在timer时间中断中, 是在时间查询那里的
{
TaskComps[i].TaskHook(); // 运行任务, 这个是一个函数, 在运行完这个函数后, 我们下一步操作就是清除标志位
TaskComps[i].Run = 0; // 标志清0
}
}
}
假设我们有三个任务:时钟显示,按键扫描,和工作状态显示
1. 定义一个上面定义的那种结构体变量:
/**************************************************************************************
* Variable definition
**************************************************************************************/
static TASK_COMPONENTS TaskComps[] =
{ //0:程序刚开始不运行; 60:用于减减的计数; 60:函数重复周期,用于重装减减; TaskDisplayClock:是一个函数名,用于重复运行的刷屏;
{0, 60, 60, TaskDisplayClock}, // 显示时钟
{0, 20, 20, TaskKeySan}, // 按键扫描
{0, 30, 30, TaskDispStatus}, // 显示工作状态
// 这里添加你的任务。。。。
};
在定义变量时,我们已经初始化了值,这些值的初始化,非常重要,跟具体的执行时间优先级等都有关系,这个需要自己掌握。
上面的结构体初始化表示,我们有三个任务:
①每1s执行一下时钟显示,因为我们的时钟最小单位是1s,所以在秒变化后才显示一次就够了。
②由于按键在按下时电平会抖动,而我们知道一般按键的抖动大概是20ms,那么我们在顺序执行的函数中一般是延迟20ms等待电平稳定后才开始采集电平,而这里我们每20ms扫描一次,效果是非常不错的,即达到了消抖的目的,也不会漏掉按键输入。
③为了能够显示按键后的其他提示和工作界面,我们这里设计每30ms显示一次,如果你觉得反应慢了,你可以让这些值小一点。
TaskDisplayClock, TaskKeySan, TaskDispStatus 后面的名称是对应的函数名,你必须在应用程序中编写这函数来分别完成三个任务。
2. 任务列表:(也叫作任务清单)
typedef enum _TASK_LIST
{
TAST_DISP_CLOCK, // 显示时钟
TAST_KEY_SAN, // 按键扫描
TASK_DISP_WS, // 工作状态显示
// 这里添加你的任务。。。。
TASKS_MAX // 总的可供分配的定时任务数目
} TASK_LIST;
好好看看,我们这里定义这个任务清单的目的其实就是参数TASKS_MAX的值,其他值是没有具体的意义的,只是为了清晰的表面任务的关系而已。
硬件——STM32 , 软件框架的更多相关文章
- stm32软件编程的框架及注意事项——rtos篇
0.通常,嵌入式软件(这里指单片机系统)的框架千变万化,有带rtos的,也有裸机的. 0.1.写过带系统的,也写过裸机的,这里总结一下两个类型的框架,记录下自己的心得,主要是文字描述,框架图可以后期添 ...
- linux内核中的GPIO系统之(1):软件框架
一.前言 作为一个工作多年的系统工程师,免不了做两件事情:培训新员工和给新员工分配任务.对于那些刚刚从学校出来的学生,一般在开始的时候总是分配一些非常简单的任务,例如GPIO driver.LED d ...
- 安装 SQL Server 2008 R2 的硬件和软件要求(转)
以下各部分列出了安装和运行 SQL Server 2008 R2 的最低硬件和软件要求.有关 SharePoint 集成模式下的 Analysis Services 的要求的详细信息,请参阅硬件和软件 ...
- DM8168 DVRRDK软件框架研究
转载注明:http://blog.csdn.net/guo8113/article/details/41120491 Netra(DM8168)处理器是个多核处理器,每一个核之间相互独立却又相互关联, ...
- 安装 SQL Server 2012 的硬件和软件要求(官方全面)
以下各节列出了安装和运行 SQL Server 2012 的最低硬件和软件要求. 有关 SharePoint 集成模式下 Analysis Services 的要求的详细信息,请参阅硬件和软件要求(S ...
- 安装 SQL Server 2005 的硬件和软件要求(官方全面)
SQL Server 2005 安装要求 本主题介绍了安装 SQL Server 205 的硬件和软件要求,以及查看安装文档的说明. 硬件和软件要求(32 位和 64 位) 访问 SQL Server ...
- Niagara解决设备连接应用的软件框架平台技术。
Niagara 是Tridium公司所研发的设计用于解决设备连接应用的软件框架平台技术. Niagara是一种应用框架,或者说是软件框架,特别设计用于应对智能设备所带来的各种挑战,包括设备连接到企业级 ...
- WinForm酒店管理软件--框架
WinForm酒店管理软件--框架 搞软件开发4年多了,现在自认为还是菜鸟,从一开始走上工作岗位各种技术对我都很新奇没解决一个问题都觉得很伟大到后来开始对出路的迷茫,到现在我坚信学什么技术不重要,做什 ...
- STM32软件复位(基于库文件V3.5)
源:STM32软件复位(基于库文件V3.5) void SoftReset(void) { __set_FAULTMASK(); // 关闭所有中端 NVIC_SystemReset();// 复位 ...
随机推荐
- Xcode Git 客户端 + GitBucket 服务器 使用整合归纳
1.使用前说明: 不知道XCode,Git的请自行度娘,不知道GitBucket的,可参考文章:git 私服搭建-gitbucket 初试牛刀 2.创建Git步骤 1>在gitbucket创建账 ...
- 【Henu ACM Round#16 C】Graph and String
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 根据题意:先明确以下规则: 1.如果两个点之间没有边,那么这两个点只能是a或c,且不能相同 2.如果两个点之间有边,那么他们之间的差 ...
- 常用Linux命令 mount df dd
mount -t tmpfs tmpfs ~/build -o size=1G -t 对应的是类型 -o 对应的是选项 tmpfs是Linux/Unix系统上的一种基于内存的文件系统.tmpfs可以使 ...
- android側滑菜单-DrawerLayout的基本使用
眼下主流App开发中,部分是以側滑菜单为主布局架构,曾经做android側滑菜单时.大多选择使用github上的第三方开源框架SildingMenu,可是这个框架还是稍显笨重.好消息是google已经 ...
- MyReport.Form表单引擎
MyReport.Form表单引擎.主要提供表单模板的设计以及表单模板的预览填报等功能集合. 支持文本框.选择框.数字框.日期框.图片框.组合框.弹出框等经常使用控件. watermark/2/tex ...
- selector-item属性
今天做的项目,发现通过键盘选中一个button以后,并没有出现button样式的变化,后来发现是selector里面缺少状态配置的原因.这里就顺便把用到的属性记录了下来,方便以后使用.当然它的属性很多 ...
- 网页中插入javascript的几种方法
网页中插入javascript的方法常见的有两种: 一.直接使用html标记 JavaScript 可以出现在 html的任意地方.使用标记<script>…</script> ...
- 简单说一下 JSON和JSONP
JSON和JSONP,但从缩写看,可能会以为他们是很相似的两个名词,但他们除了缩写相似外,他们是两种类型的概念. 首先: JSON(JavaScript Object Notation)即JavaSc ...
- ssh框架的总结
一.spring:是基础,可以管理对象,也可以通过关键对象管理另一个框架.但是首先应该明确spring并不是只能应用于web方面,而是可以应用在一般的java项目中.只是如果在web环境下使用需要在w ...
- Kinect 开发 —— Kinect studio
This tool can record all the data coming into an application from a Kinect unit. You can then view, ...