超声波测距装置课程设计报告

目 录

第一章 绪论 .................................................................................2

1.1设计目的及要求 .................................................................. 2

1.2 设计任务 ........................................................................... 2

1.3 项目实施计划........................................................................5

第二章 原理图绘制 .....................................................................8

2.1 系统结构和接口设计 ............................................. .............3

2.2 各电路的原理图设计和原理分析 ........................ ......... ...... 8

第三章 整体模块设计.....................................................................18

3.1 系统框图 .................................................... ................. ....18

3.2 各模块源代码设计和分析 ...................................................20

3.3 设计步骤........................................................................ 28

3.3 模块仿真结果和分析 .........................................................32

第四章 总 结.................................................................................38

一、 绪论

1.1 设计目的及要求

目的:

1、 掌握电子线路板设计方法;

2、 掌握嵌入式SF32LB52用于智能电子系统的设计技术和方法;

3、 掌握GPIO\I2C控制应用方法;

4、 学习掌握智能嵌入式微处理器集成开发环境SiFli-SDK的使用方法。

要求:

1、 设计超声波发射接收模块,要求

a) 控制超时波发射频率,每秒1次

b) MCU计算距离,通过超声波发射接收时间间隔计算实际距离

c) 计算公式 distance = time * 343m/s / 2

2、 设计4位数码管显示

a) 使用I2C通信写入数据

b) 控制4位数码管显示

1.2 设计任务

使用思澈科技SF32LB52-Devkit-LCD开发板,驱动TM1650 I2C接口控制的数码管,和HC-SR04超声波模块完成。其中SF32LB52-Devkit-LCD开发板 作为主控MCU控制HC-SR04超声波模块发射超声波,并读取Echo引脚记录超声波从发射到接收的时间间隔,根据公司 Distance = 343m/s * time / 2 得到距离值,然后通过MCU I2C外设将数据发送到TM1650 四位共阴极数码管中进行显示。最终完成超声波测距装置的实现。

1.3项目实施计划

1、 实现MCU I2C 驱动配置

2、 完成 I2C 通信写入TM1650 驱动点亮4位数码管

3、 实现超声波模块驱动配置

4、 计算超时波测量距离并写入数码管

二、 原理图绘制

2.1 系统结构和接口设计

系统结构:

接口设计:

2.2 各电路的原理图设计和原理分析

SF32LB52:

超声波:

数码管:

三、 整体模块设计

3.1 系统框图

3.2 各模块源代码设计和分析

 C-SR04 模块源代码设计/分析

 源代码

c 复制代码
#include "rtthread.h"
#include "bf0_hal.h"
#include "drv_io.h"
#include "stdio.h"
#include "string.h"
#include "board.h"
#include "drv_gpio.h"
#include "ulog.h"

#define DBG_TAG "HC-SR04"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#define HC_SR04_TRIG GET_PIN(1,39)
#define HC_SR04_ECHO GET_PIN(1,40)


#define SET_TRIG(x) rt_pin_write(HC_SR04_TRIG, x)
#define SET_ECHO(x) rt_pin_write(HC_SR04_ECHO, x)


#define READ_ECHO rt_pin_read(HC_SR04_ECHO)


GPT_HandleTypeDef TIM_Handle = {0};
int GPTIM1_CORE = 0;
void HC_SR04_init(void)
{
    /* Initialize GPIO pins */
    rt_pin_mode(HC_SR04_TRIG, PIN_MODE_OUTPUT);
    rt_pin_mode(HC_SR04_ECHO, PIN_MODE_INPUT);
    
    /* Set initial state */
    rt_pin_write(HC_SR04_TRIG, PIN_LOW);
    rt_pin_write(HC_SR04_ECHO, PIN_HIGH);


        
    TIM_Handle.Instance = GPTIM1;                                               // Use GPTIM1
    TIM_Handle.Init.Prescaler = 12000 - 1; // Set prescaler
    TIM_Handle.core =  HAL_RCC_GetPCLKFreq(GPTIM1_CORE, 1);          // HAL_RCC_GetPCLKFreq(GPTIM1_CORE, 1)                                   // Clock source is from GPTIM1_CORE
    TIM_Handle.Init.CounterMode = GPT_COUNTERMODE_UP;                         // Count up
    TIM_Handle.Init.Period = 60000 - 1;                                     // Max period                                     
    HAL_GPT_Base_Init(&TIM_Handle);                                             // Initialize Timer
         
    HAL_GPT_Base_Stop(&TIM_Handle);                                                 // Stop Timer
    GPTIM1->CNT = 0;
    LOG_D("Initialized for HC-SR04 communication.");
}


