main.c
/** * 文件名称:超声波测距实验 * 实验目的:1.掌握超声波测距原理 * 实验原理:1.定时器0用于数码管的扫描、定时200ms用于采样距离; * 定时器1用于计时器,计算每次采样时从 * 发射声波到接收到声波的时间。距离除以2就为到 * 障碍物的实际距离。 */ #include <stc15f2k60s2.h> #include <intrins.h> #include "stdint.h" #include "timer.h" #include "digitalTube.h" #define somenop(); { \ _nop_();_nop_();_nop_();_nop_();_nop_(); \ _nop_();_nop_();_nop_();_nop_();_nop_(); \ } sbit TX = P1^0; //发射引脚 sbit RX = P1^1; //接收引脚 void configTmr1(); void sendWave(); volatile bit flag200ms = 0; void main() { uint16_t count; //定时器1的计数值,即为时间间隔 uint8_t distance; //单位为cm,实测最大测量距离约为90cm uint8_t tmp; configTmr0(2); configTmr1(); while (1) { if (flag200ms) { //200毫秒更新一次数据 flag200ms = 0; RX = 1; //!! sendWave(); //发送方波信号 TR1 = 1; //启动计时 while ((RX == 1) && (TF1 == 0)); //等待收到脉冲 TR1 = 0; //关闭计时 if (TF1 == 1) { //如果定时器发生溢出,则超过量程 TF1 = 0; distance = 0xFF; //无返回,距离为无穷远 } else { count = TH1; count <<= 8; count |= TL1; //distance = (uint8_t)(count * 0.017f); //计算距离(cm) distance = (uint8_t)((uint32_t)count * 17 / 1000); //计算距离(cm) } TH1 = 0; //重新复位定时器,为下次测量做好准备 TL1 = 0; dspBuf[7] = distance % 10; //将结果显示出来 tmp = distance / 10 % 10; if (tmp) dspBuf[6] = tmp; else dspBuf[6] = 10; //否则为0,不显示 tmp = distance / 100 % 10; if (tmp) dspBuf[5] = tmp; else dspBuf[5] = 10; } } } /* 特殊配置定时器1,作为计时器 */ void configTmr1() { //不要开启中断,要将溢出标志位置0,不要开始运行 AUXR &= 0xBF; TMOD &= 0x0F; TMOD |= 0x10; TL1 = 0; //!!! TH1 = 0; //!!! TF1 = 0; //!!! } //TX引脚发送40KHz方波信号驱动超声波发送探头 void sendWave() { uint8_t cnt = 8; //发送8个脉冲 EA = 0; //!!! do { TX = 1; somenop(); //保持TX一段时间 TX = 0; somenop(); //保持TX一段时间 } while (--cnt); EA = 1; //!!! } //定时器0中断服务函数 void tmr0ISR() interrupt 1 { static uint16_t cnt = 0; TH0 = tmr0HighByte; TL0 = tmr0LowByte; digitalTubeScan(); //2ms执行一次 if (cnt == 99) { cnt = 0; flag200ms = 1; } else { cnt++; } }
digitalTube.h
#ifndef _DIGITAL_TUBE_H #define _DIGITAL_TUBE_H extern uint8_t code tab[]; extern uint8_t dspBuf[8]; void digitalTubeScan(); #endif
digitalTube.c
#include <stc15f2k60s2.h> #include "stdint.h" #include "digitalTube.h" uint8_t code tab[] = { // 0 1 2 3 4 5 6 7 8 9 null 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xFF }; uint8_t dspBuf[8] = { 10, 10, 10, 10, 10, 10, 10, 10 }; //显示缓冲区 void digitalTubeScan() { static uint8_t index = 0; P2 = (P2 & 0x1F) | 0xE0; //使能具体值 P0 = 0xFF; //消隐 P2 &= 0x1F; //锁存 P2 = (P2 & 0x1F) | 0xC0; //使能位选 P0 = (1 << index); //数码管选择是1有效 P2 &= 0x1F; P2 = (P2 & 0x1F) | 0xE0; //使能具体值 P0 = tab[dspBuf[index]]; // P2 &= 0x1F; index = (index + 1) & 0x07; }
timer.h
#ifndef _TIMER_H #define _TIMER_H #define SYS_MCLK 11059200 extern uint8_t tmr0LowByte, tmr0HighByte; //extern uint8_t tmr1LowByte, tmr1HighByte; void configTmr0(uint8_t ms); //void configTmr1(uint8_t ms); #endif
timer.c
#include <stc15f2k60s2.h> #include "stdint.h" #include "timer.h" uint8_t tmr0LowByte, tmr0HighByte; //uint8_t tmr1LowByte, tmr1HighByte; void configTmr0(uint8_t ms) { //!!8bits uint32_t tmp; //小心溢出 tmp = ms * SYS_MCLK / 12 / 1000; tmp = 65536 - tmp; tmr0LowByte = (uint8_t)tmp; tmr0HighByte = (uint8_t)(tmp >> 8); AUXR &= 0x7F; //定时器时钟12T模式 TMOD &= 0xF0; TMOD |= 0x01; TL0 = tmr0LowByte; TH0 = tmr0HighByte; EA = 1; ET0 = 1; TR0 = 1; } /* void configTmr1(uint8_t ms) { //!!8bits uint32_t tmp; tmp = ms * SYS_MCLK / 12 / 1000; tmp = 65536 - tmp; tmr1LowByte = (uint8_t)tmp; tmr1HighByte = (uint8_t)(tmp >> 8); AUXR &= 0xBF; TMOD &= 0x0F; TMOD |= 0x10; TL1 = tmr1LowByte; TH1 = tmr1HighByte; EA = 1; ET1 = 1; TR1 = 1; } */
stdint.h
#ifndef STDINT_H_INCLUDED #define STDINT_H_INCLUDED typedef unsigned char uint8_t; typedef unsigned int uint16_t; typedef unsigned long uint32_t; typedef signed char int8_t; typedef signed int int16_t; typedef signed long int32_t; #endif // STDINT_H_INCLUDED