当前位置: 首页 > article >正文

STM32 HAL库 HC - SR04 超声波测距模块驱动实现

一、引言

在现代嵌入式系统开发中,传感器技术起着至关重要的作用。超声波测距模块作为一种常用的距离测量传感器,因其成本低、精度较高、使用方便等优点,被广泛应用于机器人避障、液位检测、工业自动化等领域。HC - SR04 超声波测距模块是一款常见的超声波测距传感器,它可以方便地与微控制器进行连接,实现距离的测量。本文将详细介绍如何基于 STM32F407 的 HAL 库来驱动 HC - SR04 超声波测距模块。

二、HC - SR04 超声波测距模块概述

2.1 工作原理

HC - SR04 超声波测距模块的工作原理基于超声波在空气中的传播速度是已知的(在常温下约为 340m/s),通过测量超声波从发射到接收的时间差,就可以计算出模块与目标物体之间的距离。具体工作过程如下:

  1. 微控制器向 HC - SR04 的 Trig 引脚发送一个至少 10μs 的高电平脉冲,触发模块发射超声波。
  2. HC - SR04 接收到触发信号后,会自动发射 8 个 40kHz 的超声波脉冲,并将 Echo 引脚置为高电平,开始计时。
  3. 当超声波遇到目标物体后反射回来,HC - SR04 接收到反射波,将 Echo 引脚置为低电平,停止计时。
  4. 微控制器通过测量 Echo 引脚高电平的持续时间 t,根据公式d=v×t/2(其中v为超声波在空气中的传播速度,d为模块与目标物体之间的距离)计算出距离。

2.2 引脚说明

HC - SR04 超声波测距模块有 4 个引脚,分别是:

  • VCC:电源正极,一般接 5V。
  • GND:电源负极,接地。
  • Trig:触发引脚,用于接收微控制器的触发信号。
  • Echo:回响引脚,用于输出超声波从发射到接收的时间信号。

2.3 性能参数

  • 工作电压:5V
  • 工作电流:15mA
  • 探测距离:2cm - 400cm
  • 测量精度:±3mm
  • 探测角度:<15°
  • 超声波频率:40kHz

三、STM32F407 简介

3.1 主要特性

  • 高性能:采用 ARM Cortex - M4 内核,最高主频可达 168MHz,具有丰富的外设资源。
  • 低功耗:支持多种低功耗模式,适用于对功耗要求较高的应用场景。
  • 丰富的外设:包含多个串口、SPI、I2C 等通信接口,以及定时器、ADC、DAC 等功能模块。

3.2 HAL 库

HAL(Hardware Abstraction Layer)库是 ST 公司为 STM32 系列微控制器提供的硬件抽象层库,它简化了开发人员对硬件外设的操作,提高了代码的可移植性和开发效率。

四、硬件连接

将 HC - SR04 超声波测距模块与 STM32F407 开发板进行连接,连接方式如下:

HC - SR04 引脚STM32F407 引脚
VCC5V
GNDGND
Trig任意 GPIO 输出引脚(例如 PA0)
Echo任意 GPIO 输入引脚(例如 PA1)

需要注意的是,由于 HC - SR04 的 VCC 为 5V,而 STM32F407 的 GPIO 引脚一般为 3.3V,为了避免损坏 STM32F407 的 GPIO 引脚,需要在 Echo 引脚与 STM32F407 的 GPIO 输入引脚之间添加一个电平转换电路,将 5V 信号转换为 3.3V 信号。可以使用一个简单的分压电路来实现电平转换,例如使用两个电阻R1​和R2​,将R1​连接到 Echo 引脚,R2​接地,R1​和R2​的中间节点连接到 STM32F407 的 GPIO 输入引脚,选择合适的电阻值使得中间节点的电压为 3.3V。

五、开发环境搭建

5.1 安装开发工具

  • Keil MDK:用于编写、编译和调试 STM32 的代码。
  • STM32CubeMX:用于配置 STM32 的外设和生成初始化代码。