void HC_SR04_Trigger(void)
{
    SET_TRIG(1);
    rt_thread_mdelay(0.015); // 15 microseconds
    SET_TRIG(0);
    LOG_D("HC-SR04 Triggered.");
}

uint8_t LAST_CNT = 0;
uint8_t NOW_CNT = 0;
float HC_SR04_Measure(void)
{
    uint32_t start_time, end_time, duration;
    
    HC_SR04_Trigger();

    // Wait for ECHO to go high
    while(!READ_ECHO);
    HAL_GPT_Base_Start(&TIM_Handle); // Start timer
    // Wait for ECHO to go low
    while(READ_ECHO);
    HAL_GPT_Base_Stop(&TIM_Handle); // Ensure timer is stopped
    LOG_I("%d",GPTIM1->CNT);
    LAST_CNT = GPTIM1->CNT;
    NOW_CNT = 0.7 * LAST_CNT + 0.3 * GPTIM1->CNT;
    float distance = NOW_CNT * 1.7;  // Distance in cm
    GPTIM1->CNT = 0; // Reset counter for next measurement
    LOG_I("Measured Distance: %.2f cm", distance);
    return distance;
}

 分析

这一段属于超声波模块C-SR04驱动代码,包括模块ECHO、TRIG相关IO口配置和,计数用定时器GPTIM配置,以及一个距离计算处理函数。

其中:

HC_SR04_init()

此函数为初始化函数,初始化了两个控制IO口,ECHO -- PAD_PA40 配置为输入模式 并初始设高电平,TRIG -- PAD_PA39 配置为输出模式 并初始设置低电平。同时初始化配置GPTIM定时器用于计数,记录时间。这里配置定时器时钟为HAL_RCC_GetPCLKFreq(GPTIM1_Core,1),这里时钟即为120Mhz,配置定时器预分频器为12000-1,将时钟预先分频为100000,配置计数模式为向上计数,同时计数周期为60000 -- 1,其余配置默认即可,此处定时器仅用到其中计数的功能,随后读取其CNT寄存器中的值即可计算出时间,初始化关闭定时器,并设CNT寄存器为0。

HC_SR04_Trigger()

此函数为超声波模块TRIG引脚控制函数。根据数据手册:

需要给TRIG引脚至少10us的高电平信号以触发超声波发射。因此使用SET_TRIG(1) 拉高引脚,并延时15us,然后拉低引脚SET_TRIG(0),即发送了10us以上高电平信号,超声波模块会自动发出超声波信号。

HC-SR04_Measure()

这是距离测量计算函数,先触发TRIG引脚使模块发射出超声波信号。根据数据手册可知,超声波信号发出时,模块自动拉高ECHO引脚,当超声波模块返回并被接收时,模块自动拉低引脚,计算其中高电平时间即可计算出时间并由此计算出距离。并更加GPTIM定时器配置可知,当超声波信号发出时,打开定时器,定时器开始CNT计算;当检测到超声波信号返回时,关闭定时器计算,此时读取CNT的值x。PCLK时钟为120000000 ,预分频为12000,因此计数器每秒计数100000个。由此

Distance = CNT * 340 * 1.0 * 100 / 100000 / 2 cm (单位转换为cm)

函数最终返回 两位浮点型小数。

 TM1650 4位数码管驱动显示代码/分析

 代码

c 复制代码
#define TM1650_SCL GET_PIN(1,41)
#define TM1650_SDA GET_PIN(1,42)


#define SET_SCL(x) rt_pin_write(TM1650_SCL, x)
#define SET_SDA(x) rt_pin_write(TM1650_SDA, x)


#define READ_SDA rt_pin_read(TM1650_SDA)

void I2C_Start(void)
{
    SET_SDA(1);
    SET_SCL(1);
    rt_thread_mdelay(1);
    SET_SDA(0);
    rt_thread_mdelay(1);
    SET_SCL(0);
    LOG_I("I2C Start Condition");
}

