关于Delay函数的思考

关于Delay函数的思考可能很多人对延时函数的使用并不排斥,但是我个人觉得这是非常不符合软件的本质的。软件的本质是将现实中的各种行为抽象。以现实中人的活动为例,人在同一时刻是可以实时响应很多事情的,而Delay函数的出现相当于给CPU上了刹车

大家好,又见面了,我是你们的朋友全栈君。

这几天一直在忙的一个项目中有一小部分是对机械按键的操作,在准备些BSP的时候突然想起来以前在大学
常用的处理方法就是按键消抖然后识别,待消抖最后弹起,并且所有的消抖程序段都是依靠延时程序实现。
可能很多人对该函数的使用并不排斥,但是我个人觉得这是非常不符合软件的本质的,并且也并不合理。
软件的本质是将现实中的各种行为抽象。以现实中人的活动为例,人在同一时刻是可以实时响应很多事情的,
而Delay函数的出现相当于将CPU进行软件暂停而对实时的任务拒之门外(中断除外),这在很多对任务的
执行时间有着严格要求的场合是难以忍受的。并且糟糕的是,系统任务越多,Delay函数的影响越大。那难
倒就没有了别的解决办法了吗?其实答案就在μ/COSii里。
在实时操作系统里有一个概念叫信号量,用来处理不同事件状态的查询或者对不同任务队同一资源的请求。
标志,该时间标志位在50微秒(暂定)的定时器中断中递增,当达到计时时间要求后就传递给响应的需要延
时的任务,然后该变量清零。
我们以按键的识别为例,在实际按键按下以后,需要等待按键可靠弹起,一般来说在一定时间内如果按键
借用操作系统的思路是用标志位进行间隔扫描状态,这样可以精确的判断按键的状态。详细示意图如下所示:

