You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于ATMEGA32A与HC-SR04的超声波测距读数异常求助

AVR单片机HC-SR04测距程序异常问题排查

问题概述

开发基于ATMEGA32A芯片的测距程序,搭配16x2 LCD与HC-SR04超声波传感器,遇到两类问题:

  • 初始问题:测距读数异常,物体极近时显示距离偏大,较远时显示偏小,无法获取准确值
  • 更新问题:修改代码后,距离数值大于9时,LCD显示十六进制值(例如数值10显示为1e)

硬件配置

  • 主控芯片:ATMEGA32A
  • 显示模块:16x2 LCD
  • 测距传感器:HC-SR04超声波传感器

相关代码

主程序代码

#include <avr/io.h>
#include <avr/interrupt.h>
#include <MrLcd/MrLCDmega32.h>
#define F_CPU 1000000
#include <util/delay.h>
#include <stdlib.h>
#define  Trigger_pin    PD0 /* Trigger pin */


static volatile int pulse = 0;
static volatile int i = 0;

int main(void)
{
    
    Initialise();
    DDRD = 0b11111011;
    _delay_ms(50);

    GICR |= 1<<INT0;
    MCUCR |= 1<<ISC00;
    
    int16_t count_a = 0;
    char show_a[16];

    sei();
    
    while(1)
    {
        PORTD |= (1<<Trigger_pin);
        _delay_us(10);

        PORTD &= ~(1<<Trigger_pin);
        count_a = pulse/58;

        Send_A_String("Distance Sensor");
        GoToMrLCDLocation(1,2);
        Send_A_String("Distance=");
        itoa(count_a,show_a,10);
        Send_A_String(show_a);
        Send_A_String(" ");
        GoToMrLCDLocation(13,2);
        Send_A_String("cm");
        GoToMrLCDLocation(1,1);
    }
}

ISR(INT0_vect)
{
    if(i == 1)
    {
        TCCR1B = 0;
        pulse = TCNT1;
        TCNT1 = 0;
        i = 0;
    }

    if(i==0)
    {
        TCCR1B |= 1<<CS10;
        i = 1;
    }
}

Initialise初始化函数代码

void Initialise(void)
{        
    DataDir_MrLCDsControl|=1<<LightSwitch|1<<ReadWrite|1<<BipolarMood;  //配置LCD控制引脚方向
        
    _delay_ms(15);                              //等待LCD启动
    
    Send_A_Command(0x01);   //清屏
    _delay_ms(2);
    Send_A_Command(0x38);   //设置LCD为8位数据、2行显示模式
    _delay_us(50);
    Send_A_Command(0b00001110); //开启显示、显示光标、光标不闪烁
    _delay_us(50);
}

已尝试操作

修改触发引脚定义,问题未解决


问题分析与解决建议

1. 测距读数不准问题

  • 定时器配置缺失:当前仅开启定时器1的CS10分频(无分频),但未初始化定时器模式。需在main函数初始化阶段添加TCCR1A = 0;,确保定时器处于普通计数模式,避免波形生成配置干扰计时。
  • 中断触发逻辑优化:当前MCUCR设置为任意电平变化触发INT0,易出现误触发。建议改为上升沿启动计时、下降沿停止计时,动态切换中断触发方式:
    ISR(INT0_vect)
    {
        if(i == 0)
        {
            TCNT1 = 0;
            TCCR1B |= (1<<CS10); //无分频启动定时器
            //切换为下降沿触发
            MCUCR &= ~(1<<ISC00);
            MCUCR |= (1<<ISC01);
            i = 1;
        }
        else
        {
            TCCR1B = 0; //停止定时器
            pulse = TCNT1;
            //切换回上升沿触发
            MCUCR &= ~(1<<ISC01);
            MCUCR |= (1<<ISC00);
            i = 0;
        }
    }
    
  • 计时精度验证:F_CPU为1MHz时,定时器1每计数1次对应1us,距离(cm) = pulse / 58的公式正确,但需确保pulse变量未被其他逻辑篡改。

2. LCD显示十六进制值问题

  • 字符串缓冲区清理:show_a数组未手动添加结束符,残留旧数据可能导致显示异常,转换后需补充:
    itoa(count_a,show_a,10);
    show_a[3] = '\0'; //最大距离不超过400cm,最多3位数字,手动截断避免溢出
    
  • LCD字符发送函数检查:确认Send_A_String是否正确发送ASCII字符,而非将字符值当作十六进制指令发送。可单独测试发送固定字符串(如"10"),验证LCD是否正常显示十进制数字。

内容的提问来源于stack exchange,提问作者Anonymous Stress

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 14:50:19