5.2 配置 STM32CubeMX

  1. 打开 STM32CubeMX,选择 STM32F407 芯片。
  2. 配置系统时钟,将主频设置为 168MHz。
  3. 配置 GPIO 引脚:
    • 将 Trig 引脚配置为推挽输出模式。
    • 将 Echo 引脚配置为浮空输入模式。
  4. 配置定时器:为了精确测量 Echo 引脚高电平的持续时间,需要使用定时器。选择一个合适的定时器(例如 TIM2),配置定时器的时钟源、预分频器和自动重载值,使得定时器的计数周期为 1μs。
  5. 生成代码,选择 Keil MDK 作为开发工具,点击 “Generate Code” 生成初始化代码。

六、代码实现

6.1 初始化 GPIO 和定时器

在生成的初始化代码中,已经包含了 GPIO 和定时器的初始化函数。以下是一个简单的示例代码,用于初始化 GPIO 和定时器:

#include "stm32f4xx_hal.h"TIM_HandleTypeDef htim2;
GPIO_InitTypeDef GPIO_InitStruct = {0};void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_TIM2_Init();while (1){// 主循环}
}void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** 初始化RCC振荡器 */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;RCC_OscInitStruct.PLL.PLLM = 8;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 7;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** 初始化RCC时钟 */RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK){Error_Handler();}
}static void MX_TIM2_Init(void)
{TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};htim2.Instance = TIM2;htim2.Init.Prescaler = 168 - 1; // 定时器时钟频率为1MHz,计数周期为1μshtim2.Init.CounterMode = TIM_COUNTERMODE_UP;htim2.Init.Period = 0xFFFF;htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;if (HAL_TIM_Base_Init(&htim2) != HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK){Error_Handler();}
}static void MX_GPIO_Init(void)
{__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);/*Configure GPIO pin : PA0 */GPIO_InitStruct.Pin = GPIO_PIN_0;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/*Configure GPIO pin : PA1 */GPIO_InitStruct.Pin = GPIO_PIN_1;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}void Error_Handler(void)
{while(1){}
}

6.2 触发 HC - SR04 发射超声波

为了触发 HC - SR04 发射超声波,需要向 Trig 引脚发送一个至少 10μs 的高电平脉冲。以下是一个触发 HC - SR04 发射超声波的函数:

void Trigger_HC_SR04(void)
{HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); // 将Trig引脚置为高电平HAL_Delay(1); // 延时1ms,确保高电平持续时间足够长HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // 将Trig引脚置为低电平
}

6.3 测量 Echo 引脚高电平的持续时间

使用定时器来测量 Echo 引脚高电平的持续时间。以下是一个测量 Echo 引脚高电平持续时间的函数:

uint32_t Measure_Echo_Time(void)
{uint32_t start_time, end_time;// 等待Echo引脚变为高电平while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET);// 启动定时器HAL_TIM_Base_Start(&htim2);start_time = __HAL_TIM_GET_COUNTER(&htim2);// 等待Echo引脚变为低电平while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_SET);// 停止定时器HAL_TIM_Base_Stop(&htim2);end_time = __HAL_TIM_GET_COUNTER(&htim2);return end_time - start_time; // 返回高电平持续时间(单位:μs)
}

6.4 计算距离

根据测量得到的 Echo 引脚高电平持续时间,使用公式d=v×t/2计算出距离。以下是一个计算距离的函数:

float Calculate_Distance(uint32_t time)
{float distance;distance = (float)time * 0.034 / 2; // 超声波传播速度为340m/s,转换为cm/μs为0.034cm/μsreturn distance; // 返回距离(单位:cm)
}

6.5 主函数

在主函数中,调用上述函数完成超声波测距的操作。以下是一个完整的主函数示例:

#include "stm32f4xx_hal.h"TIM_HandleTypeDef htim2;
GPIO_InitTypeDef GPIO_InitStruct = {0};void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
void Trigger_HC_SR04(void);
uint32_t Measure_Echo_Time(void);
float Calculate_Distance(uint32_t time);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_TIM2_Init();float distance;uint32_t echo_time;while (1){Trigger_HC_SR04(); // 触发HC - SR04发射超声波echo_time = Measure_Echo_Time(); // 测量Echo引脚高电平的持续时间distance = Calculate_Distance(echo_time); // 计算距离// 可以在这里将距离值通过串口等方式输出HAL_Delay(1000); // 延时1s,避免频繁测量}
}// 其他函数定义保持不变

七、调试与测试

7.1 硬件连接检查

