最近重温经典喜剧电影时,发现下面这么一幕:
达文西发明了一个“古怪手电筒”,“在有光的时候就会亮,在没有光的情况下绝对不会亮!”,这种手电筒是怎么制作的呢,我们能否自己制作一个类似的手电筒呢?当然可以,情继续往下看。
设计“古怪手电筒”
这里计划仍然使用C语言编程 51 单片机完成这种设计,那么,51 单片机就是“古怪手电筒”的大脑,它决定“古怪手电筒”是否发光。而为了实现“有光才亮,无光不亮”的机制,51 单片机还需要一只“眼睛”,用于观察“古怪手电筒”所处环境是否有光。
光敏电阻恰好可以作为 51 单片机的“眼睛”,它能够感知环境光照的变化。当照射在光敏电阻上的光亮度改变时,光敏电阻的阻值也会变化:
加上适当的电路(例如简单将光敏电阻与定电阻和电源串联),很容易将这样的电阻值变化,转变为电压值变化,而 51 单片机的 ADC 模块恰恰可以采集电压值。
如此一来,“古怪手电筒”的设计思路就有了:先将光敏电阻和定电阻与电源串联起来,如下图,然后使用 51 单片机的 P1.0 口(ADC的通道 0)连接检测点:
再使用51 单片机的 ADC 模块检测电压,记录有光时的电压 Vb 和无光时的电压 Vd。之后,当 51 单片机检测到 Vb 附近的电压时,就控制“手电筒”发光,检测到 Vd 附近的电压时则关闭“手电筒”。
C语言编程单片机,实现“古怪手电筒”的设计
因为要使用到 51 单片机的 ADC 模块,所以首先要实现 ADC 的C语言代码,请看:
void adc_init()
{
P1ASF = 0xff; // 8 个通道都开
ADC_RES = 0;
ADC_CONTR = ADC_POWER|ADC_SPEEDLL;
delay_about_100ms(2);
}
这里将 P1ASF 赋值为 0xff,表示 P1 的 8 个 IO 口都可以作为 ADC 采样口。然后延时一段时间,等待 ADC 模块初始化。获取一次 ADC 采样值的 C语言代码可以如下写:
// 获取高 8 位的 adc 值
BYTE get_adc_h8bit(BYTE ch)
{
ADC_CONTR = ADC_POWER|ADC_SPEEDLL|ADC_START|ch;
_nop_();_nop_();_nop_();_nop_(); // 等待转换完成
while(!(ADC_CONTR & ADC_FLAG));
ADC_CONTR &= ~ADC_FLAG;
return ADC_RES;
}
// 获取 10 位 adc
WORD get_adc_res(BYTE ch)
{
WORD res = 0;
res = get_adc_h8bit(ch);
res <<= 2;
res |= ADC_LOW2;
return res;
}
这里的 ADC 代码比较简要,详细的说明可参考第 9 节文章。现在将 51 单片机测量的电压值发送到串口,C语言代码可以如下写:
void main()
{
float vol;
adc_init();
init_uart(9600);
while(1){
vol = 5.0*((float)get_adc_res(0))/1024.0;
delay_about_100ms(2);
printf("voltage: %0.2fV\r\n", vol);
}
}
编译C语言程序,烧写到单片机,在电脑端打开串口调试工具:
这是我开着灯时, 51单片机采集到的电压值,可以看出是大于 4.4V 的。现在关灯,观察 51 单片机传来的电压值:
此时电压值基本在 2 V 附近,低于 3V。现在用 LED 小灯模拟“手电筒”,控制代码可以如下写:
void main()
{
float vol;
adc_init();
while(1){
vol = 5.0*((float)get_adc_res(0))/1024.0;
if(vol < 3.00)
P20 = 1;
else
P20 = 0;
}
}
上面的C语言代码很简单,就是认为电压小于 3V 时是关灯,此时单片机关闭“古怪手电筒”。否则认为开着灯,此时单片机控制“古怪手电筒”发光。编译C语言程序,烧写到单片机,测试发现我们成功的仿制出了达文西的“古怪手电筒”,“在有光的时候就会亮,在没有光的情况下绝对不会亮!”:
其实稍微修改一下C语言控制代码,就可以把“古怪手电筒”改成真正的“智能手电筒”:
if(vol < 3.00)
P20 = 0;
else
P20 = 1;
编译C语言程序,烧写到单片机,再测试之,发现“手电筒”在没光的时候自动亮起来,有光的时候则自动关闭:
思考
可以说,目前所谓的“信息化”社会,其实就是“电信号”的社会,从手机到计算机,再到集群服务器,本质上都是基于数字电路的计算机器。看了这两节内容的朋友,应该发现单片机的 ADC 模块的强大之处了,ADC 能够将模拟信号“数字化”,而没有数字化的信号,“信息化”也无从谈起。
“智能”机器则可以认为是能够对外界环境做出反应的机器。例如上一节介绍的温度警报器在某种程度上就属于一种智能机器,它能够检测环境温度,并在温度超过设定值后发出警报。本节最后介绍的“智能手电筒”也属于智能机器。