51单片机驱动舵机超声波测距,数码管显示


  • 我是小白,程序肯定有需要改进的地方,大家参考就行

#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;
    }
}

 

 

//可以直接用,我测试过,欢迎大家提问题,由于我自学的,专业术语我可能不知道,但是我会尽自己的努力,并且我的目标不止于此,我是要自己做个多功能避障小车,上面还有一些距离光电,计数器等等51单片机驱动舵机超声波测距,数码管显示_第1张图片

 

 

你可能感兴趣的:(51单片机)