利用红外发射接收传感器进行距离检测利用红外发射接收传感器进行距离检测
利用红外发射接收传感器进行距离检测 一、实验要求
对红外的发射接收作进一步的探讨。红外可以用来测距离,理解红外测距的基本原理,能够掌握简单的比例控制方法,以及编程。掌握定时/计数器的使用。对循迹效果作分析。 二、实验概要
本实验将探讨红外测距的内容。利用红外检测器的内置电子滤波功能,调节发射红外的载波频率,而检测器对不同频率的信号有不同的“敏感度”,这样,就能大概的知道距离。
1(测试红外的扫描频率。记录红外发射接收的距离。
2(尾随小车。让一个小车跟着另一个小车前行。要将前后距离...
利用红外发射接收传感器进行距离
利用红外发射接收传感器进行距离检测 一、实验要求
对红外的发射接收作进一步的探讨。红外可以用来测距离,理解红外测距的基本原理,能够掌握简单的比例控制方法,以及编程。掌握定时/计数器的使用。对循迹效果作分析。 二、实验概要
本实验将探讨红外测距的
。利用红外检测器的内置电子滤波功能,调节发射红外的载波频率,而检测器对不同频率的信号有不同的“敏感度”,这样,就能大概的知道距离。
1(测试红外的扫描频率。记录红外发射接收的距离。
2(尾随小车。让一个小车跟着另一个小车前行。要将前后距离控制在一定的范围内,若前后距离较大,后面跟随的小车应该加速,跟上去;若距离小于预定值,则减速。
3(跟踪黑色条纹带。红外测距的另一种形式的应用。也能让小车实现循迹功能。 三、实验内容
红外技术发展到现在,已经为大家所熟知,这种技术已经在现代科技、国防和工农业等领域获得了广泛的应用。红外传感系统是用红外线为介质的测量系统,按照功能能够分成五类:(1)辐射计,用于辐射和光谱测量;(2)搜索和跟踪系统,用于搜索和跟踪红外目标,确定其空间位置并对它的运动进行跟踪;(3)热成像系统,可产生整个目标红外辐射的分布图像;(4)红外测距和通信系统;(5)混合系统,是指以上各类系统中的两个或者多个的组合。红外传感器根据探测机理可分成为:光子探测器(基于光电效应)和热探测器(基于热效应)。
本次试验将尝试用红外来测距。
1(测试扫描频率
下图9-1显示的是一个特殊品牌的红外线探测器数据表(Panasonic PNA4602M)的部分摘录。这个摘录显示了红外线探测器在接收到频率不同于38.5 kHz时红外线信号时其敏感程度随频率变化的曲线图。
例如,当你发送频率为40 kHz的信号给探测器时,它的灵敏度是频率为38.5 kHz的50%。如果红外LED发送频率为42 kHz,探测器的灵敏度是频率为38.5 kHz的20%左右。尤其是对于让探测器的灵敏度很底的频率,为了让探测器探测到红外线的反射,物体必须离探测器更近让反射的红外光更强。
另一个角度来考虑就是最高灵敏度的频率可以探测最远距离的物体,较低灵敏度的频率可以探测距离较近的物体。这使得距离探测就简单了。选择5个不同频率,然后从最高灵敏度到最低灵敏度进行测试。首先尝试最高灵敏度频率,如果物体被探测到了,就让仅次于它的高灵敏度频率测试,观察是否可以探测到。依赖于探测器不能再检测到物体的红外线频率,我们就可以推断物体的大概位置。
图 9-1 滤波器灵敏度由载波频率决定
图 9-2 探测区域
例程:TestLeftFrequencySweep.c
例程要做两件事情:首先,测试IR LED/探测器(分别与P1_3和P1_2连接)以确认它们
的距离探测功能正常;然后,完成图9-2所示的频率扫描。
#include
#include
#define LeftIR P1_2 //左边红外接受连接到P1_2
#define LeftLaunch P1_3 //左边红外发射连接到P1_3
unsigned int time; //定时时间值
int leftdistance; //左边的距离
int distanceLeft, irDetectLeft;
unsigned int frequency[5]={29370,31230,33050,35700,38460};
void timer_init(void)
{
IE=0x82; //开总中断EA,允许定时器0中断ET0 TMOD |= 0X01; //定时器0工作在模式1:16位定时器模式 }
void FreqOut(unsigned int Freq) {
time = 256 - (500000/Freq); //根据频率计算初值
TH0 = 0XFF; //高八位设FF
TL0 = time; //低八位根据公式计算
TR0 = 1; //启动定时器
delay_nus(800); //延时
TR0 = 0; //停止定时器
}
void Timer0_Interrupt(void) interrupt 1 //定时器中断
{
LeftLaunch = ~LeftLaunch; //取反
TH0 = 0xFF; //重新设值
TL0 = time;
}
void Get_lr_Distances()
{
unsigned int count;
leftdistance = 0; //初始化左边的距离
for(count = 0;count<5;count++)
{
FreqOut(frequency[count]);//发射频率
irDetectLeft = LeftIR;
printf("irDetectLeft = %d",irDetectLeft);
if(irDetectLeft == 1)
leftdistance++;
}
}
int main(void)
{
uart_Init();
timer_init();
printf("Progam Running!\n");
printf("FREQENCY ETECTED\n");
while(1)
{
Get_lr_Distances();
printf("distanceLeft = %d\n",leftdistance);
printf("-----------------\n");
delay_nms(1000);
}
}
Tips:TestLeftFrequencySweep.c是如何工作的,
还记得“数组”吗,这里你将用整数型数组存储五个频率值:
unsigned int frequency[5]={29370,31230,33050,35700,38460};
uart_Init();
串口的初始化,这个函数已多次用到。
timer_init();
定时器的初始化。此例程使定时器0工作在模式1,16位定时模式,不具备自动重载功能。注意,timer_init()并没有开启定时器。
Get_lr_Distances();
机器人要发射某一频率,该给定时器设定多大的值呢,
n频率为f时,周期T=1/f,高低电平持续时间为t=1/(2T),根据公式TC=2-CC可算定时器初值time:
t50000016time265536 ,,,,,6f110,
但实际上,time值并未占满低八位,所以你可以这样简化计算:高八位设0xFF,低八位根据n=8时计算,即函数FreqOut(frequency[count])中用的time = 256 - (500000/Freq)
来计算。当低八位计满后,整个寄存器将溢出。
根据图6-2所示的描述原理,如果检测结果irDetectLeft为1,即没有发现物体,则距离leftdistance加1。循环描述,当5个频率描完后,可根据leftdistance的值来判断物体离机器人的大致距离。
运行程序时,在机器人前端放一白纸,前后移动白纸,调试终端将会显示白纸所在的区域,如图9-3所示。
图9-3 距离探测输出实例
程序通过计算 “1” 出现的数量,就可以确定目标在哪个区域。
紧记,这种距离测量方法是相对的而非绝对地精确。然而,它为机器人跟随,跟踪和其他行为提供了一个足够好的探测距离的能力。
, 输入、保存并运行程序TestLeftFrequencySweep.c
, 用一张纸或卡片面对IR LED/探测器做距离探测
, 改变纸片与机器人距离,记录使distanceLeft变化的位置
该你了――测试右边的IR LED/探测器
, 修改程序TestLeftFrequencySweep.c,对右边的IR LED/探测器做距离探测测试
, 运行该程序,检验这对IR LED/探测器能否测量同样的距离。
你可参考教材配套光盘对应例程中的注释部分。
例程:DisplayBothDistances.c
, 修改程序TestLeftFrequencySweep.c,添加右边IR LED/探测器部分
, 输入、保存并运行程序DisplayBothDistances.c
, 用纸片重复对每个IR LED进行距离探测,然后对两个IR LED同时进行测试
该你了――更多的距离测试
, 尝试测量不同物体的距离,弄清物体的颜色和(或)材质是否会造成距离测量的差异 2(尾随小车
让一个宝贝车跟随另一个宝贝车行走,跟随的宝贝车,也叫尾随车,必须知道距离引导车有多远。如果尾随车落在后面,它必须能察觉并加速。如果尾随车距离引导车太近,它也要能察觉并减速。如果当前距离正好合适,它会等待直到测量距离变远或变近。
距离仅仅是由机器人和其它自动化机器需要控制一种数值之一。当一个机器被用来自动维持某一数值,比如距离、压力或液位等,它一般都包含一个控制系统。这些系统有时由传感器和阀门组成,或者由传感器和电机组成。在宝贝车里面,由传感器和连续旋转电机组成。还必须有某些处理器可以接受传感器的测量结果并把它们转化为机械运动。必须对处理器编程来基于传感器的输入做出决定,从而控制机械输出。
闭环控制是一种常用的维持控制目标数据的方法,它很好地帮助宝贝车保持与一个物体之间的距离。闭环控制算法类型多种多样,最常用的有滞后、比例、积分以及微分控制。所有这些控制方法都将在《过程控制》教材中详细介绍。
事实上,图9-4所示的方框图描述了宝贝车用到的比例控制过程的步骤,即宝贝车用右边的IR LED/探测器探测距离并用右边的伺服电机调节机器人之间的位置以维持适当的距离。
图9-4 右边的伺服电机及IR LED/探测器的比例控制方框图
让我们仔细观察一下图9-4的数字,学习一下比例控制是如何工作的。这个特殊的例子是右边的IR LED/探测器和右边的伺服电机的比例控制方框图。设定位置为2,说明我们想宝贝车维持它和任何它探测到的物体之间的距离是2。测量的距离为4,距离太远。误差是设定值减去测量值的差,即2 - 4 = - 2 ,这在圆圈的左方以符号的形式指出,这个圆圈叫求和点。接着,误差传入一个操作框。这个操作框显示,误差将乘以一个比例常数Kp。Kp的值为70。该操作框的输出显示为–2×70 = –140,这叫输出校正。这个输出校正结果输入到另一个求和点,这时它与电机的零点脉冲宽度1500相加。相加的结果是1360,这个脉宽可以让电机大约以3/4全速顺时针旋转。这让宝贝车右轮向前、朝着物体的方向旋转。
第二次经过闭环,测量距离可能发生变化,但是没有问,因为不管测量距离如何变,这个控制环路将会计算出一个数值,让电机旋转来纠正任何误差。修正值与误差总是成比例关系,该误差就是设定位置和测量位置的关系的偏差。
控制环都有一组方程来主导系统行为。图9-4中的方框图是对该组方程的可视化描述方法。下面是从方框图中归纳出来的方程关系及结果:
Error = Right distance set point – Measured right distance
= 2 – 4
Output adjus = error?Kp
= –2 ?70
= –140
Right servo output = Output adjust + Center pulse width
= – 140 +1500
= 1360
通过一些置换,上面三个等式可被简化为一个,提供你相同的结果:
Right servo output = (Right distance set point – Measured right distance) Kp+ Center pulse
width
代入数值,我们可以看到结果一致:
= ((2 – 4)?70) + 1500
= 1360
左边的IR LED/探测器以及左边的伺服电机的控制框图如图9-5所示,与右边的运算法则类似。不同的是比例系数Kp的值由+70变为为-70。假设与右边的测量值一样,输出修正的脉冲宽度应该为1640。下面是该框图的计算等式:
Left servo output = (Left distance set point – Measured left distance) Kp + Center pulse
width
= ((2 – 4)?(–70)) +1500
图 9-5 机器人左伺服电机及 IR Led/探测器的比例控制方框图
例程:FollowingRobot.c
该例程实现刚才讨论过的各个伺服脉冲比例控制。换句话说,在每个脉冲发送之前,需要测量距离,决定误差信号,然后将误差值乘以比例系数Kp,再将结果加上(或减去)发送到左(或右)伺服电机的脉冲宽度值。
, 输入、保存并运行程序FollowingRobot.c
, 把大小为20×28cm的纸片置于机器人的前面,就像障碍物墙。机器人应该维持它和纸
片之间的距离为预定的距离
, 尝试轻轻旋转一下纸片,机器人应该跟随之旋转
, 尝试用纸片引导机器人四处运动,机器人应该跟随它
, 移动纸片距离机器人特别近时,机器人应该后退,远离纸片
#include
#include
#define LeftIR P1_2 //左边红外接受连接到P1_2
#define RightIR P3_5 //右边红外接收连接到P3_5
#define LeftLaunch P1_3 //左边红外发射连接到P1_3
#define RightLaunch P3_6 //右边红外发射连接到P3_6
#define Kpl -70
#define Kpr 70
#define SetPoint 2
#define CenterPulse 1500
unsigned int time;
int leftdistance,rightdistance;//左边和右边的距离
int delayCount,distanceLeft,distanceRight,irDetectLeft,irDetectRight;
unsigned int frequency[5]={29370,31230,33050,35700,38460};
void timer_init(void)
{
IE=0x82; //开总中断EA,允许定时器0中断ET0
TMOD |= 0X01; //定时器0工作在模式1:16位定时器模式
}
void FreqOut(unsigned int Freq)
{
time = 256 - (50000/Freq);
TH0 = 0XFF ;
TL0 = time ;
TR0 = 1;
delay_nus(800);
TR0 = 0;
}
void Timer0_Interrupt(void) interrupt 1
{
LeftLaunch = ~LeftLaunch;
RightLaunch= ~ RightLaunch;
TH0 = 0XFF;
TL0 = time;
}
void Get_lr_Distances()
{
unsigned char count;
leftdistance = 0; //初始化左边的距离
rightdistance = 0; //初始化右边的距离
for(count = 0;count<5;count++)
{
FreqOut(frequency[count]);
irDetectRight = RightIR;
irDetectLeft = LeftIR;
if (irDetectLeft == 1)
leftdistance++;
if (irDetectRight == 1)
rightdistance++;
}
}
void Send_Pulse(unsigned int pulseLeft,unsigned int pulseRight)
{
P1_1=1;
delay_nus(pulseLeft);
P1_1=0;
P1_0=1;
delay_nus(pulseRight);
P1_0=0;
delay_nms(18);
}
int main(void)
{
unsigned int pulseLeft,pulseRight;
uart_Init();
timer_init();
while(1)
{
Get_lr_Distances();
pulseLeft=(SetPoint-leftdistance)*Kpl+CenterPulse;
pulseRight=(SetPoint-rightdistance)*Kpr+CenterPulse;
Send_Pulse(pulseLeft,pulseRight);
} Tips:FollowingRobot.c是如何工作的, } 主程序做的第一件事是调用Get_lr_Distances子函数。Get_lr_Distances函数运行完成
之后,变量leftdistance和rightdistance分别包含一个与区域相对应的数值,该区域里的
目标被左、右红外线探测器探测到。
随后两行代码对每个电机执行比例控制计算:
pulseLeft =(SetPoint - leftdistance)* Kpl + CenterPulse pulseRight =(SetPoint – rightdistance) * Kpr + CenterPulse 最后调用子函数Send_Pulse对电机的速度进行调节。
因为你要做的实验是尾随,串口线的连接影响了机器人的运动,故可去掉。
该你了
图9-6所示是引导车和尾随车。引导车运行的程序是FastIrRoaming.c修改后的版本,尾
随车运行的程序是FollowingRobot.c。比例控制让尾随车成为忠实的追随者。一个引导车可
以引导一串大概6到7个尾随车。只需要把导引车的侧面板和后挡板加到其它的尾随车上。
图9-6 导引机器人(左)和尾随机器人(右)
, 如果你是成员之一,把纸板安装在导引小车的两侧和尾部,参考图9-6
, 如果你不属于班级成员的一部分(并且只有一个机器人),可以让尾随车跟随一张纸
或你的手来运动,就和跟随导引车一样
2kΩ的电阻替换掉连接机器人红外线发光二极管的470Ω电阻 , 用阻值为1kΩ或
, 使用程序FastIrRoaming.c修改后的版本对导引机器人编程来做避障试验,打开程序
FastIrRoaming.c重命名为SlowerIrRoamingForLeadRobot.c
, 对程序SlowerIrRoamingForLeadRobot.c做以下修改:
, 把1300的增加为1420
, 把1700的减少为1580
, 尾随车运行程序FollowingRobot.c,不用做任何修改
, 机器人都运行自己的程序,把尾随车放在引导车的后面。尾随车应该跟随一个固定的
距离,只要它不被其它的诸如手或附近墙壁等引开
你可以通过调整SetPoint和比例常数来改变尾随车的行为。用手或一张纸片来引导尾随车,做下面练习:
, 尝试用30到100范围内的常量Kpr和Kpl来运行程序FollowingRobot.c,注意机器人在
跟随目标运动的时候的响应有何差异
, 尝试调节常量SetPoint的值,范围从0到4
3(跟踪条纹带
图9-8是你可以搭建的一个路径并编程使机器人跟它运动的例子。路径中每个条纹带是由三条1/4英寸宽的聚乙烯绝缘带边对边并行放置在白色招贴板上组成的,绝缘带条纹之间不能漏出白色板。
1)搭建和测试路线
为了成功跟踪该路径,测试和调节机器人是必要的。
需要的材料:
(1)一张招贴板――大概尺寸: 22 X 28 英寸 (56 X 71 cm)
(2)1/4英寸(19 mm)宽黑色聚乙烯绝缘带一卷
, 参考图9-7用白色招贴板和绝缘带搭建运行路径
图9-7 条纹带跟踪 图9-8 红外探测器朝下扫描条纹带
2)测试条纹带
, 调节IR LED/探测器的位置向下和向外,如图6-8所示
, 确保绝缘带路径不受荧光灯干扰
, 用1k电阻代替与IR LED串联的470Ω电阻,使机器人更加近视 , 运行程序DisplayBothDistances.c。机器人与串口电缆相连,以便你能看到显示的距离
, 如图9-9所示,把机器人放在白色招贴板上
, 验证你的区域读数是否表示被探测的物体
在很近的区域,两个传感器给你的读数都
是1或0
, 放置机器人使两个IR LED/检测器都直接指
10和9-11所向三条绝缘带的中心,如图9-
示,然后调整机器人的位置(靠近或远离
绝缘带)直到两个区域的值都达到4或者5,
这表明要么发现一个很远的物体,要么没
有发现物体
图9-9 低区域测试俯视图 , 如果在你的绝缘带路径上很难获得比较高的读数值,参考绝缘带路径排错部分
图9-10 高区域测试顶视图 图9-11 高区域测试(侧视图)
3)绝缘带路径排错
如果当IR LED/检测器指向绝缘带路径的中心的时候你不能获得比较高的读数值,代替原来三条绝缘带用四条绝缘带搭建路径。如果区域读数仍然低,确认你是用1k?电阻串联在IR LED上。你可以试用2k?电阻使机器人更加近视。如果都不行,试试不同的绝缘带。调整IR LED/探测器,使它们指向更靠近或更远离机器人的前部可能有帮助。
如果当读白色表面时你的低区域测试有问题。试试将IR LED/探测器朝机器人的方向再向下调整,但是要注意不要让底盘带来干扰。你也可以试试一个更低阻值的电阻。
如果你用老的缩小包装的IR LED代替带套筒的IR LED,当IR LED/探测器聚焦在白色背景上时你要得到一个低区域的值可能有问题。这些IR LED可能需要串联220?电阻。也要确保IR LED的脚没有相互接触。
, 现在,将机器人放在绝缘带路径上,它的轮子正好跨在黑色线上。IR探测器应该稍稍
向外,如图9-12。验证两个距离读数是否又是0或者1。如果读数较高,意味着IR探测
器需要再稍微朝远离绝缘带边缘的方向向外调整一下
图9-12 IR检测器朝向放大图
当你把机器人沿图中双箭头所示的任何一个方向移动,两个IR中的一个会指向绝缘带上。当你做了这些后,这个指向绝缘带上的IR的读数应该增加到4或5。记住如果你将机器人向左移动,右边检测器的值会增加,如果你将机器人向右移动,左边检测器的值会升高。
, 调整IR LED/检测器直到机器人通过这个最后的测试,然后你可以试验下面的例程使
机器人沿着条纹带行走
4)编程跟踪条纹带
你只需对程序FollowingRobot.c做一点小小的调整,就可以使机器人跟踪条纹带行走。
首先,机器人应当向目标靠近,以使到目标的距离比SetPoint要小;或远离目标,以使距离比SetPoint大,这同程序FollowingRobot.c的表现相反。当机器人离物体的距离不在SetPoint的范围内时,让机器人向相反的方向运动。只需简单地更改Kpl和Kpr的符号,换句话说,将Kpl由-70改为70;由Kpr由70改为-70。你应该做试验,当SetPoint从2到4时,看哪个值使系统工作稳定。下面的例程将SetPoint值改为3。
例程:StripeFollowingRobot.c
, 打开程序FollowingRobot.c另存为StripeFollowingRobot.c
, 将SetPoint的值由2改为3
, 将Kpl由-70改为70
, 将Kpr由70改为-70
, 运行程序
, 将机器人放在图9-7所示的“Start”位置,机器人将静止。如果你把手放在IR组前面,
然后它会向前移动,当它走过了开始的条纹带时,把手移开,它会沿着条纹带行走。
当它看到“Finish”条纹带时,它应该停止不动
, 假定你从绝缘带获得的距离读数为5,从白色招贴板获得的读数为0,SetPoint的常量
、3 以及4时都可以正常工作。尝试不同的SetPoint值,注意机器人在条纹带上值为2
运行时的性能
附录:
定时/计数器的运用
实验需要用到单片机更精确的定时功能,因此再回顾一下51单片机定时/计数器的使用方法。单片机的定时/计数器能够提供更精确的时间。
前面已经介绍了几种延时方法,除了空操作函数_nop_()外,定时/计数器能产生更精确的延时,它的最小延时单位为1个机器周期。前面讲过:若晶振频率为12MHz,则延时单位为1us;若为11.0592MHz,则延时单位为1.08us。
单片机P89V51RD2的定时/计数器可以分为定时器模式和计数器模式。其实这两种模式没有本质上的区别,均使用二进制的加一计数:当计数器的值计满回零时能自动产生中断的请求,以此来实现定时或者计数功能。它们的不同之处在于定时器使用单片机的时钟来计数,而计数器使用的是外部信号。
定时/计数器的控制
单片机P89V51RD2有3个定时/计数器,通过TCON和TMOD这两个特殊功能寄存器控制。TCON和TMOD你都可以在头文件uart.h中看到其应用。
TCON为定时器控制寄存器,有8位,每个位的含义为如表9-1所示。TCON的低4位与定时器无关,它们用于检测和触发外部中断。
表 9-1 TCON控制寄存器
位 符 号 描述
TCON.7 TF1 定时器1溢出标志位。由硬件置位,由软件清除 TCON.6 TR1 定时器1运行控制位。由软件置或清除:置1为启动;置0为停止 TCON.5 TF0 定时器0溢出标志位
TCON.4 TR0 定时器0运行控制位
TCON.3 IE1 外部中断1边沿触发标志
TCON.2 IT1 外部中断1类型标志位
TCON.1 IE0 外部中断0边沿触发标志
TCON.0 IT0 外部中断0类型标志位
TMOD为定时器模式寄存器,它也有8位,但不能像TCON一样可以一位一位的设置,只能通过字节传送指令来设定TMOD的各个状态。TMOD的各位定义如表9-2所示。
表9-2 TMOD模式寄存器
位 名字 定时器 描述
7 GATE 1 门控制。当被置为1时,只有为高电平时,定时器才开始工作 INT
6 1 定时/计数器选择位:1=计数器;0=定时器 C/T
5 M1 1 模式位1(见表6-3)
4 M0 1 模式位0(见表6-2)
3 GATE 0 定时器0的门控制位
2 0 定时器0的定时/计数选择位 C/T
1 M1 0 定时器0的模式位1
0 M0 0 定时器0的模式位0
表9-3 定时器工作模式
M1 M0 模式
0 0 0
0 1 1
1 0 2
1 1 3
工作模式
计数器都有一个16位的寄存器Tn(n=0或1)来控制计数长度,由高8位THn和 每个定时/
低8位TLn置初值。定时/计数器有四种工作模式。
模式0:定时/计数器按13位自加1计数器工作。这13位由TH的全部8位和TL中的低5位组成,TL中的高3位没有用到。
模式1:定时/计数器按16位自加1计数器工作。
模式2:定时/计数器被拆成一个8位寄存器TH和一个8位计数器TL,以便实现自动重载。这种模式使用起来非常方便,一旦设置好TMOD和THn,定时器就可以按设定好的周期溢出。 模式3:TH0和TL0均作为两个独立的8位计数器工作。定时器1在模式3下不工作。 定时/计数器初值的计算
定时/计数器是在计数初值的基础上加法记数的,假设Tn(TLn和THn)中写入的值为TC,
n在该模式下最大计数值为2,程序运行的计数值为CC nTC=2-CC
回顾一下,前面的实验中已经用LED来测试电路,通过延时函数使LED每隔一段时间闪烁
一次。在实验中,你是否可以通过定时/计数器来实现LED测试电路呢,
假设通过P1_0所接的灯每0.4ms闪动一次,即每过0.2ms灭一次,再过0.2ms亮一次。
8模式2最大计数值为256us(2),满足要求,因此用模式2来显示LED灯闪烁功能,计数的值
CC为0.2ms/1us=200。利用公式计算得出TC=256-200=59,换成十六进制为TC=0x38。 例程:TimeApplication.c
, 搭建LED的测试电路(具体请参照第二章内容)
, 接通教学板的电源
, 输入、保存并运行程序Time_Application.c
, 验证与P1_0连接的LED是否每个0.4ms闪烁一次
#include
#include
void initial(void); //子函数声明
void main(void)
{
initial(); //调用定时/计数器初始化函数
while(1); //等待中断
}
/*===========================================
初始化定时/计数器函数
===========================================*/
void initial(void)
{
IE=0x82; //开总中断EA,允许定时器0中断ET0
TCON=0x00; //停止定时器,清除标志
TMOD=0x02; //工作在定时器0的模式2中
TH0=0x38; //设置重载值
TL0=0x38; //设置定时器初值
TR0=1; //启动定时器0
}
//中断服务程序
void TIMER(void) interrupt 1 //中断服务程序,1是定时器0的中断号
{
P1_0=~P1_0; //P1_0的值取反 TimeApplication.c是如何工作的, }
在程序开头,你看到了两个头文件——reg51.h和stdio.h,它们有什么用呢,打开这两
个头文件(reg51.h在“C:\Program Files\Keil\C51\INC”目录下,stdio.h在“C:\Program
Files\Keil\C51\INC”目录下),你可以看到:在reg51.h中对一些标识符进行了声明,如
P1_0(可能没有,要自己在程序中定义)、IE、TCON等;而stdio.h对常用的一些IO函数进行
了声明,如printf()等。
在,程序中,一个函数的定义可以放在任意位置,既可放在主函数main之前,也可放在main之后,但如果放在main之后的话,那么应该在main函数的前面加上这个函数的声明:
void initial(void); //子函数声明
主函数main()很好理解:首先对中断进行初始化设置,然后等待中断。
IE=0x82;
EA=1且ET0=1,打开了全局和定时器0的中断(参考表6-4)。
TCON=0x00;
停止定时器,并清除了中断标志(参考表6-1)。
TMOD=0x02;
M1=0且M0=0,定时器0选择模式2(参考表6-2)。
TH0=0x38;
TL0=0x38;
设置计数初值和重载值。
TR0=1;
启动定时器0(参考表9-1)。
中断
中断即发生了某种情况(事件),使得CPU暂时中止当前程序的执行,转去执行相应的处理程序。中断在单片机应用的设计与实现中起着非常重要的作用。使用中断允许系统响应事件并在执行其他程序的过程中处理该事件。中断驱使系统能够在同一时间处理许多任务。在某种程度上,中断与子程序有些相似:CPU执行另一个程序——子程序——然后返回主程序。
单片机P89V51RD2有6个中断源:2个外部中断源;3个定时器中断;1个串口中断。
每个中断源可以单独允许或禁止,通过修改可位寻址的专用寄存器IE(允许中断寄存器)实现,如表9-4所示。
表9-4 IE(中断使能)寄存器简表
位 符 号 描述(1=使能,0=禁止)
IE.7 EA 全局允许/禁止
IE.6 未定义
IE.5 ET2 允许定时器2中断
IE.4 ES 允许串口中断
IE.3 ET1 允许定时器1中断
IE.2 EX1 允许外部中断1
IE.1 ET0 允许定时器0中断
IE.0 EX0 允许外部中断0
中断优先级
P89V51RD2的中断分为2级,高和低。利用“优先级”的概念,允许拥有高优先级的中断源中断系统正在处理的低优先级的中断源。
中断的优先级由高到低依次为:外部中断0,定时器0,外部中断1,定时器1,串口中断,定时器2中断。
编译器Keil uVision3支持在C源程序中直接开发中断程序,提高了工作效率。中断服务程序是通过按规定语法格式定义的一个函数,语法格式如下:
返回值 函数名([参数])interrupt m[using n]
{
„„
}
其中,m(0,31)表示中断号,C51编译器允许32个中断,定时器0的中断号为1;n(0,3)表示第n组寄存器,例程没有使用该参数,默认为寄存器组0。
寄存器组n的使用
P89V51RD2有四个寄存器组,每个寄存器组由8个字节组成。默认情况下(系统复单片机
位后),程序使用第一个寄存器组0。
使用“寄存器组”的概念使软件的不同部分可以拥有一组私有的寄存器,不受其他部分的影响,因而可以快速高效地进行“上下文切换”。
由于LED灯的闪烁频率过快,而人的视觉反应不够快,因此你观察到LED灯是一直亮着的。你可以借助示波器观察P1_0输出的是不是矩形波,周期是不是400us。
该你了——调整定时器时间
为了可以看见LED灯闪烁,你可以使用定时器模式0,由于在此方式下最大延时时间为8ms
13(2=8192)。对比前面的LED程序,分析它们有何不同之处,使用示波器观察,你会发现使用定时器方式可以产生更精确的时间。
若效果还不明显,你可设计一个循环,如当检测到2500次中断后更改一次IO口的电平,即将闪烁时间改为2500*0.4ms=1s,有利于肉眼观察。
本文档为【利用红外发射接收传感器进行距离检测】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。