笔狸狸 2025-09-29 16:42 采纳率: 50%
浏览 7
已结题

51小车超声避障好像卡循环了

检查了一下,运行时到while(echo);停止了,能确定引脚没有接错。

img

下面是全部代码:


#include <REGX52.H>

sbit ENB=P2^0;
sbit IN4=P2^1;
sbit IN3=P2^2;

sbit IN1=P2^3;
sbit IN2=P2^4;
sbit ENA=P2^6;     //

sbit echo=P3^4;
sbit trig=P3^3;    //

unsigned long Time;
unsigned int Distance;

void Timer0Init(void)        //0开始计时@11.0592MHz
{
    TMOD &= 0xF0;        //设置定时器模式
    TMOD |= 0x01;        //设置定时器模式
    TL0 = 0x00;        //设置定时初值
    TH0 = 0x00;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    EA=1;
    
}



void Delay15us()        //@11.0592MHz
{
    unsigned char i;

    i = 4;
    while (--i);
}

void Delay10ms(xms)        //@11.0592MHz
{
    while(xms)
    {
        unsigned char i, j;

        i = 18;
        j = 235;
        do
        {
            while (--j);
        } while (--i);
        xms--;
    }
}

//void Measure()
//{
////    unsigned int Timeout = 0;
//    trig=1;
//    Delay15us();
//    trig=0;
////    while(!echo && Timeout++ < 50000);
////  if(Timeout >= 50000) return; 
////       
////  TR0 = 1;
////  Timeout = 0;
////  while(echo && Timeout++ < 50000);
////  TR0 = 0;
//    
//    while(echo)
//    {
//        TR0=1;
//        break;
//    }
////    while(echo);
////    TR0=0;
////    Time=(256*TH0+TL0)*120000/110592;
////    TH0=TL0=0;
////    Distance=Time*0.17;       //mm
//    if(echo)
//    {
//        TR0=0;
//        Time=(256*TH0+TL0)*120000/110592;
//        TH0=TL0=0;
//        Distance=Time*0.17;       //mm

//    }
////    SendData[0]=Distance/1000 +'0';
////    SendData[1]=Distance%1000/100 +'0';
////    SendData[2]=Distance%100/10 +'0';
////    SendData[3]='.';
////    SendData[4]=Distance%10 +'0';
////    SendData[5]='c';
////    SendData[6]='m';
////    TxStr(SendData);
////    TxStr("\r\n");
//}
























unsigned char SendData[10]={0x00};




void UartInit(void)        //9600bps@11.0592MHz
{
    SCON = 0x50;        //8位数据,可变波特率
    TMOD &= 0x0F;        //清除定时器1模式位
    TMOD |= 0x20;        //设定定时器18位自动重装方式
    TL1 = 0xFD;        //设定定时初值
    TH1 = 0xFD;        //设定定时器重装值
    ET1 = 0;        //禁止定时器1中断
    TR1 = 1;        //启动定时器1
    ES=1;
}

void TxStr(unsigned char *Str)
{
    ES=0;
    while(*Str!=0)
    {
        SBUF = *Str;
        while(TI==0);
        TI=0;
        Str++;
    }
    ES=1;
}


void Measure()
{
    unsigned int Timeout = 0;
    trig=1;
    Delay15us();
    trig=0;
    while(!echo && Timeout++ < 50000);
  if(Timeout >= 50000) return; 
       
  TR0 = 1;
  Timeout = 0;
  while(echo && Timeout++ < 50000);
  TR0 = 0;
    
    while(!echo);
    TR0=1;
    while(echo);
    TR0=0;
    Time=(256*TH0+TL0)*120000/110592;
    TH0=TL0=0;
    Distance=Time*0.17;       //mm
    
    SendData[0]=Distance/1000 +'0';
    SendData[1]=Distance%1000/100 +'0';
    SendData[2]=Distance%100/10 +'0';
    SendData[3]='.';
    SendData[4]=Distance%10 +'0';
    SendData[5]='c';
    SendData[6]='m';
    TxStr(SendData);
    TxStr("\r\n");
}

















void main()
{
    Timer0Init();
    echo=1;
    trig=0;
    Distance=0;
    P2_7=1;

        ENB=1;    //M轮  目前正转    
        IN4=1;
        IN3=0;
        
        ENA=1;    //N轮  目前正转
        IN2=0;
        IN1=1;

    while(1)
    {
        if(Distance<=1)
        {
            P2_7=~P2_7;
            IN4=0;
            IN3=1;
                

                
            

        }
        else
        {
            P2_5=1;
            
            IN4=1;
            IN3=0;
        }
        
        Measure();

    }    
}

希望大家有时间能帮忙看一下到底那里出问题了,以及要怎么处理

  • 写回答

