单片机很好玩3,制作一个呼吸灯
发表于: 2019-01-06 13:31:11 | 已被阅读: 26 | 分类于: 单片机
上一节为了解决单片机 IO 电流驱动能力不足,导致 LED 小灯亮度不高的问题,借助了三极管。单片机的 IO 通过三极管开关 LED 小灯的电流,最后的确明显让小灯的亮度更高了。
使用电路模拟软件
还记得上一节的这张图吗?
虽然不能迷信模拟软件,但是它(DesignSoft Tina 9 - Industrial)的确是一个不错的参考,尤其对于和我一样的初学者朋友来说。
使用C语言制作呼吸灯
现在既然 LED 小灯足够亮,那么就能做些更好玩的东西了。相信不少朋友使用过带“呼吸灯”的手机,指示灯慢慢的变暗,再慢慢的变亮,看起来就跟动物呼吸一样,所以称为“呼吸灯”。
C语言控制小灯亮度
“呼吸灯”其实就是小灯的亮度是逐渐变化的。也就是说,只要能够使用单片机控制我们的 LED 小灯的亮度,“呼吸灯”效果也就实现了。
上一节使用 C语言控制单片机 IO 交替输出高低电平,实现了 LED 小灯的闪烁效果,核心代码如下:
while(1){
P20 = 0;
delay(10);
P20 = 1;
delay(10);
}
IO 输出的高低电平持续时间都是 10 个单位,一个完整的周期内,LED 小灯的亮灭时间都是相等的。那么,现在有下面这两种情况:
- 一个周期内,LED 小灯亮的时间比灭的时间持续时间长。
- 一个周期内,LED 小灯亮的时间比灭的时间持续时间短。
想象一下,哪种情况下的小灯更亮呢?答案是显而易见的,所以使用 C语言编程单片机控制小灯亮度的思路就有了,就是控制一个周期内,LED 小灯的亮灭持续时间长短而已。如此一来,假设一个亮灭周期为 100 个时间单位,就可以写出下面这个函数:
void twinkle_once(unsigned char darkTime)
{
P20 = 0;
delay(100-darkTime);
P20 = 1;
delay(darkTime);
}
现在在 main 函数里测试一下该函数,分两次,一次传入的参数为 10,一次为 90:
int main()
{
while(1){
twinkle_once(10); // 分别测试
//twinkle_once(90); // 分别测试
}
return 0;
}
可以看出,twinkle_once() 函数的确会因为参数不同,驱动小灯的亮度也不同。
实现“呼吸灯”
既然已经能够使用 C语言编程单片机控制 LED 小灯的亮度,实现“呼吸灯”就不难了。只要传递给 twinkle_once() 函数的参数由小变大,再有大变小就可以了。所以可以写出如下控制代码,请看:
int main()
{
char darkTime = 0, dir = 1;
unsigned int cnt = 0;
while(1){
cnt ++;
twinkle_once(darkTime);
if(cnt == 4){
cnt = 0;
if(dir)
darkTime += 1;
else
darkTime -= 1;
if(darkTime >= 100)
dir = 0;
if(darkTime <= 60)
dir = 1;
}
}
}
最终完整代码如下:
能够看出, twinkle_once() 函数控制 LED 小灯的亮度并不是线性的,所以呼吸灯的“呼吸”效果并不是特别好。因此,更理想的做法不应该只是简单加减 1 修改 darkTime ,而是按照 LED 小灯的响应曲线修改之。限于篇幅,这里就不写了。