在进行调试之前,需要检查硬件连接是否正确,确保 HC - SR04 超声波测距模块的电源、Trig 引脚和 Echo 引脚连接无误,同时检查电平转换电路是否正常工作。

7.2 串口调试

可以通过串口将测量得到的距离值输出到串口调试助手中,方便观察和调试。在代码中添加串口初始化和数据发送的代码,例如使用 USART1 进行串口通信:

#include "stm32f4xx_hal.h"UART_HandleTypeDef huart1;
TIM_HandleTypeDef htim2;
GPIO_InitTypeDef GPIO_InitStruct = {0};void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
static void MX_USART1_UART_Init(void);
void Trigger_HC_SR04(void);
uint32_t Measure_Echo_Time(void);
float Calculate_Distance(uint32_t time);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_TIM2_Init();MX_USART1_UART_Init();float distance;uint32_t echo_time;char buffer[50];while (1){Trigger_HC_SR04(); // 触发HC - SR04发射超声波echo_time = Measure_Echo_Time(); // 测量Echo引脚高电平的持续时间distance = Calculate_Distance(echo_time); // 计算距离// 将距离值转换为字符串sprintf(buffer, "Distance: %.2f cm\r\n", distance);// 通过串口发送距离值HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);HAL_Delay(1000); // 延时1s,避免频繁测量}
}void SystemClock_Config(void)
{// 系统时钟配置函数,保持不变
}static void MX_TIM2_Init(void)
{// 定时器初始化函数,保持不变
}static void MX_GPIO_Init(void)
{// GPIO初始化函数,保持不变
}static void MX_USART1_UART_Init(void)
{huart1.Instance = USART1;huart1.Init.BaudRate = 9600;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}
}void Trigger_HC_SR04(void)
{// 触发HC - SR04发射超声波函数,保持不变
}uint32_t Measure_Echo_Time(void)
{// 测量Echo引脚高电平持续时间函数,保持不变
}float Calculate_Distance(uint32_t time)
{// 计算距离函数,保持不变
}void Error_Handler(void)
{while(1){}
}

7.3 实际测试

将 STM32F407 开发板和 HC - SR04 超声波测距模块放置在合适的位置,使用不同距离的目标物体进行测试,观察串口调试助手中输出的距离值是否准确。

八、常见问题及解决方法

8.1 测量结果不准确

  • 原因
    • 超声波传播过程中受到干扰,例如周围有其他超声波源或障碍物。
    • 定时器精度不够,导致测量的 Echo 引脚高电平持续时间不准确。
    • 电平转换电路存在问题,导致 Echo 引脚信号异常。
  • 解决方法
    • 尽量避免在有干扰的环境下使用 HC - SR04 超声波测距模块,或者采取屏蔽措施减少干扰。
    • 检查定时器的配置,确保定时器的计数周期准确,同时可以考虑使用更高精度的定时器。
    • 检查电平转换电路的连接和电阻值,确保电平转换正常。

8.2 无法触发 HC - SR04 发射超声波

  • 原因
    • Trig 引脚连接不正确,或者没有输出正确的触发信号。
    • HC - SR04 模块本身存在故障。
  • 解决方法
    • 检查 Trig 引脚的连接,确保其与 STM32F407 的 GPIO 输出引脚连接正确,同时检查触发信号的持续时间是否满足要求。
    • 更换 HC - SR04 模块,检查是否是模块本身的问题。

8.3 无法测量 Echo 引脚高电平的持续时间

  • 原因
    • Echo 引脚连接不正确,或者没有接收到正确的回响信号。
    • 定时器没有正常工作。
  • 解决方法
    • 检查 Echo 引脚的连接,确保其与 STM32F407 的 GPIO 输入引脚连接正确,同时检查电平转换电路是否正常工作。
    • 检查定时器的初始化和启动、停止操作,确保定时器能够正常工作。

九、总结

通过本文的介绍,你已经了解了如何基于 STM32F407 的 HAL 库来驱动 HC - SR04 超声波测距模块。从硬件连接、开发环境搭建到代码实现和调试,详细介绍了整个开发过程。希望本文能帮助你顺利完成基于 HC - SR04 超声波测距模块的嵌入式系统开发。

相关文章:

STM32 HAL库 HC - SR04 超声波测距模块驱动实现

