森侃 2024-03-10 22:57 采纳率: 60%
浏览 9
已结题

蓝桥杯单片机超声波测距

在显示超声波是,我是想1s测一次,使用定时器0定时,结果一直没办法测距,显示一直是0,中断是进去了的,因为这个不行,所以我改为了延时1s,延时中也使用了显示函数,但最后也为0,想问一下这是为什么,如果一直让测距的话,数据都重合了,感觉不太能看清。
想问一下有人可以解决吗?


void Display()
{
    SelectHC573(7);
    SelectHC573(0);
    SMG_Bit(SMG[d%10],7);
    SMG_Delay(300);
    SMG_Bit(SMG[(d/10)%10],6);
    SMG_Delay(300);
    SMG_Bit(SMG[(d/100)%10],5);
    SMG_Delay(300);
    SMG_Bit(SMG[(d/1000)%10],4);
    SMG_Delay(300);
    SMG_Bit(SMG[d/10000],3);
    SMG_Delay(300);
    SMG_Bit(0xff,8);
    SMG_Delay(300);
}
void Delay1000ms(void)    //@12.000MHz
{
    unsigned char data i, j, k;

    _nop_();
    _nop_();
    i = 46;
    j = 153;
    k = 245;
    do
    {
        do
        {
            while (--k) Display();
        } while (--j) ;
    } while (--i) ;
}
int main()
{
    Close();
    while(1)
    {
        d=distance();//每一秒测一次,超声波,不属于NE555,需要定时1s
        Display();
        Delay1000ms();
    }
}

超声波模块


#include "sonic.h"
void delay12()
{
    unsigned int i = 33;
    _nop_();
    _nop_();
    while(--i);
}

void send_wave()
{
  unsigned char i ;
  for(i = 0;i < 8;i ++)
  {
    TX = 1;
    delay12();
    TX = 0;
    delay12();
  }
}

unsigned char distance()
{
    unsigned int time = 0;
    TMOD &= 0x0f;
    TL1 = 0x00;
    TH1 = 0x00;
    send_wave();
    TR1 = 1;
    while((RX == 1)&&(TF1 == 0));
    TR1 = 0;
    if (TF1 == 0)
    {
        time = TH1;
        time <<= 8;
        time = time | TL1;

        return (time*0.017);  //单位cm
    }
    else 
    {
        TF1 = 0;
        return 9999;
    }

}
  • 写回答

5条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-03-10 22:57
    关注

    引自免费微信小程序:皆我百晓生

    在您的问题中,您提到使用单片机进行超声波测距,并且在1秒内进行一次测量。根据提供的代码片段,看起来有以下几个可能的问题:

    1. 中断配置与定时器问题:尽管您提到了定时器0,但distance()函数中实际配置并使用的似乎是定时器1(TR1和TF1)。请确保定时器正确配置为1秒钟触发一次中断,以便在每秒开始时发送超声波脉冲。

      // 假设单片机晶振频率为12MHz
      #define SYS_CLK 12000000UL
      #define TIMER1_PRESCALER 12 // 选择合适的分频系数使定时器周期接近1s
      
      void init_timer1_for_1s() {
          TMOD &= 0x0f; // 清除高四位以配置定时器模式
          TMOD |= 0x10; // 设置定时器1为16位模式
          TH1 = (SYS_CLK / TIMER1_PRESCALER) / 1000 - 1; // 计算TH1初值以得到1s中断
          TL1 = TH1;
          EA = 1; // 打开总中断
          ET1 = 1; // 打开定时器1中断
          TR1 = 1; // 启动定时器1
      }
      
      void timer1_isr(void) interrupt 3 { // 根据单片机型号调整中断号
          TR1 = 0; // 关闭定时器1
          TH1 = ...; // 重新加载初始值
          TL1 = TH1;
          d = distance(); // 在中断服务程序中调用测距函数
          Display();
          TR1 = 1; // 重新启动定时器1
      }
      
    2. 延时函数的精度与显示更新:在Delay1000ms()函数中同时进行延时和显示可能会导致延时不准确以及显示刷新问题。您可以考虑在延时期间禁用显示刷新,然后在延时结束后一次性完成显示。

    3. 超声波模块驱动问题:检查send_wave()函数是否正常工作,确保发射端TX能正确发出8个40kHz的方波脉冲。如果发射信号有问题,接收端自然无法接收到回波信号。

    4. 接收端处理:确认在接收回波时的等待逻辑无误。while((RX == 1)&&(TF1 == 0));这一句可能需要修改为等待特定时间窗口内的下降沿或其他有效标志,确保能在接收到回波后正确停止定时器。

    5. 显示函数优化:由于您希望在每次测距完成后显示新的距离值,可以将显示操作放在distance()函数成功获取到数据之后立即进行,避免因延时函数内部多次调用显示函数造成混乱。

    总之,请按照上述建议检查并修正相关代码部分,确保定时器、中断服务程序、超声波发射及接收处理均正确无误。这样应该能够实现每秒测量一次距离,并清晰地显示在数码管上。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月15日
  • 创建了问题 3月10日

悬赏问题

  • ¥15 求高通平台Softsim调试经验
  • ¥15 canal如何实现将mysql多张表(月表)采集入库到目标表中(一张表)?
  • ¥15 wpf ScrollViewer实现冻结左侧宽度w范围内的视图
  • ¥15 栅极驱动低侧烧毁MOSFET
  • ¥30 写segy数据时出错3
  • ¥100 linux下qt运行QCefView demo报错
  • ¥50 F1C100S下的红外解码IR_RX驱动问题
  • ¥20 基于matlab的航迹融合 航迹关联 航迹插补
  • ¥15 用Matlab实现图中的光线追迹
  • ¥15 联想笔记本开机出现系统更新界面