void I2C_ACK(void)
{
    uint8_t timeout = 0;
    SET_SCL(1);
    rt_thread_mdelay(1);
    SET_SCL(0);
    //rt_pin_mode(TM1650_SDA, PIN_MODE_INPUT);
    while(READ_SDA&&timeout<=100)
    {
        timeout++;
        LOG_I("I2C ACK Waiting...");
    }
    //rt_pin_mode(TM1650_SDA, PIN_MODE_OUTPUT);
    rt_thread_mdelay(1);
    SET_SCL(0);
    LOG_I("I2C ACK Received");
}

void I2C_Stop(void)
{
    SET_SDA(0);
    SET_SCL(1);
    rt_thread_mdelay(1);
    SET_SDA(1);
    rt_thread_mdelay(1);
    LOG_I("I2C Stop Condition");
}


void I2C_Send_Byte(uint8_t byte)
{
    SET_SCL(0);
    rt_thread_mdelay(1);

    for(int i=0;i<8;i++)
    {
        if(byte&0x80)
            SET_SDA(1);
        else
            SET_SDA(0);
        rt_thread_mdelay(1);
        byte <<= 1;
        SET_SCL(1);
        rt_thread_mdelay(1);
        SET_SCL(0);
        rt_thread_mdelay(1);
    }
    LOG_I("I2C Sent Byte: 0x%02X", byte);
}

void TM1650_GPIO_init(void)
{
    /* Initialize GPIO pins */
    rt_pin_mode(TM1650_SCL, PIN_MODE_OUTPUT);
    rt_pin_mode(TM1650_SDA, PIN_MODE_OUTPUT);
    
    /* Set initial state */
    rt_pin_write(TM1650_SCL, PIN_LOW);//
    rt_pin_write(TM1650_SDA, PIN_HIGH);//

    LOG_D("GPIO initialized for TM1650 I2C communication.");
}

void TM1650_Brightness_Set(uint8_t data)
{
    I2C_Start();
    I2C_Send_Byte(0x48);
    I2C_ACK();
    I2C_Send_Byte(data);
    I2C_ACK();
    I2C_Stop();
    LOG_D("TM1650 Displayed data 0x%02X at address 0x%02X", data, 0x24);
}


void TM1650_Display(uint8_t DIG, uint8_t data)
{
    I2C_Start();
    I2C_Send_Byte(0x68 + DIG);
    I2C_ACK();
    I2C_Send_Byte(data);
    I2C_ACK();
    I2C_Stop();
    LOG_D("TM1650 Displayed data 0x%02X at address 0x%02X", data, 0x34 + DIG);
}


uint8_t DATA_NUM[10]=
{
    0x3F, //0
    0x06, //1
    0x5B, //2
    0x4F, //3
    0x66, //4
    0x6D, //5
    0x7D, //6
    0x07, //7
    0x7F, //8
    0x6F  //9
};

#define TM1650_DOT 0x80

//15.45   
void TM1650_display_float(float num)
{
    int int_part = (int)num; //15
    int frac_part = (int)((num - int_part) * 100); // 45

    TM1650_Display(0, DATA_NUM[int_part / 10]);
    TM1650_Display(2, DATA_NUM[int_part % 10] | TM1650_DOT);
    TM1650_Display(4, DATA_NUM[frac_part / 10]);
    TM1650_Display(6, DATA_NUM[frac_part % 10]);
}

 分析

(数据波形图)

SF32LB52支持硬件I2C、软件I2C。这里选择写出软件I2C,以直观的显示出时序波形控制。

TM1650_GPIO_init()

模拟I2C的引脚配置,配置PAD_PA41为SCL引脚,配置PAD_PA42为SDA引脚。

I2C_Start()

复制代码
这是I2C起始信号函数。根据数据手册中的波形控制图可知,I2C起始信号需要先将SDA:SET_SDA(1);

,SCL:SET_SCL(1);拉高,在SCL为高电平期间,拉低SDA:SET_SDA(0);认为是开始信号。

I2C_Stop()

复制代码
这是I2C停止信号函数。根据数据手册中的波形控制图可知,I2C停止信号需要SDA:SET_SDA(0);

为低电平,SCL:SET_SCL(1);为高电平,在SCL为高电平期间,拉高SDA:SET_SDA(1);认为是停止信号。

I2C_ACK()

复制代码
等待接收ACK信号函数。当一次数据发送完成后从机会返回一个ACK应答信号。对于主机来说,当SDA为低电平时,SCL由低电平转为高电平后,从机释放SDA为输入。