一、引言 在现代嵌入式系统开发中&#xff0c;传感器技术起着至关重要的作用。超声波测距模块作为一种常用的距离测量传感器&#xff0c;因其成本低、精度较高、使用方便等优点&#xff0c;被广泛应用于机器人避障、液位检测、工业自动化等领域。HC - SR04 超声波测距模块是一…...

Spring Boot 热部署详解,包含详细的配置项说明

Spring Boot 热部署详解 1. 热部署简介 热部署&#xff08;Hot Deployment&#xff09;允许在应用运行时修改代码或配置文件&#xff0c;无需重启应用即可使更改生效。Spring Boot 通过 spring-boot-devtools 模块实现这一功能&#xff0c;其核心依赖于 LiveReload 技术和自动…...

剑指Offer(数据结构与算法面试题精讲)C++版——day12

剑指Offer&#xff08;数据结构与算法面试题精讲&#xff09;C版——day12 题目一&#xff1a;小行星碰撞题目二&#xff1a;每日温度题目三&#xff1a;直方图最大矩形面积附录&#xff1a;源码gitee仓库 题目一&#xff1a;小行星碰撞 题目&#xff1a;输入一个表示小行星的数…...

贪心算法(18)(java)距离相等的条形码

在一个仓库里&#xff0c;有一排条形码&#xff0c;其中第 i 个条形码为 barcodes[i]。 请你重新排列这些条形码&#xff0c;使其中任意两个相邻的条形码不能相等。 你可以返回任何满足该要求的答案&#xff0c;此题保证存在答案。 示例 1&#xff1a; 输入&#xff1a;barco…...

Docker学习笔记-docker安装、删除

一、在centOS 7中docker的默认安装目录 # Docker 主配置文件目录 ls /etc/docker# Docker 数据目录&#xff08;镜像、容器、卷等&#xff09; ls /var/lib/docker# Docker 可执行文件路径 which docker # 输出类似 /usr/bin/docker 二、docker文件目录说明 目录/文件用途/…...

【Python 开源】你的 Windows 关机助手——PyQt5 版定时关机工具

&#x1f5a5;️ 你的 Windows 关机助手——PyQt5 版定时关机工具 相关资源文件已经打包成EXE文件&#xff0c;可双击直接运行程序&#xff0c;且文章末尾已附上相关源码&#xff0c;以供大家学习交流&#xff0c;博主主页还有更多Python相关程序案例&#xff0c;秉着开源精神的…...

STM32 HAL库 ADC+TIM+DMA 3路 1S采样一次电压

一、引言 在很多嵌入式系统应用中&#xff0c;需要对多路模拟信号进行周期性采样&#xff0c;例如在工业控制、环境监测等领域。STM32F407 是一款高性能的微控制器&#xff0c;其丰富的外设资源可以方便地实现这样的功能。通过结合 ADC&#xff08;模拟 - 数字转换器&#xff…...

汉诺塔问题——用贪心算法解决

目录 一&#xff1a;起源 二&#xff1a;问题描述 三&#xff1a;规律 三&#xff1a;解决方案 递归算法 四&#xff1a;代码实现 复杂度分析 一&#xff1a;起源 汉诺塔&#xff08;Tower of Hanoi&#xff09;问题起源于一个印度的古老传说。在世界中心贝拿勒斯&#…...

【Python爬虫】简单介绍

目录 一、基本概念 1.1 什么是爬虫 1.2 Python为什么适合爬虫 1.3 Python爬虫应用领域 &#xff08;1&#xff09;数据采集与分析 市场调研 学术研究 &#xff08;2&#xff09;内容聚合与推荐 新闻聚合 视频内容聚合 &#xff08;3&#xff09;金融领域 股票数据获…...

使用MCP服务通过自然语言操作数据库(vscode+cline版本)

使用MCP服务操纵数据库(vscodecline版本) 本文主要介绍&#xff0c;在vscode中使用cline插件调用deepseek模型&#xff0c;通过MCP服务器 使用自然语言去操作指定数据库。本文使用的是以己经创建号的珠海航展数据库。 理解MCP服务&#xff1a; MCP&#xff08;Model Context…...

Vue 3 + TypeScript 实现一个多语言国际化组件(支持语言切换与内容加载)