![按键扫描示意图](https://img-blog.csdn.net/20150817223738086)

以下是编写的BSP程序(基于DSP C2000)

/*******************************************************************************
* * -------------------------
* Details to create profits
* * All rights reserved.
* Contact information:V1.0
* QQ:    836002276
* e-mail:      836002276@qq.com
*******************************************************************************/
/******************************************************************************
 * 本文件实现了Key.c文件中函数的定义和全局变量的定义
 * 1.0.0, 2015-07-4, Aaron       created
 ******************************************************************************/
#include"Key.h"

_KEY_EVENT     KEY_1;                //定义按键一结构体
/*******************************************************************
 * 函数描述:按键事件结构体初始化
 * 形参:按键事件结构体指针
 * 返回值:无
 * 调用者:应用层
 ******************************************************************
void Key_Event_Init(_KEY_EVENT *key_x)
{
 key_x->Key_Change_Time = 0;
 key_x->Key_Flag = 0;
 key_x->Key_Over_Flag = 0;
 key_x->Key_Date = 0;
 key_x->Key_Recover_Flag = 0;
 key_x->Key_Original_Mod = 0;
}
/*******************************************************************
 * 函数描述:按键扫描,实现了按键的按下识别和按键的有效弹起识别
 * 形参:按键事件结构体指针
 * 返回值:无
 * 调用者:应用层
 *******************************************************************
 void Key_Scan(_KEY_EVENT *key_x)
 {
 if(key_x->Key_Date^key_x->Key_Original_Mod)
 { 
   
 key_x->Key_Flag = 1;
 key_x->Key_Over_Flag = 0;
 key_x->Key_Change_Time = 0;
 }
 else
 { 
   
 if(key_x->Key_Change_Time%200 == 0)
 { 
   
 if(key_x->Key_Date = key_x->Key_Original_Mod)
 { 
   
 key_x->Key_Recover_Flag++;
 }
 }
 if(key_x->Key_Recover_Flag >=10)
 { 
   
 key_x->Key_Change_Time = 0;
 key_x->Key_Over_Flag = 0;
 key_x->Key_Recover_Flag = 0;
 }
 }
 }
 /*******************************************************************
 * 函数描述:上电时检测按键在没有按下时输入口的状态,主要目的是为了确定
 是下降沿检测还是上升沿检测
 * 形参:按键事件结构体指针
 * 返回值:无
 * 调用者:应用层
 *******************************************************************
 void  IO_First_Mod_Scan(_KEY_EVENT *key_x)
 {
 if(key_x->Key_Date == 0)
 { 
   
 key_x->Key_Original_Mod = 0;
 }
 else
 { 
   
 key_x->Key_Original_Mod = 1;
 }
 }
 /*******************************************************************
 * 函数描述:对时间计数器进行自加,超过1秒钟就清零
 * 形参:按键事件结构体指针
 * 返回值:无
 * 调用者:定时中断
 *******************************************************************
 void Key_Time_Sum(_KEY_EVENT *key_x)
 {
 key_x->Key_Change_Time++;
 if(key_x->Key_Change_Time >20000)
 { 
   
 key_x->Key_Change_Time = 0;
 }
 }
 /*******************************************************************
 * 函数描述:定时器中断函数
 * 形参:无
 * 返回值:无
 * 调用者:应用层
 *******************************************************************
 void Time_Isr(void)
 {
 Key_Time_Sum(KEY_1); 
 }
/*******************************************************************************
* * -------------------------
* Details to create profits
* * All rights reserved.
* Contact information:V1.0
* QQ:    836002276
* e-mail: sure220@gmail.com
*******************************************************************************/
/******************************************************************************
 * 本文件实现了Key.c文件中函数的声明和全局变量的声明
 * 1.0.0, 2015-07-4, Aaron       created
 ******************************************************************************/
#ifndef KEY_H_
#define KEY_H_

typedef struct{
 unsigned char Key_Flag;
 unsigned char Key_Over_Flag;
 unsigned int Key_Change_Time;
 unsigned char Key_Date;
 unsigned char Key_Recover_Flag;
 unsigned char Key_Original_Mod;
}_KEY_EVENT;

void Key_Event_Init(_KEY_EVENT *key_x);
void Key_Scan(_KEY_EVENT *key_x);A
void  IO_First_Mod_Scan(_KEY_EVENT *key_x);
void Key_Time_Sum(_KEY_EVENT *key_x);


#endif /*KEY_H_*/

中断程序在此略过,因为中断中关于按键的部分仅仅是调用Key_Time_Sum()函数进行时间变量的递增。在CPU上电后首先调用IO_First_Mod_Scan()函数用来设置按键的初始状态,然后再在主函数中调用Key_Scan()既可。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/137210.html原文链接:https://javaforall.net

(0)
上一篇 2022年5月5日 下午12:00
下一篇 2022年5月5日 下午12:00


相关推荐

  • PHP如何解决网站大流量与高并发的问题(四)「建议收藏」

    PHP如何解决网站大流量与高并发的问题(四)

    2022年2月9日
    45
  • docker的端口映射_外网远程桌面端口映射

    docker的端口映射_外网远程桌面端口映射Docker端口映射实现网络访问首先,大家如果看到有什么不懂的地方,欢迎吐槽!!!我会在当天或者第二天及时回复,并且改进~~Docker运行容器之后却发现没IP,没端口,那要如何访问容器呢?下面我来介绍下Docker通过端口映射来实现网络访问一、从外部访问容器应用在启动容器的时候,如果不指定对应参数,在容器外部是无法通过网络来访问容器内的网络应用和服务的。当容器中运行一些网络应用,要让外部访问这些应用时,可以通过-P或-p参数指定端口映射。先来说说p和P吧-p可以指定要映射的端口,并

    2022年10月9日
    6
  • 回声状态网络(echo state network,ESN)概述

    回声状态网络(echo state network,ESN)概述一 提出递归神经网络 RecurrentNeu RNNs 的训练是通过权值直接优化来实现的 这种方式容易产生两个问题 收敛速度慢和易陷入局部最优 回声状态网络 echostatenet ESN 由 Jaeger 于 2001 年提出 在模型构建与学习算法方面较传统的递归神经网络有较大差别 其相应的学习算法为递归神经网络的研究开启了新纪元 回声状态网络又称储备池计算 采用由随机稀疏连接的神经元组成的储备池作为隐层 用以输入进行高维 非线性的表示 ESN 将神经网络的

    2026年3月26日
    2
  • 实例分割–Mask RCNN详解(ROI Align / Loss Fun)

    实例分割–Mask RCNN详解(ROI Align / Loss Fun)1总结架构与主要思想未完待续。。。

    2022年8月23日
    6
  • Oracle11g软硬件基本要求,Oracle 11g的安装

    Oracle11g软硬件基本要求,Oracle 11g的安装Oracle11g有基本安装和高级安装两种方式。两种方式对硬件要求也不相同,oracle11g软件非常大,对硬件要求很高。目前只是讲述在windows环境下的安装,Linux环境下安装以后会讲,下表给出了安装Oracle11g所需的硬件配置。系统要求说明CPU最低主频550MHZ以上内存1GB以上虚拟内存物理内存的2倍磁盘空间基本安装需4.55G,高级安装需4.92G一、Windows环境下安装…

    2022年7月25日
    31
  • Delphi 跨平台_delphi调用api接口

    Delphi 跨平台_delphi调用api接口DELPHI是怎么实现跨平台的?

    2022年4月21日
    212

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号