根据提供的文件信息,我们可以分析出该程序主要实现了利用单片机进行超声波测距的功能,并将结果通过LED显示器显示出来。接下来,我们将对这段代码的关键部分进行详细解析。 ### 超声波测距原理简介 超声波测距的基本原理是发射一束超声波,然后测量这束超声波往返所需的时间来计算距离。超声波在空气中的传播速度大约为340米/秒,在实际应用中,这个值可能会受到温度、湿度等因素的影响而有所变化。因此,为了提高精度,通常会采用温度补偿等技术手段。 ### 程序结构分析 #### 主函数 `main(void)` 主函数首先初始化了单片机的端口和定时器,并进入一个无限循环。在这个循环中,程序调用 `cs_t()` 函数触发超声波的发射,然后等待一段时间(通过 `delay(1);` 实现),之后检查 `testok` 变量的状态。如果 `testok` 为1,则表示接收到了回波信号,此时程序读取定时器的值,并计算出距离;如果 `testok` 不为1,则认为没有接收到有效的回波信号,此时会在显示器上显示错误信息。 #### 超声波控制函数 `cs_t()` 这部分代码未完全给出,但从注释可以推测,这是一个外部声明的函数,用于控制超声波的发射。具体实现应该是通过设置定时器并触发外部中断来实现的。 #### 中断处理函数 - **超声波接收中断** (`void cs_r(void) interrupt 0`): 当接收到回波时,此中断被触发。在这个函数中,程序关闭定时器、外部中断,并将 `testok` 设置为1。 - **定时器溢出中断** (`void overtime(void) interrupt 1`): 如果在预期时间内没有接收到回波信号,则触发此中断。程序同样关闭定时器、外部中断,并将 `testok` 设置为2。 #### 显示器驱动函数 `display(uchar*)` 这个函数负责将数字转换成适合LED显示器显示的形式。它首先递增 `DISPNUM` 来选择要显示的位数,然后根据选择的位数和存储的数字信息,查找 `DISPTABLE` 数组来获取对应的LED显示码,并通过 `P0` 和 `P2` 端口输出到LED显示器上。 ### 关键代码解释 #### 距离计算 ```c time = TH0; time = (time << 8) | TL0; time *= 172; time /= 10000; ``` 这一段代码用于计算超声波从发射到接收所经历的时间,并据此计算出距离。其中 `TH0` 和 `TL0` 分别是定时器高8位和低8位的值。由于超声波在空气中的传播速度大约为每秒340米,因此可以通过公式 `时间 * 声速 / 2` 计算出距离(除以2是因为计算的是往返时间)。这里使用了一个经验值 `172` 来近似表示声速,并进行了适当的单位转换。 #### 显示逻辑 在 `display` 函数中,通过以下代码实现了LED显示器的驱动: ```c MOV A,DISPNUM CJNE A,#4D,DISP1 DISP1: JCDISP2 MOV DISPNUM,#00H MOV DISPBIT,#0FEH ``` 这里通过比较 `DISPNUM` 的值与预设值 `#4D` 来判断是否已经完成了所有位数的显示,如果是,则重置 `DISPNUM` 并更新 `DISPBIT` 的值。 ### 总结 该程序实现了一种基于单片机的超声波测距系统,能够有效地测量目标的距离并将结果显示在LED显示器上。通过对外部中断和定时器的巧妙运用,使得整个系统的测量精度得到了保证。同时,通过合理的软件设计,简化了硬件电路,降低了成本,具有很好的实用价值。
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
extern void cs_t(void);
extern void delay(uint);
extern void display(uchar *);
data uchar testok;
/*主程序*/
void main(void)
{
data uchar dispram[5];
data uint i;
data ulong time;
P0=0xff;
P2=0xff;
TMOD=0x11;
IE=0x80;
while (1)
{
cs_t();
delay(1);
testok=0;
EX0=1;
ET0=1;
while(!textok)display(dispram);
if(1==testok)
{
time=TH0;
time*=172;
time/=10000;
dispram[0]=(uchar)(time%10);
time/=10;
dispram[1]=(uchar)(time%10);
time/=10;
dispram[2]=(uchar)(time%10);
dispram[3]=(uchar)(time/10);
if(0==dispram[3])dispram[3]=17;
}else
{
dispram[0]=16;
dispram[1]=16;
dispram[2]=16;
dispram[3]=16;
}
for(i=0;i<300;i++)display(dispram);
}
}
/*超声波接收程序*/
void cs_r(void) interrupt 0
{
TR0=0;
ET0=0;
EX0=0;
testok=1;
}
/*超时消除程序(内中断T0)*/
void overtime(void) interrupt 1
剩余5页未读,继续阅读
- 粉丝: 0
- 资源: 13
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助