今天上午发了一个“
浅谈我的单片机程序架构”的帖子,有点啰嗦,可能大家看不太下去。现在补充一个按键扫描实例,看对大家是否有所启发。
注意:此文不仅是程序架构,而且还提出了一种按键识别的解决方案,也属抛砖引玉,欢迎大家讨论。
【程序仅提供思想】
主框架结构(下面这个大家应该都很熟悉吧)
void main()
{
...//系统相关底层驱动初始化
while(1)
{
...//服务程序
...//应用程序
}
}
开始填写框架
void main()
{
...//系统相关底层驱动初始化
while(1)
{
/*服务程序*/
Input_Scan_Svr();//输入服务程序
...//应用程序
}
}
输入服务程序包含什么呢,继续往下看
void Input_Scan_Svr()//系统输入服务
{
/*针对按键的*/
KeyScan_Svr();
KeyIDEXC();//键码转换,将按键转换为系统能识别的键码
/*针对串口的*/
...
}
可以看到针对按键处理的1个子服务和1个转换进程。
来看看按键扫描服务程序(...代表其他按键相同写法)
/*服务程序*/
void KeyScan_Svr()//按键扫描服务程序
{
/*该服务程序给上层服务或应用提供按键状态信息(Keyx_State)*/
static u8 Key1State_TC=0;//按键端口状态计时
...
/*状态计时*/
//按键1
if(GetKey1State()==K_TRIGGERING)
{
if(Key1State_TC<127)//防止状态计时溢出
Key1State_TC+=os_100ms;//每个扫描服务周期状态正向计时+100ms
}
...
/*状态解析*/
//按键1
if(GetKey1State()==K_NORMAL)//松键才识别
{
Key1_State=KEY_NO_PRESS;
if(Key1State_TC>0)
{
if(PressCountA<5) Key1_State=KEY_SHORT_PRESS;//按下时间小于0.5s,视为短按
else if(PressCountA<30) Key1_State=KEY_LONG_PRESS;//按下时间大于0.5s小于3秒,视为长按
Key1State_TC=0; //状态计时清零
}
}
if(Key1State_TC>=30)//按键1触发持续超过3秒,视为持续按下
Key1_State=KEY_KEEP_PRESS;
...
}
可以看到这个扫描服务中调用了底层驱动程序GetKey1State();这个函数就很简单啦
/*驱动程序*/
u8 GetKey1State()//返回按键1端口状态
{
//IO_Key1 =Px^x
if(IO_Key1==0) return K_TRIGGERING;
else return K_NORMAL;
}
最后再来看看键码转换进程
void KeyIDEXC()//键码转换标准键码
{
LocalKeyID=0;//初始化ID
if(Key1_State==KEY_SHORT_PRESS)
LocalKeyID=K_UP;
else if(Key1_State==KEY_LONG_PRESS)
LocalKeyID=K_ENTER;
else if(Key1_State==KEY_KEEP_PRESS)
LocalKeyID=K_F1;
...
//还可以随意补充按键组合,返回一个键码即可
}
上层应用程序能识别的键码就是K_UP、K_DOWN、K_ENTER...在这里我把这些键码和电脑键盘键码对应起来
#define K_ENTER 13
#define K_ESC 27
#define K_UP 38
#define K_DOWN 40
#define K_F1 112
#define K_F2 113
#define K_F3 114
#define K_TAB 9
#define K_HOME 36
...
这就是按照我自己的架构写的按键识别的服务程序。至于按键状态计时中的os_100ms等时间脉冲,是由另外一个系统服务程序提供的,可以保证这些时间脉冲仅存在1个周期,在主逻辑执行周期小于这些时间脉冲时是准确有效的。所以完整的框架变成为
void main()
{
NTOS_Init();//系统相关底层驱动初始化
while(1)
{
/*服务程序*/
NTOS_TimePulse_Svr();//时间脉冲服务,产生100ms,500ms,1s的计时脉冲
Input_Scan_Svr();//输入服务程序,抓取外部输入信号
...//应用程序
}
}
当然,NTOS_TimePulse_Svr()服务还需用到内部定时器硬件,因此需写一个TimePulse的驱动,而这个驱动比较特殊,需要用到定时器罢了。
以上就是在我的程序框架下搭建按键识别服务的一个过程,看似有些麻烦和冗余,实际上却是条理清晰,这点,估计自己的框架只有自己懂了吧!再次欢迎大家提出更优秀的算法。