文章目录 一、项目背景与功能概览二、项目技术架构与依赖安装2.1 技术栈2.2 安装依赖 三、国际化组件实现3.1 创建 i18n 实例3.2 配置 i18n 到 Vue 应用3.3 在组件中使用国际化内容3.4 支持语言切换 四、支持类型安全4.1 添加类型支持4.2 自动加载语言文件 一、项目背景与功能概…...

PhalApi 2.x:让PHP接口开发从“简单”到“极简”的开源框架

—— 专为高效开发而生&#xff0c;助你轻松构建高可用API接口 一、为什么选择PhalApi 2.x&#xff1f; 1.轻量高效&#xff0c;性能卓越 PhalApi 2.x 是一款专为接口开发设计的轻量级PHP框架&#xff0c;其核心代码精简但功能强大。根据开发者实测&#xff0c;在2核2G服务器…...

库magnet使用指南

Magnet 多线程控制库使用指南 目录 库功能概述环境配置核心类与接口基础使用示例代码生成工具高级功能与改进建议完整示例代码常见问题解答 https://blink.csdn.net/details/1872803?spm1001.2014.3001.5501 1. 库功能概述 Magnet 库提供以下核心功能&#xff1a; 多线程…...

Oracle数据库数据编程SQL<9.3 数据库逻辑备份和迁移Data Pump (EXPDP/IMPDP) 导出、导入补充>

Oracle Data Pump 是 Oracle 10g 引入的高效数据迁移工具,相比传统的 EXP/IMP 工具,它提供了更强大的功能和显著的性能提升。以下是对 EXPDP 和 IMPDP 工具的全面讲解。 目录 一、高级功能扩展 1. 数据过滤与转换 2. 加密与安全 二、性能调优进阶 1. 并行处理优化 2. …...

Java 企业级应用:SOA 与微服务的对比与选择

企业级应用开发中&#xff0c;架构设计是决定系统可扩展性、可维护性和性能的关键因素。SOA&#xff08;面向服务的架构&#xff09;和微服务架构是两种主流的架构模式&#xff0c;它们各自有着独特的和设计理念适用场景。本文将深入探讨 SOA 和微服务架构的对比&#xff0c;并…...

Linux LED驱动(设备树)

Linux LED驱动&#xff08;设备树&#xff09; 之前的LED驱动直接在驱动文件中定义有关寄存器物理地址&#xff0c;然后使用io_remap函数进行内存映射&#xff0c;得到对应的虚拟地址&#xff0c;最后操作寄存器对应的虚拟地址完成对GPIO的初始化。 但也可以先在设备树文件中创…...

Zookeeper的典型应用场景?

大家好&#xff0c;我是锋哥。今天分享关于【Zookeeper的典型应用场景?】面试题。希望对大家有帮助&#xff1b; Zookeeper的典型应用场景? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 ZooKeeper 是一个开源的分布式协调服务&#xff0c;主要用于管理和协调大…...

数据分析不只是跑个SQL!

数据分析不只是跑个SQL&#xff01; 数据分析五大闭环&#xff0c;你做到哪一步了&#xff1f;闭环一&#xff1a;认识现状闭环二&#xff1a;原因分析闭环三&#xff1a;优化表现闭环四&#xff1a;预测走势闭环五&#xff1a;主动解读数据 数据思维&#xff1a;WHY-WHAT-HOW模…...

面试篇 - GPT-3(Generative Pre-trained Transformer 3)模型

GPT-3&#xff08;Generative Pre-trained Transformer 3&#xff09;模型 模型结构 与GPT-2一样&#xff0c;但是应用了Sparse attention&#xff1a; Dense attention&#xff1a;每个token之间两两计算attention&#xff0c;复杂度为O(n2)。 Sparse attention&#xff1a;…...

Dify智能体平台源码二次开发笔记(4) - 多租户的SAAS版实现

前言 Dify 的多租户功能是其商业版的标准功能&#xff0c;我们应当尊重其盈利模式。只有保持良性的商业运作&#xff0c;Dify 才能持续发展&#xff0c;并为用户提供更优质的功能。因此&#xff0c;此功能仅限学习使用。 我们的需求是&#xff1a;实现类似 SaaS 版的账号隔离&a…...