5条回答 默认 最新

  • 檀越@新空间 2025-09-29 16:43
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    你提到的问题是:“51小车超声避障好像卡循环了,运行时到while(echo);停止了”,这表明程序在 Measure() 函数中执行到 while(echo);无法退出,导致程序卡死


    问题分析

    1. 引脚配置是否正确?

    你已经确认引脚没有接错,这是一个关键点。但为了确保万无一失,可以再次检查以下内容:

    • echotrig 是否分别连接到了 P3^4 和 P3^3?
    • 是否有外部电路(如上拉电阻)?

    结论:引脚配置基本没问题。


    2. Measure() 函数中的逻辑问题

    从你的代码看,Measure() 函数存在几个严重的问题:

    错误1:TR0 的控制混乱

    你在 Measure() 中多次设置 TR0 = 1;TR0 = 0;,但是你并没有在函数中启动定时器,也没有正确使用它。

    错误2:未启用定时器中断

    你定义了 Timer0Init(),但并没有开启定时器中断(ET0 = 1;),因此即使 TR0 = 1;,也不会触发任何计时。

    错误3:while(echo); 会卡死

    这个语句的意思是:一直等待 echo 引脚为高电平,如果 echo 没有被拉低,就会一直卡在这里。


    🔧 解决方案

    步骤 1:修正 Timer0Init() 函数

    你需要开启定时器 0 的中断,并且设置正确的初值。

    void Timer0Init(void)        //由0开始计时@11.0592MHz
    {
        TMOD &= 0xF0;        //设置定时器模式
        TMOD |= 0x01;        //设置定时器模式 (方式1)
        TL0 = 0x00;        //设置定时初值
        TH0 = 0x00;        //设置定时初值
        TF0 = 0;        //清除TF0标志
        ET0 = 1;        //开启定时器0中断
        EA=1;           //全局中断使能
    }
    

    步骤 2:修正 Measure() 函数

    以下是优化后的 Measure() 函数,避免卡死并正确测量距离:

    void Measure()
    {
        unsigned int Timeout = 0;
    
        // 发送超声波脉冲
        trig = 1;
        Delay15us();
        trig = 0;
    
        // 等待 echo 变为高电平(即收到回波)
        while (!echo && Timeout++ < 50000);
        if (Timeout >= 50000) return;
    
        // 启动定时器0
        TR0 = 1;
    
        // 等待 echo 变为低电平(即回波结束)
        Timeout = 0;
        while (echo && Timeout++ < 50000);
        TR0 = 0;
    
        if (Timeout >= 50000) return;
    
        // 计算时间
        Time = (256 * TH0 + TL0) * 120000 / 110592; // 计算时间(单位:微秒)
        Distance = Time * 0.17;                   // 距离(单位:毫米)
    
        // 打印数据
        SendData[0] = Distance / 1000 + '0';
        SendData[1] = (Distance % 1000) / 100 + '0';
        SendData[2] = (Distance % 100) / 10 + '0';
        SendData[3] = '.';
        SendData[4] = Distance % 10 + '0';
        SendData[5] = 'c';
        SendData[6] = 'm';
        TxStr(SendData);
        TxStr("\r\n");
    
        // 重置定时器
        TH0 = TL0 = 0;
    }
    

    步骤 3:添加定时器中断服务函数

    因为使用了定时器 0,需要添加中断服务函数来处理计时。

    void Timer0Isr() interrupt 1
    {
        // 不需要在此处做任何操作,因为我们只在 Measure() 中启动和关闭定时器
    }
    

    步骤 4:主函数中调用 Measure() 前先初始化

    void main()
    {
        Timer0Init();       // 初始化定时器
        UartInit();         // 初始化串口
    
        // 设置电机方向
        ENB = 1;
        IN4 = 1;
        IN3 = 0;
    
        ENA = 1;
        IN2 = 0;
        IN1 = 1;
    
        while (1)
        {
            Measure();  // 测量距离
    
            if (Distance <= 10)  // 如果距离小于等于10mm
            {
                // 停止并转向
                P2_7 = ~P2_7;
                IN4 = 0;
                IN3 = 1;
            }
            else
            {
                // 正常前进
                P2_5 = 1;
                IN4 = 1;
                IN3 = 0;
            }
    
            Delay10ms(100);  // 延迟100ms,防止频繁测量
        }
    }
    

    🛠️ 总结

    | 问题 | 解决方案 | |------|----------| | while(echo); 卡死 | 使用超时机制,并通过 TR0 控制定时器 | | 定时器未启用 | 在 Timer0Init() 中添加 ET0 = 1;EA = 1; | | 未使用定时器中断 | 添加 Timer0Isr() 函数 | | 测量不准确 | 修正 Measure() 函数,加入超时判断 |


    📌 建议

    • 在调试时,可以通过串口输出 Distance 值,观察是否正常。
    • 如果 Distance 始终为 0 或非常大,可能是 echo 引脚没有响应,需检查硬件连接或使用示波器检测信号。

    如果你还有其他问题,欢迎继续提问!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 10月7日
  • 已采纳回答 9月29日
  • 创建了问题 9月29日