arduino延时用法(Arduino进阶-第一节点灯仪式)
arduino延时用法(Arduino进阶-第一节点灯仪式)下面,我们以12号引脚来控制另外一个LED,实现13号引脚的LED每0.5秒改变一次状态、12号引脚的LED每0.25秒改变一次状态的效果。从上面例程中可以看到,它与上一个例程的结构是相似的。只是增加了一个任务函数,在初始化中设置两个任务函数以不同的周期调用,其中对于0.5秒改变一次状态的LED控制,直接将该任务设置为每0.5秒调用一次,而取消了计数。程序中同样没有出现任何一个"delay",却实现了两个LED按照我们的设置互不干涉地闪烁,如果使用"delay"是无法实现的。另外,两个LED的控制,我们也可以合并到一个任务中去完成,它们工作在同一个时基上,而我们可以通过分别计数来实现不同的频率控制。本期就讲到这里,在后面的课程中我们将基于这种方法不断深入,实现Arduino复杂系统的设计。
入门Arduino的第一个例程,就是点亮一个LED,并且让这个LED"亮-灭-亮-灭……"不断地重复。作为入门的第一个程序,那是比较简单了,就是在主循环中让LED开,"delay"一下,然后LED关,然后再"delay"一下。为什么进入到进阶阶段,还要再来一次"点灯仪式"呢?这一课,我们将用另外一种方法来"举行"点灯仪式。
我们先来讨论一个问题:当程序执行到"delay"的时候,CPU在干什么?实际上,"delay"是让CPU执行空指令,就是让它"坐"在那儿"数数",其它的什么也不干,数到我们给它规定好的那个数(delay()中延时的时间)之后再继续执行后面的程序,这样的延时我们也可以通过设置一个"for"或者"while"的循环体,在循环中做简单的计数减来实现,只不过延迟的时间不准确。这样有什么"不妥"呢?假如我们就只让CPU控制一个LED开和关,这样做没有什么不妥,但是如果控制两个LED,一个LED每0.5秒完成一次开或关,而另一个LED一秒内要完成两次开关,并且两个LED的开关动作是互不影响的,这样的系统还能用"delay"来搭建吗?很明显,这是不行的,我们必须寻求新的方法:定时,在进阶课程中,我们所有的例程都将基于这种方法。
在单片机内部,都有通用的定时/计数器,通过设置定时器的寄存器,定时器可以自己计数,当计数到我们设定好的时间值时产生一个中断通知CPU,然后CPU去执行相应的处理,而在整个计数的过程中,CPU是不参与的,这个时候CPU可以去处理其他的任务,这样就提高系统的效率和实时性。在一些高端的单片机中(例如STM32),内核里还带有系统定时器(systick),它可以为操作系统提供时基,当然也可以像通用定时计数一样用于产生固定时间的定时中断,而同时通用定时计数器也是可以使用的。在Arduino搭载AVR mega单片机系列的开发板中,我们可以利用通用定时计数器来产生中断。
在上面的例程中,我们将LED的控制放置于函数led_control()中,并且在初始化中调用every(long T callback)函数设置它每10毫秒调用一次。因此,我们可以把10毫秒看作LED控制的时基,每一次进入led_control()函数,经过的时间就是10毫秒,也就是count每加1一次则经过了10毫秒,当计数值达到50次时,时间就经过了500毫秒-0.5秒,这时改变LED的电平,就实现了我们的任务要求。注意,每次计数达到设定值后,必须将计数变量(count)清零,以进入下一轮计数。程序中没有出现任何一个"delay",但却实现了"delay"的效果。
下面,我们以12号引脚来控制另外一个LED,实现13号引脚的LED每0.5秒改变一次状态、12号引脚的LED每0.25秒改变一次状态的效果。
从上面例程中可以看到,它与上一个例程的结构是相似的。只是增加了一个任务函数,在初始化中设置两个任务函数以不同的周期调用,其中对于0.5秒改变一次状态的LED控制,直接将该任务设置为每0.5秒调用一次,而取消了计数。程序中同样没有出现任何一个"delay",却实现了两个LED按照我们的设置互不干涉地闪烁,如果使用"delay"是无法实现的。另外,两个LED的控制,我们也可以合并到一个任务中去完成,它们工作在同一个时基上,而我们可以通过分别计数来实现不同的频率控制。
本期就讲到这里,在后面的课程中我们将基于这种方法不断深入,实现Arduino复杂系统的设计。