简介:
本文主要讲解在完成这个作业的所思所想。而这些思路会引导我们一步一步走下去,直到完成这个作业。
编程思路:
我想大家应该和我一样,在拿到这个作业的时候,都有些激动,但是更多的还是担心。因为这是个比我们平时写单个模块都要大的程序。虽然我们在学习嵌入式Linux之前都会有一些其他单片机的学习经验,如51,avr或者是32 。并且我们也用这些单片机做过一些小的项目。但是我们依然对这个作业感到一些担心,则是因为我们以前的项目都是使用keil或者其他的软件所写。而在这个项目中我们是要自己去完成这些底层的编写。同时我们还要想到将各个模块运用起来而不使他们产生冲突。这就很考验大家的学习成果了。那么我们激动的原因则是:我们学习了这么久的裸机操作,现在终于有一个合适的机会来展示我们所学习的知识了。
下面我们来聊聊这个作业,或者说是小项目更合适。我想大家在拿到这个项目的时候脑子里都会蹦出各种去完成这个项目的方法,
我们要想这里这么多的模块我们要用什么样的方法来控制他们以实现我们点触摸屏相应的位置,哪里相应的程序就会运行?我想这里就涉及到了我们
对整个要求的把握和
对程序设计思路的考验。这里我想有人会使用 一种方法:使用while语句中嵌套for语句来实现对各个模块的扫描。当相应位置的程序被点击后,其对应的标志位XXX_flag被置1,在下一个扫描周期时就可以执行这个模块的程序。当程序结束时清除该标志位。这个方法确实不错。
但是我们会发现当我们再添加一个新的模块后我们就要对for语句进行修改,这样是不利于程序的扩展的。而一个好的程序是,当有新的模块添加进来后我们原有的程序不需要做太大的修改,或者说我们不应该只要有模块添加进来就要对原有的程序进行修改。所以我否定了这个想法,而我所用的是
状态机的思路,使用状态机我们只需要在状态机中添加我们需要的一环就可以而不用去对原有的程序进行修改。
下面我先介绍什么是状态机并就本程序对状态机进行说明(
本状态机的例子是我很早的时候从一个介绍avr单片机书上看到的,现在有一些忘了,但是中心思想还记得,所以在这个与大家分享,如果有什么错误请指正)。
现在我们以一个
按键防抖程序为例子介绍状态机,我想我们以前很多时候实现按键防抖是使用下面这段伪代码所写的方法来实现。
if(按键是否按下){
delay(100ms);
if(按键是否按下){
做要做的事情;
}
}
确实上面伪代码实现的按键防抖是一种便利的方法,
在一个对时间要求不高的项目中我们完全可以这样写。但是对于这个对时间要求比较高的项目
我们就不能使用delay这样的函数来让CPU在哪了空转了。我们应该让CPU做更多的事情。那么我们就要介绍状态机了。
我们设定三个状态,
分别为状态1——检验按键第一次是否按下,状态2——检验按键第二次是否按下,状态1——检验按键是否抬起。他们执行的过程如下图:
而他
对应的程序为:
while(1){
switch(state){
case 1:{
如果按键按下,state=2;
break;
}
case 2:{
如果按键按下,state=3;否则state=1;
break;
}
case 3:{
如果按键抬起,state=1;
做该做的事;
break;
}
}
当我们的状态处在1时,我们不断的检测按键是否被按下,如果按键没有被按下我们将不断的检测,直到按键被按下。这时我们的按键要进入到状态2,这里我们将检测按键是真的被按下还是因为某些噪声干扰。如果这里是因为噪声干扰那么state将回到状态1,而如果这是我们的按键还在按下状态我们就进入状态3。在状态3中我们不断的检测按键是否被抬起。如果按键被抬起我们做我们要做的事情并将状态设为1为下一次的按键检测做准备。如果没有我们就要继续检测了。
上面就是使用按键对状态机进行的介绍。而
状态机的中心思想就是,
我们将一件事情分为不同的状态,而各个状态之间有联系,但是他们又在执行自己状态时,只做自己本状态的事情。其他状态对他不影响。当条件适合时实现状态的跳转。
而在本项目中我将各个模块分开,而每个模块使用一个状态机。我的程序设计思路是:
while(1){
switch(module_select){
case LED_MODE:{
switch(state){
case MODE_READY:{模块初始化;state=MODE_IN;break;}
case MODE_IN :{模块操作;如果点击退出state=MODE_OUT;break;}
case MODE_OUT:{模块退出;state=MODE_READY;mode_select=NULL;break;}
}
break;
}
case BUTTON_MODE:{
switch(state){
case MODE_READY:{模块初始化;state=MODE_IN;break;}
case MODE_IN :{模块操作;如果点击退出state=MODE_OUT;break;}
case MODE_OUT:{模块退出;state=MODE_READY;mode_select=NULL;break;}
}
break;
}
}
}
上面就是我程序的设计思路了:
我使用了两次switch语句。
第一次使用switch选择的是各种模块的选择。而第二次则是对每一种模块中状态的选择。从上面我们可以看出如果我们想再加一个模块只要 加一个下面的模块就可以了:
case XXX_MODE:{
switch(state){
case MODE_READY:{模块初始化;state=MODE_IN;break;}
case MODE_IN :{模块操作;如果点击退出state=MODE_OUT;break;}
case MODE_OUT:{模块退出;state=MODE_READY;mode_select=NULL;break;}
}
break;
}
所以我们这个程序的好处就是当我们添加或者删除模块时不用对原理的程序做太多的修改,只要添加或者删除就可以了。这样使程序变得更加灵活。
我们程序设计的整体思路就介绍给大家了,而我会在下一篇文章中介绍具体的程序设计代码。