Featured image of post JSN SR04T超声波测距

JSN SR04T超声波测距

JSN-SR04T超声波测距

JSN-SR04T-V3.3 Datasheet - Original.pdf

数据手册(模式0)

  • 参数

image-20260328010000613

  • 功能

image-20260328010118704

  • 模式

image-20260328020412880

jsn-sr04t.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "jsn-sr04t.h"


// ==============================================
// 函数功能:超声波初始化
// ==============================================
void JSN_SR04T_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    // 使能 GPIO 和定时器时钟
    RCC_APB2PeriphClockCmd(TRIG_RCC | ECHO_RCC, ENABLE);
    RCC_APB1PeriphClockCmd(TIM_RCC, ENABLE);

    // TRIG 引脚:推挽输出
    GPIO_InitStructure.GPIO_Pin = TRIG_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(TRIG_PORT, &GPIO_InitStructure);
    GPIO_ResetBits(TRIG_PORT, TRIG_PIN);

    // ECHO 引脚:浮空输入
    GPIO_InitStructure.GPIO_Pin = ECHO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(ECHO_PORT, &GPIO_InitStructure);

    // TIM2 配置:1us 计数一次
    TIM_TimeBaseStructure.TIM_Period = 65535;
    TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
}

// ==============================================
// 函数功能:获取距离
// 计算公式:cm = 时间(us) / 57.5
// 返回值:距离(单位:cm)
// ==============================================
float JSN_SR04T_GetDistance(void)
{
    uint32_t time = 0;
    uint32_t timeout = 0;  // 超时计数器
    float distance = 0;

    // 发送 12us 触发信号
    GPIO_SetBits(TRIG_PORT, TRIG_PIN);
    Delay_us(12);
    GPIO_ResetBits(TRIG_PORT, TRIG_PIN);
		
	//等待ECH0为高电平,如果从发送高电平后,40ms后就出错退出
	  timeout = 0;
    while(GPIO_ReadInputDataBit(ECHO_PORT, ECHO_PIN) == 0)
    {
        timeout++;
        Delay_us(1);
        if(timeout > 40000)  // 40ms 超时
        return -1;
    }

		//开始计时
		TIM_SetCounter(TIM2, 0);
    TIM_Cmd(TIM2, ENABLE);

		//等待ECHO低电平,超时40ms
		timeout = 0;
    while(GPIO_ReadInputDataBit(ECHO_PORT, ECHO_PIN) == 1)
    {
        timeout++;
        Delay_us(1);
        if(timeout > 40000)  // 40ms 超时
        return -1;
    }


    time = TIM_GetCounter(TIM2);
    TIM_Cmd(TIM2, DISABLE);

    // 距离换算:cm = 时间(us) / 57.5
    distance = (float)time / 57.5;

    // 有效范围判断
    if(distance > 400)
    return -1;

    return distance;
}

// ==============================================
// 函数功能:获取实际水深
// 计算公式:水深 = 安装总高度 - 测得距离
// 返回值:距离(单位:cm)
// ==============================================
float Get_Water_Depth(float date)
{
	return FIXED_DISTANCE - date;
}

jsn-sr04t.h

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#ifndef __JSN-SR04T_H
#define __JSN-SR04T_H

#include "stm32f10x.h"
#include "delay.h"

// 宏定义固定距离
#define FIXED_DISTANCE    200.0f

// 引脚配置
#define TRIG_PIN    GPIO_Pin_3
#define TRIG_PORT   GPIOA
#define ECHO_PIN    GPIO_Pin_2
#define ECHO_PORT   GPIOA

// 时钟使能
#define TRIG_RCC    RCC_APB2Periph_GPIOA
#define ECHO_RCC    RCC_APB2Periph_GPIOA
#define TIM_RCC     RCC_APB1Periph_TIM2

// 函数声明
void JSN_SR04T_Init(void);
float JSN_SR04T_GetDistance(void);
float Get_Water_Depth(float date);

#endif

数据手册(模式1)

image-20260329003249104

jsn-sr04t.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include "stm32f10x.h"

// 全局数据
static uint8_t JSN_Buf[4];       // 接收缓冲区
static uint8_t JSN_Cnt = 0;      // 接收计数
static uint16_t JSN_Distance = 0;// 最终距离
static uint8_t JSN_DataValid = 0; // 数据有效标志


// 串口初始化:9600 8N1
void UART1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 配置 PA9 (TX) 为复用推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置 PA10 (RX) 为浮空输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置串口参数:9600 8N1
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);


    // 配置 NVIC
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    // 开启接收中断
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    USART_Cmd(USART1, ENABLE);
}

/*************************************************
中断服务函数:接收数据
*************************************************/
void USART1_IRQHandler(void)
{
    uint8_t ch;

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        ch = USART_ReceiveData(USART1);

        // 帧头 0xFF
        if(JSN_Cnt == 0 && ch == 0xFF)
        {
            JSN_Buf[0] = ch;
            JSN_Cnt = 1;
        }
        // 接收剩余字节
        else if(JSN_Cnt > 0 && JSN_Cnt < 4)
        {
            JSN_Buf[JSN_Cnt++] = ch;

            // 校验
            if(JSN_Cnt == 4)
            {
                uint8_t sum = (JSN_Buf[0] + JSN_Buf[1] + JSN_Buf[2]) & 0xFF;
                if(sum == JSN_Buf[3])
                {
                    JSN_Distance = (JSN_Buf[1] << 8) | JSN_Buf[2];
                    JSN_DataValid = 1; // 数据有效
                }
                JSN_Cnt = 0; // 重置
            }
        }
        else
        {
            JSN_Cnt = 0;
        }
    }
}

/*************************************************
函数名称:JSN_SR04T_GetDistance
功能:获取最新距离 mm
返回值:成功返回最新距离	失败返回0
*************************************************/
u16 JSN_SR04T_GetDistance(void)
{
    if(JSN_DataValid)
    {
        return JSN_Distance;
    }
    return 0;
}

/*************************************************
函数名称:JSN_SR04T_GetWaterLevel
功能:计算真实水位
返回:真实水位高度 mm	无效数据 返回0
*************************************************/
u16 JSN_SR04T_GetWaterLevel(void)
{
    u16 dist = JSN_SR04T_GetDistance();

    if(dist == 0 || dist > INSTALL_HEIGHT)
    {
        return 0;   
    }

    return (INSTALL_HEIGHT - dist);
}

jsn-sr04t.h

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#ifndef __JSN_SR04T_H
#define __JSN_SR04T_H

#include "stm32f10x.h"

#define INSTALL_HEIGHT  2000  // 单位:mm,传感器安装高度(例如2米=2000mm)
// 初始化(串口1 中断接收)
void JSN_SR04T_Init(void);

// 获取最新距离(单位:mm)
u16 JSN_SR04T_GetDistance(void);

#endif
最后更新于 2026-03-29 00:51
...