I2C_Send_Byte()

复制代码
写入8bit数据函数。写入8bit 函数实际为循环写入8次1bit数据。在发出start信号后,每来一次SCL高电平信号时,视为写入此时SDA电平数据,当SET_SDA(1);视为写入1,当SET_SDA(0);视为写入0。循环8次后为写入1byte数据。

TM1650_Brightness_Set()

复制代码
根据数据手册可知,写入地址0x48为控制命令设置,写入0x48指令后紧跟的数据为控制亮度段数,开关控制数据。

TM1650_Display()

根据数据手册,写入地址0x68为显示数据存储地址,对应第一个数码管显示,0x6A对应第二个数码管的显存地址,输入地址数据后紧接一个8位数据,即可点亮对应数码管显示。

DATA_NUM/TM1650_DOT

数码管显示0~9的数据显示/数码管显示小数点。

TM1650_display_float()

4位数码管显示2位小数浮点型数据,用来显示测量的距离。输入浮点型参数,处理后显示在4位数码管上。

 超声波测距代码

 代码

c 复制代码
/**
  * @brief  Main program
  * @param  None
  * @retval 0 if success, otherwise failure number
  */
int main(void)
{
    HC_SR04_init();
    TM1650_GPIO_init();
    TM1650_Brightness_Set(0x01); // Set brightness to maximum
    while (1)
    {
        TM1650_display_float(HC_SR04_Measure());
        rt_thread_mdelay(1000);
    }

    return RT_EOK;
}

 分析

Main 函数

超声波测距主函数,先初始化HC-SR04超声波模块和TM1650 4位数码管模块。初始化完成设置数码管亮度等级为8级,显示段数为8段,并开启显示,只有这样数码管才能显示。在while循环中反复执行HC_SR04_Measure 超声波测距代码,并用TM1650_display_float函数显示在数码管上。

3.3 设计步骤

    1. 4位数码管显示驱动
    1. HC-SR04 超声波驱动
    1. 距离计算
    1. 数据显示
    1. 结果分析
      3.4 模块仿真结果和分析

    结果分析:分析显示和测量结果,测量数据显示接近实际距离。

四、 总结

本次课程设计项目:超声波测距模块。使用主控MCU为SFLB52系列开发板。与以为直接使用共阴极数码管显示模块显示,这里使用了由TM1650芯片控制的数码管模块,两者之间的差别是,以往数码管模块需要多条数据线控制,本模块使用I2C主线来控制显示数据。配合超声波模块,由MCU计算距离,完成整体模块设计。其中原定使用SF32LB52硬件I2C驱动模块该数码管显示模块,但是硬件I2C驱动无法完整显示出TM1650 4位数码管I2C的时序控制,因此后续改为模拟I2C,使用软件模拟I2C的形式,更加直观的展示出数据手册中的数据传输时序。最终超声波测距装置完成,以超声波模块、主控MCU、数码管显示模块三部分组成。

相关推荐
richxu202510012 小时前
嵌入式学习之路->stm32篇-->(8)I2C通讯(上)
stm32·嵌入式硬件·学习
国科安芯3 小时前
微小卫星红外相机双MCU冗余架构的抗辐照可靠性评估
人工智能·单片机·嵌入式硬件·数码相机·架构·自动化·安全性测试
电子阿板3 小时前
STM32G0B1 NRST复位和其它IO复用了,如何设置成专用复位引脚,
stm32·单片机·嵌入式硬件
兆龙电子单片机设计3 小时前
【STM32项目开源】STM32单片机智慧农业大棚控制系统
stm32·单片机·物联网·开源·毕业设计
不脱发的程序猿3 小时前
使用Python高效对比多个相似的CAN DBC数据
python·单片机·嵌入式硬件·嵌入式
bai5459363 小时前
STM32 CubeIDE 串口通信
stm32·单片机·嵌入式硬件
国科安芯3 小时前
强辐射环境无人机视频系统MCU可靠性分析
人工智能·单片机·嵌入式硬件·音视频·无人机·边缘计算·安全性测试
WaWaJie_Ngen4 小时前
C++实现一笔画游戏
c++·算法·游戏·游戏程序·课程设计
代码游侠4 小时前
应用——基于 51 单片机的多功能嵌入式系统
笔记·单片机·嵌入式硬件·学习·51单片机