AVR单片机程序设计架构
扫描二维码
随时随地手机看文章
昨天在回家的火车上,带了一本《匠人手记》,看了几篇,受益匪浅。其中一篇讲到编程思路,也就是如何入手构建一个程序。我用C语言在原文的基础上稍微展开一下,以备日后查看。
简单的程序只要用简单的方式就可以了,我在此之前也只会这一种方式。也就是:
void main()
{
init();//初始化
while (1)
{
module01();//模块1,或若干语句
}
}
匠人在书中讲到事件驱动机制,例如:
void main()
{
init();
while (1)
{
if (事件1条件)
shijian1();//执行事件1
if (事件2条件)
shijian2();//执行事件2
if (事件3条件)
shijian1();//执行事件3
......
}
}
以前编的一些多事件程序中,我也用过类似的思想,但是用了很多条件的嵌套,编出的程序远没有这种清晰。
上面的方式也叫顺序调度机制,在每次循环中每个事件都可能被执行到,另有一种优先调度机制:
void main()
{
init();
while (1)
{
if (事件1条件)
{
shijian1();//执行事件1
continue;
}
if (事件2条件)
{
shijian2();//执行事件2
continue;
}
if (事件3条件)
{
shijian3();//执行事件3
continue;
}
......
}
}
将优先级最高的事件放在前面,被执行到的概率最大。但是假如前面的事件频率太高,后面的就有可能执行不到了。
最精彩的部分要数多任务并行运行。简单的多进程程序还是很容易的,比方同时控制流水灯和数码管(动态),单独的流水灯是赋值后延时,再赋值,再延时。如果要同时控制数码管,只要把之前用作延时的那段时间用来扫描数码管就行了。简单说来,就是把以前浪费掉的时间充分利用起来。
稍微复杂一点的多任务运行就要稍微动些脑筋了,可以把每个任务看做一个进程,每个进程可以被分为多个阶段,每个阶段执行时间较短。多个进程的每个阶段交替进行:进程1阶段1,进程2阶段1,进程1阶段2,进程2阶段2,……
我想到两种方式实现各阶段的分配,第一种是人为设定好每个阶段结束的条件,等待着某个阶段“主动”结束然后进入另一个进程的某个阶段。这种方式每个阶段所用的时间是不确定的,但是每个阶段所做的事情是确定的。第二种方式是每进入一个阶段,就开启一个定时器,等到定时器计到设定的时间就强制结束这个阶段,开始另一个进程的某个阶段。这样每个阶段运行的时间都是固定的,但是一般不能明确地知道在这个阶段将任务执行到哪里(有点像量子力学的测不准原理了)。
用定时器实现进程的分配:
#include
#include
unsigned char fond = 0;
#pragma interrupt_handler tc0:10
void tc0()//定时器0溢出中断,假设共有3个进程
{
fond++;
if(fond == 3) fond = 0;
}
void shijian1()
{
char a1;
.....//读取上次数据
a1 = fond;
while (fond == a1)
{
....//继续运行
}
.....//保存本次数据
}
void shijian2()
{......}
void shijian3()
{......}
void main()
{
TCCR0 = 0x05;//设8M晶振,1024分频,每秒平均产生30.5次中断,应用中可视情况而定
TIMSK |= BIT(0);
SREG |= BIT(7);
while (1)
{
switch (fond)
{
case 0:
if (事件1条件)
shijian1();
else
fond++;//假如此事件发生的条件不满足,就让fond加1以便执行下一个事件
break;
case 1:
if (事件2条件)
shijian2();
else
fond++;
break;
case 2:
if (事件3条件)
shijian3();
else
fond=0;
break;
}
}
}
除此之外,还可以设计一段专门用于分配CPU时间的程序,可以更系统地处理多进程的问题,这就很有些操作系统的感觉了。
在应用中不限于这几种方法,根据实际情况的复杂程度能灵活使用各种方法编出最合适的程序才是最重要的。另外,匠人同志还说过这么句话:简单的,才是最有效的。