C# 13新特性 - .NET 9

转载&#xff1a; C# 13 中的新增功能 | Microsoft Learn C# 13 包括以下新增功能。 可以使用最新的 Visual Studio 2022 版本或 .NET 9 SDK 尝试这些功能&#xff1a;Introduced in Visual Studio 2022 Version 17.12 and newer when using C# 13 C# 13 中的新增功能 | Micr…...

【Code】《代码整洁之道》笔记-Chapter9-单元测试

第9章 单元测试 过去十年以来&#xff0c;编程专业领域进步很大。1997年时&#xff0c;没人听说过测试驱动开发。对于我们之中的大多数人来说&#xff0c;单元测试是那种用来确保程序“可运行”的用过即扔的短代码。我们辛勤地编写类和方法&#xff0c;再弄出一些特殊代码来测…...

java -jar 如何持久化运行

在 Linux 中,直接通过 java -jar 启动服务后关闭 SSH 客户端(如 Xshell)会导致服务终止,因为进程默认与当前终端会话绑定。以下是几种解决方案,确保服务在后台持久运行: (1)使用nohup命令,让进程忽略挂断信号,并在后台运行。 ps -ef | grep xxx.jar 或者 ps -ef …...

layui中transfer两个table展示不同的数据列

在项目的任务开发中需要达到transfer右侧table需要有下拉框可选择状态&#xff0c;左侧table不变 使用的layui版本为2.4.5&#xff0c;该版本没有对transfer可自定义数据列的配置&#xff0c;所以改动transfer.js中的源码 以下为transfer.js部分源码 也是transfer.js去render的…...

如何通过Radius认证服务器实现虚拟云桌面安全登录认证:安当ASP身份认证系统解决方案

引言&#xff1a;虚拟化时代的安全挑战 随着云计算和远程办公的普及&#xff0c;虚拟云桌面&#xff08;如VMware Horizon、Citrix&#xff09;已成为企业数字化办公的核心基础设施。然而&#xff0c;传统的用户名密码认证方式暴露了诸多安全隐患&#xff1a;弱密码易被暴力破…...

如何用DeepSeek大模型提升MySQL DBA工作效率?实战案例解析

如何用DeepSeek大模型提升MySQL DBA工作效率&#xff1f;实战案例解析 MySQL DBA&#xff08;数据库管理员&#xff09;的工作涉及数据库监控、SQL优化、故障排查、备份恢复等复杂任务&#xff0c;传统方式依赖手动操作和经验判断&#xff0c;效率较低。而DeepSeek大模型可以结…...

【机器学习】机器学习笔记

1 机器学习定义 计算机程序从经验E中学习&#xff0c;解决某一任务T&#xff0c;进行某一性能P&#xff0c;通过P测定在T上的表现因经验E而提高。 eg&#xff1a;跳棋程序 E&#xff1a; 程序自身下的上万盘棋局 T&#xff1a; 下跳棋 P&#xff1a; 与新对手下跳棋时赢的概率…...

CFD中的动量方程非守恒形式详解

在计算流体力学&#xff08;CFD&#xff09;中&#xff0c;动量方程可以写成守恒形式和非守恒形式&#xff0c;两者在数学上等价&#xff0c;但推导方式和应用场景不同。以下是对非守恒形式的详细解释&#xff1a; 1. 动量方程的守恒形式 首先回顾守恒形式的动量方程&#xff…...

如何在本地修改 Git 项目的远程仓库地址

✅ 场景说明 你当前的 Git 项目地址是&#xff1a; http://192.168.0.16/xxx.git你希望把它改成&#xff1a; http://192.168.0.22:8099/xxx.git&#x1f9e9; 操作步骤 步骤 ①&#xff1a;进入项目所在目录 你已经在正确路径下了&#xff1a; cd C:\Develop\xxx确认这个…...

clickhouse中的窗口函数

窗口函数 边界核心参数 窗口边界通过 ROWS、RANGE 或 GROUPS 模式定义,语法为: ROWS BETWEEN AND 基于 ​物理行位置 定义窗口,与排序键的实际值无关,适用于精确控制窗口行数 – 或 RANGE BETWEEN AND 基于 ​排序键的数值范围 定义窗口,适用于时间序列或连续数值的场景(…...