前言:
写单片机程序,大部分人都是从流程开始,因为这个最容易理解,也最符合人的思路,但是当发现,自己很多的写程序,明明是重复以前做过的事情,但是又不得不重新写一遍,你就会开始考虑怎么提高移植性,扩展性,然后慢慢的开始思考可行性,最近周围的朋友们讨论流程和对象,才豁然醒悟,我的思考不过是别人早就已经总结过的,以前也都是听流程和对象,当时自身知识储备不够,没法深刻理解,现在有了一些经验,才发现这是这么自然又深刻的道理。于是,最近又思考了不少,写下这篇心得文章,希望对大家有所帮助,可以早点踏入对象这个领域。
简述流程与对象
还是学庄子,打比方吧。听过郭德纲先生的一段相声,说是,某某降生,他父亲病倒了,回到家之后,他母亲最不容易。这边儿是丈夫,这边儿是孩子,都得管。给这边儿喂喂奶,那边儿喂喂药,喂喂奶,喂喂药。喂喂药,喂喂奶。他父亲特壮,这孩子吃错药了。相声很好笑,听完了,我们也受教育下,免得让老艺术家们说郭德纲先生三俗,从这一段,我们总结下,从流程角度,喂孩子奶是流程,喂父亲药也是流程,他母亲是主体,如果是程序,我们封装成两个子程序,一个是给父亲喂药,一个是给孩子喂奶,处理器分时调用这两个子程序。我们转换思路,从对象角度去分析:主体还是他母亲,他爸爸是对象,孩子是对象,药和奶,也都是对象,我们把药和奶,归类成一类,姑且称之为形参1对象,然后把他父亲和孩子,归类成一类,姑且称之为形参2对象,然后,把喂的动作,封装成一个执行子程序,我们把上述行为想像成一段程序,处理器传送形参对象和执行对象到处理子程序进行处理。
不知道上面描述,能否让你区分面向对象和面向流程的区别,本质上,我们都是要完成一件事,面向流程是人的思维,对具象的事务进行处理。面向对象,是抽象的思维,微机的思维,因为微机是不会明白什么是喂奶什么是喂药,他是调取参数,传递参数到执行程序执行。
我们扩展一下,把上面说的形参对象,列成一张表,1号成员{药,父亲},2号成员{奶,孩子},所谓的喂药,就是我们的主体–处理器,传递表内1号成员内容到执行程序执行。对象(表)到对象(执行程序)。
再抽象化,#define 药 0,#define 父亲 0。然后你会发现,你写的程序,大部分不就是这样吗?
面向对象的好处是显而易见,你在列表中继续添加成员,3号成员{酒,父亲},4号成员{饭,小孩},同类的事情,你可以扩展很多。
而且,整个程序非常清爽,如果要修改程序,只要修改对应的执行程序,就能完成,而流程型的程序,很容易错综复杂,彼此相互调用操作很难修改。
面向对象如何在程序中运用
有同学又要说,我已经理解了面向对象了,那我在程序中,如何实现呢?这个需要大家在实际应用中,慢慢领会应用,以下举一些例子,供大家参考。
1、蜂鸣器。做电子的经常使用到,就说有源的三极管驱动开和关,看我们怎么用这么简单的一个器件,怎么设计一个面向对象的程序。
可能有人要问,就蜂鸣器,我让他响就完了呗,有什么花头?简单的东西,更容易引入思路,更有扩展空间。比如,就一个蜂鸣器,甲方要求,有3种提示音。你写好了,过几天,又说,要增加几种提示音,原来的提示音改一下!请问,你碰到这种情况,怎么写程序?于是,我设计下面这个面向对象的程序,讲解一下。代码如下:
#define NORMAL_RING_ONCE 0 //响一声
#define SHORT_RING_TWICE 1 //短响2声
#define NORMAL_RING_THREE 2 //响3声
#define SHORT_RING_FOUR 3 //短响4声
#define NORMAL_RING_TWICE 4 //响2声
#define SHORT_NORMAL_TWICE 5 //
#define NORMAL_SHORT_TWICE 6 //
#define LONG_RING_ONCE 7 //
#define BELL_MODE_MAX_NUM 8
typedef struct
{
uint8 Step;
uint8 Count[10];
}bellset;
const bellset BellTab[BELL_MODE_MAX_NUM] =
{
{1,15},
{3,5,2,8},
{5,25,12,25,12,25},
{7,8,1,8,1,8,1,8},
{3,25,12,25},
};
static bellset BellSetObject;
static uint8 BellState = 0,BellRun=0;
void BuzzerSet(uint8 mode) //
{
if(BellState) return; //
if(mode>=BELL_MODE_MAX_NUM) return ;
BellState = TRUE;
BellRun = 0;
BellSetObject = BellTab[mode];
}
void BuzzerLoop(void) //20ms per loop
{
if(BellState)
{
if(BellRun>=BellSetObject.Step)
{
BellState = FALSE;
BellRun = 0;
BellSetObject.Step = 0;
BUZZER_OFF();
}
else
{
if(BellRun%2==0)
{
BUZZER_ON();
}
else
{
BUZZER_OFF();
}
if(BellSetObject.Count[BellRun])BellSetObject.Count[BellRun]--;
else BellRun++;
}
}
else
{
BUZZER_OFF();
}
}
如上,BuzzerLoop()每20ms调用一次。这个怎么实现就不说了。然后你要让蜂鸣器响,在任意程序位置,调用BuzzerSet()子程序就行了,传递进去你要实现的效果参数。这就是面向对象的思路,如果你要添加响声的效果,只要在表格BellTab里添加对应的效果就行了,至于怎么添加自己要的效果,动动脑筋,这个程序还是很好理解。这样的蜂鸣器程序,是不是便于编辑,便于移植,便于扩展?甲方有什么需求,轻松改改就可以实现。
这个是比较简单的,类似的如LED指示灯的应用,也可以用相近的方式,展现很多效果。
另外,显示,按键之类的,都是可以用面向对象的方式编写程序,就可以写出又漂亮,又直观,又能便于移植的程序了。
本篇就写到这里,如有空,再写一些其他的应用思路。希望对各位新人朋友有所帮助。老鸟估计都有更好的方法去实现。