找回密码
 立即注册
查看: 111|回复: 1

重新写了一个超声波测距程序,测量距离4米以内,验证成功

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:11
  • 最近打卡:2026-04-10 01:15:45
已绑定手机

12

主题

8

回帖

98

积分

注册会员

积分
98
发表于 2026-4-10 15:22:19 | 显示全部楼层 |阅读模式
超声波测距,喜欢的朋友留言,下面是验证照片,用尺子测了很精准


描述:STC32G12K128 + HC-SR04超声波测距 + I2C LCD1602显示程序
* 晶振:24MHz


#include "STC32G.h"     // STC32G系列单片机头文件
#include "intrins.h"    // 包含_nop_()等函数
#include <stdio.h>      // 标准输入输出库
#include <string.h>     // 字符串处理库


/*============================================================================
* 类型定义
*============================================================================*/
typedef unsigned char  u8;       // 8位无符号整数
typedef unsigned int   u16;      // 16位无符号整数
typedef unsigned long  u32;      // 32位无符号整数


/*============================================================================
* 硬件引脚定义
*============================================================================*/
// HC-SR04超声波模块引脚
sbit TRIG = P1^0;       // 触发信号输出引脚
sbit ECHO = P1^1;       // 回波信号输入引脚


// I2C总线引脚(软件模拟I2C)
sbit SCL = P3^2;        // I2C时钟线
sbit SDA = P3^3;        // I2C数据线


/*============================================================================
* LCD1602 I2C地址定义(PCF8574T扩展芯片)
*============================================================================*/
#define LCD1602_I2C_ADDR     0x4E    // PCF8574T的7位地址为0x27,左移1位后写地址=0x4E
#define LCD_RS               0x01    // RS引脚连接到P0
#define LCD_RW               0x02    // RW引脚连接到P1(实际I2C LCD1602通常R/W接地,始终写)
#define LCD_EN               0x04    // EN引脚连接到P2
#define LCD_BACKLIGHT        0x08    // 背光控制引脚连接到P3


/* 注意:以上引脚映射基于常见的PCF8574与LCD1602连接方式:
* P0 - RS(寄存器选择)
* P1 - R/W(读写选择)
* P2 - EN(使能信号)
* P3 - 背光控制
* P4 - D4(数据线4)
* P5 - D5(数据线5)
* P6 - D6(数据线6)
* P7 - D7(数据线7)
*/


/*============================================================================
* 全局变量定义
*============================================================================*/
float  g_distance = 0.0;        // 测量距离(单位:厘米)
u16    g_pulse_width = 0;       // 高电平脉冲宽度(单位:微秒)
u8     g_display_buf[17];       // LCD显示缓冲区(16字符+结束符)
u16    g_timer0_overflow_cnt = 0;   // 定时器0溢出次数


// 测量标志位
bit    g_measure_complete = 0;  // 测量完成标志
bit    g_timeout_flag = 0;      // 超时标志


/*============================================================================
* 函数声明
*============================================================================*/
// 系统初始化函数
void System_Init(void);                     // 系统时钟及IO口初始化
void Timer0_Init(void);                     // 定时器0初始化(用于脉冲宽度测量)


// 延时函数
void Delay_us(u16 us);                      // 微秒级延时
void Delay_ms(u16 ms);                      // 毫秒级延时
void Delay_10us(u16 n);                     // 10微秒级延时


// I2C底层驱动函数
void I2C_Start(void);                       // I2C起始信号
void I2C_Stop(void);                        // I2C停止信号
void I2C_WriteByte(u8 dat);                 // I2C发送一个字节
u8   I2C_ReadByte(u8 ack);                  // I2C读取一个字节
void I2C_Ack(void);                         // I2C应答信号
void I2C_NoAck(void);                       // I2C非应答信号
u8   I2C_WaitAck(void);                     // I2C等待应答


// LCD1602驱动函数
void LCD_WriteCmd(u8 cmd);                  // 写命令到LCD
void LCD_WriteData(u8 dat);                 // 写数据到LCD
void LCD_WriteByte(u8 dat, u8 rs);          // 写入字节(带RS控制)
void LCD_Init(void);                        // LCD初始化
void LCD_SetCursor(u8 row, u8 col);         // 设置光标位置
void LCD_ShowString(u8 row, u8 col, u8 *str); // 显示字符串
void LCD_Clear(void);                       // 清屏


// HC-SR04超声波测距函数
void HC_SR04_Start(void);                   // 启动超声波测距
u16  HC_SR04_Measure(void);                 // 测量并返回脉冲宽度
float HC_SR04_GetDistance(void);            // 获取距离值(厘米)


// 工具函数
void GPIO_Init(void);                       // GPIO端口初始化
void Display_Update(void);                  // 更新LCD显示内容




/******************************************************************************
* 函数名称:main
* 功能描述:主函数
* 输入参数:无
* 输出参数:无
* 返回参数:int(程序返回状态)
******************************************************************************/
void main(void)
{
    // 系统初始化
    System_Init();
   
    // 延时等待外设稳定
    Delay_ms(500);
   
    // LCD1602初始化并显示欢迎信息
    LCD_Init();
    LCD_Clear();
    LCD_ShowString(0, 0, "HC-SR04 Distance");
    LCD_ShowString(1, 0, "System Initial..");
    Delay_ms(2000);
    LCD_Clear();
    LCD_ShowString(0, 0, "Distance:");
    LCD_ShowString(1, 0, "000.0 cm");
   
    // 主循环
    while(1)
    {
        // 获取测量距离
        g_distance = HC_SR04_GetDistance();
        
        // 判断测量是否有效(2cm - 400cm为有效范围)
        if(g_distance >= 2.0 && g_distance <= 400.0)
        {
            // 更新显示内容
            Display_Update();
        }
        else
        {
            // 超出测量范围,显示错误提示
            LCD_ShowString(1, 0, "Out of Range!   ");
        }
        
        // 延时60ms以上,防止发射信号对回响信号的干扰[reference:4]
        Delay_ms(100);
    }
}




/******************************************************************************
* 函数名称:System_Init
* 功能描述:系统时钟及外设初始化
* 输入参数:无
* 输出参数:无
* 返回参数:无
******************************************************************************/
void System_Init(void)
{
    // 系统时钟已在STC-ISP烧录软件中配置为24MHz
    // 此处初始化GPIO和定时器
   
    GPIO_Init();        // GPIO端口初始化
    Timer0_Init();      // 定时器0初始化
    EA = 1;             // 开启总中断
}
....................................................需要完整代码请留言


4.jpg
3.jpg
2.jpg
1.jpg
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:350
  • 最近打卡:2026-05-01 00:39:49
已绑定手机

25

主题

216

回帖

1946

积分

金牌会员

积分
1946
发表于 4 天前 | 显示全部楼层
分享一下代码让大家学习、借鉴一下吧。
学习MCU
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-5-1 10:31 , Processed in 0.131426 second(s), 57 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表