#include
#include
unsigned char code LedChar[]={ //数码管真值表
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71
};
unsigned char LedBuff[]={ //数码管暂存值
0x00,0x00,0x00,0x00
};
unsigned int sec = 0; //超声波测算距离
unsigned char PWM_t1; //PWM1高电平时间
unsigned char PWM_t2; //PWM2高电平时间
unsigned char Timer_flag = 0; //超声波溢出值 ;
unsigned char T1count = 0; //舵机1的周期
unsigned char T2count = 0; //舵机2的周期
sbit ADDR0 = P1^4;//数码管段选
sbit ADDR1 = P1^5;
sbit ADDR2 = P1^6;
sbit ADDR3 = P1^7;
sbit Trig = P1^0; //超声波发射引脚
sbit Echo = P1^1; //超声波接收引脚
sbit BUZZ = P1^3; //蜂鸣器
sbit PWM1 = P1^2; //舵机1
sbit PWM2 = P3^4; //舵机2
sbit SE3 = P3^5; //舵机3——暂时没用上
void Timer0_Init(); //定时器0方式一,配置1ms中断的函数
void Timer1_Init(); //定时器1方式一,配置1ms中断的函数
void Inter_Timer(); //外部中断
void LedCount(); //数码管显示函数
void TrigTimer(); //超声波发射函数
void EchoSec(); //超声波计算距离函数
void delay(unsigned long i) //延时函数
{
unsigned int r;
for(r=0; r>=1000; r++)
{
while(i--);
}
}
void main()
{
unsigned int e = 0;
Timer0_Init(); //timer0
Timer1_Init(); //timer1
while(1)
{
for(e=0; e<=100; e++)
{
PWM_t2 = 15; //舵机2归中
PWM_t1 = 15; //舵机1归中
if(e<50)
{
TrigTimer();
}
delay(100);
}
for(e=0; e<=100; e++)
{
PWM_t1 = 11; //舵机1右转
if(e<50)
{
TrigTimer(); //超声波驱动函数
}
delay(100);
if(sec<=200)
{
delay(1000);
if(sec<=250) //距离小于250
{
PWM_t2 = 11; //舵机2右转
}
}
}
for(e=0; e<=100; e++)
{
PWM_t2 = 15; //舵机1归中
PWM_t1 = 15; //舵机2归中
if(e<50)
{
TrigTimer();
}
delay(100);
}
for(e=0; e<=100; e++)
{
PWM_t1 = 19; //舵机1左转
if(e<50)
{
TrigTimer();
}
delay(100);
if(sec<=250)
{
delay(1000);
if(sec<=250) //距离小于250
{
PWM_t2 = 19; //舵机2左转
}
}
}
}
}
void Timer0_Init() //定时器0方式一,配置1ms中断的函数
{
TMOD &= 0xF0;
TMOD |= 0x01; //配置定时器0方式一,这样设置不影响定时器1的配置
// TH0 = 64536/256; //定时1ms,高8位(65536-1000)/256
// TL0 = 64536%256; //定时1ms,低8位(65536-1000)%256,这个不够精准,实际应该是(65536-1000)%256+1
TH0 = 0x00;
TL0 = 0x00;
TF0 = 0; //清除TF0标志
EA = 1; //开总中断
ET0 = 1; //开定时器0中断
PT0 = 0; //中断优先级,0为低优先级,1为高优先级
}
void Timer1_Init() //定时器1方式一,配置1ms中断的函数
{
TMOD &= 0x0F;
TMOD |= 0x10; //配置定时器0方式一,这样设置不影响定时器1的配置
TH1 = (65535-100)/256;
TL1 = (65535-100)%256;
TF1 = 0; //清除TF1中断标志
TR1 = 1;
EA = 1; //开总中断
ET1 =1; //开定时器1中断
PT1 = 1; //中断优先级,0为低优先级,1为高优先级
}
void LedCount() //数码管显示函数
{
unsigned char h; //数码管段选值
unsigned char l = 0;
for(l=0; l<=4; l++)
{
P0 = 0x00;
switch (h)
{
case 0: ADDR0=0; ADDR1=1; ADDR2=1; ADDR3=1; h++; P0=LedBuff[3]; break;
case 1: ADDR0=1; ADDR1=0; ADDR2=1; ADDR3=1; h++; P0=LedBuff[2]; break;
case 2: ADDR0=1; ADDR1=1; ADDR2=0; ADDR3=1; h++; P0=LedBuff[1]; break;
case 3: ADDR0=1; ADDR1=1; ADDR2=1; ADDR3=0; h=0; P0=LedBuff[0]; break;
default: break;
}
}
}
void TrigTimer() //超声波发射函数
{
Trig = 1;
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
Trig = 0;
while(!Echo);
TR0 = 1; //定时器0开始计时
while(Echo);
TR0 = 0;
EchoSec();
}
void EchoSec() //超声波计算距离函数
{
unsigned long s = 0;
unsigned long time = 0;
time = TH0*256+TL0;
s = time*0.17;
TH0 = 0;
TL0 = 0;
if(s>=800 || Timer_flag==1) //超出测量范围
{
sec = 9999; //显示9999
}
else
{
sec = s;
if(sec <= 500) //距离小于500,蜂鸣器工作(有源)
{
BUZZ = ~BUZZ;
}
}
LedBuff[0] = LedChar[sec%10];
LedBuff[1] = LedChar[sec/10%10];
LedBuff[2] = LedChar[sec/100%10];
LedBuff[3] = LedChar[sec/1000%10];
LedCount();
}
void InterruptTimer0 () interrupt 1 //超声波计时中断
{
Timer_flag = 1; //超声波中断溢出标志位
}
void InterruptTimer1 () interrupt 3 //超声波发射及数码管显示函数
{
TH1 = (65535-100)/256;
TL1 = (65535-100)%256;
T1count++;
if(T1count >= 200) //20毫秒一个周期
{
T1count = 0;
}
if(T1count <= PWM_t1)
{
PWM1 = 1;
}
else
{
PWM1 = 0;
}
T2count++;
if(T2count >= 200)
{
T2count = 0;
}
if(T2count <= PWM_t2)
{
PWM2 = 1;
}
else
{
PWM2 = 0;
}
}
//可以直接用,我测试过,欢迎大家提问题,由于我自学的,专业术语我可能不知道,但是我会尽自己的努力,并且我的目标不止于此,我是要自己做个多功能避障小车,上面还有一些距离光电,计数器等等