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

基于STM32、HAL库的DS2401P安全验证及加密芯片驱动程序设计

一、简介:

DS2401P是Maxim Integrated(现为Analog Devices)生产的一款1-Wire®硅序列号芯片,具有以下特点:

  • 64位唯一ROM编码(包括8位家族码、48位序列号和8位CRC校验码)

  • 单总线接口,仅需一根数据线(加上地线)

  • 工作电压范围:2.8V至5.25V

  • 每个器件有唯一的64位ROM编码,适合用于设备识别

  • 典型读取时间小于5ms

  • 工作温度范围:-40°C至+85°C

二、硬件接口:

DS2401P          STM32L4xx|                |
1 |--DATA---------->| GPIO (配置为开漏输出)
2 |--GND------------| GND

注意事项:

  1. 需要在DATA线上拉一个4.7kΩ电阻到VCC

  2. 建议在靠近MCU端添加一个100Ω电阻作为保护

  3. 如果总线较长,可能需要更强的上拉电阻

三、头文件:

#ifndef __DS2401P_H
#define __DS2401P_H

#ifdef __cplusplus
extern "C" {
#endif

#include "stm32l4xx_hal.h"

#define DS2401P_FAMILY_CODE 0x01

typedef struct {
    GPIO_TypeDef* GPIOx;
    uint16_t GPIO_Pin;
    uint8_t ROM[8];
} DS2401P_HandleTypeDef;

HAL_StatusTypeDef DS2401P_Init(DS2401P_HandleTypeDef *hds, GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
HAL_StatusTypeDef DS2401P_ReadROM(DS2401P_HandleTypeDef *hds);
uint8_t DS2401P_CRC8(const uint8_t *addr, uint8_t len);
HAL_StatusTypeDef DS2401P_ValidateROM(DS2401P_HandleTypeDef *hds);

#ifdef __cplusplus
}
#endif

#endif /* __DS2401P_H */

四、源文件:

#include "ds2401p.h"
#include "main.h"

// 单总线时序延迟函数
#define DS2401P_DELAY_US(us) HAL_Delay_us(us)

// 微秒级延迟函数(需要根据系统时钟配置)
__weak void HAL_Delay_us(uint16_t us)
{
    uint32_t ticks = us * (SystemCoreClock / 1000000) / 5;
    uint32_t start = DWT->CYCCNT;
    while ((DWT->CYCCNT - start) < ticks);
}

// 初始化单总线GPIO
static void DS2401P_GPIO_Init(DS2401P_HandleTypeDef *hds)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // 配置为开漏输出,无上拉
    GPIO_InitStruct.Pin = hds->GPIO_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(hds->GPIOx, &GPIO_InitStruct);
    
    // 初始状态为高电平
    HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_SET);
}

// 发送复位脉冲并检测存在脉冲
static HAL_StatusTypeDef DS2401P_Reset(DS2401P_HandleTypeDef *hds)
{
    uint8_t presence = 0;
    
    // 拉低总线至少480us
    HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_RESET);
    DS2401P_DELAY_US(480);
    
    // 释放总线(上拉电阻将拉高)
    HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_SET);
    DS2401P_DELAY_US(70);
    
    // 检测存在脉冲(设备应在60-240us内拉低总线)
    presence = HAL_GPIO_ReadPin(hds->GPIOx, hds->GPIO_Pin);
    DS2401P_DELAY_US(410);
    
    return (presence == GPIO_PIN_RESET) ? HAL_OK : HAL_ERROR;
}

// 写一个位到单总线
static void DS2401P_WriteBit(DS2401P_HandleTypeDef *hds, uint8_t bit)
{
    if (bit) {
        // 写"1"
        HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_RESET);
        DS2401P_DELAY_US(6);
        HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_SET);
        DS2401P_DELAY_US(64);
    } else {
        // 写"0"
        HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_RESET);
        DS2401P_DELAY_US(60);
        HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_SET);
        DS2401P_DELAY_US(10);
    }
}

// 从单总线读取一个位
static uint8_t DS2401P_ReadBit(DS2401P_HandleTypeDef *hds)
{
    uint8_t bit = 0;
    
    HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_RESET);
    DS2401P_DELAY_US(6);
    HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_SET);
    DS2401P_DELAY_US(9);
    
    bit = HAL_GPIO_ReadPin(hds->GPIOx, hds->GPIO_Pin);
    DS2401P_DELAY_US(55);
    
    return (bit == GPIO_PIN_SET) ? 1 : 0;
}

// 写一个字节到单总线
static void DS2401P_WriteByte(DS2401P_HandleTypeDef *hds, uint8_t byte)
{
    for (uint8_t i = 0; i < 8; i++) {
        DS2401P_WriteBit(hds, byte & 0x01);
        byte >>= 1;
    }
}

// 从单总线读取一个字节
static uint8_t DS2401P_ReadByte(DS2401P_HandleTypeDef *hds)
{
    uint8_t byte = 0;
    
    for (uint8_t i = 0; i < 8; i++) {
        byte >>= 1;
        if (DS2401P_ReadBit(hds)) {
            byte |= 0x80;
        }
    }
    
    return byte;
}

// 初始化DS2401P
HAL_StatusTypeDef DS2401P_Init(DS2401P_HandleTypeDef *hds, GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
    hds->GPIOx = GPIOx;
    hds->GPIO_Pin = GPIO_Pin;
    memset(hds->ROM, 0, sizeof(hds->ROM));
    
    DS2401P_GPIO_Init(hds);
    
    return HAL_OK;
}

// 读取DS2401P的ROM
HAL_StatusTypeDef DS2401P_ReadROM(DS2401P_HandleTypeDef *hds)
{
    if (DS2401P_Reset(hds) != HAL_OK) {
        return HAL_ERROR;
    }
    
    // 发送读取ROM命令 (0x33)
    DS2401P_WriteByte(hds, 0x33);
    
    // 读取64位ROM
    for (uint8_t i = 0; i < 8; i++) {
        hds->ROM[i] = DS2401P_ReadByte(hds);
    }
    
    return DS2401P_ValidateROM(hds);
}

// CRC8校验计算
uint8_t DS2401P_CRC8(const uint8_t *addr, uint8_t len)
{
    uint8_t crc = 0;
    uint8_t i, j;
    
    for (i = 0; i < len; i++) {
        uint8_t inbyte = addr[i];
        for (j = 0; j < 8; j++) {
            uint8_t mix = (crc ^ inbyte) & 0x01;
            crc >>= 1;
            if (mix) crc ^= 0x8C;
            inbyte >>= 1;
        }
    }
    
    return crc;
}

// 验证ROM数据是否有效
HAL_StatusTypeDef DS2401P_ValidateROM(DS2401P_HandleTypeDef *hds)
{
    // 检查家族码
    if (hds->ROM[0] != DS2401P_FAMILY_CODE) {
        return HAL_ERROR;
    }
    
    // 检查CRC
    if (DS2401P_CRC8(hds->ROM, 7) != hds->ROM[7]) {
        return HAL_ERROR;
    }
    
    return HAL_OK;
}

五、应用:

#include "main.h"
#include "ds2401p.h"

DS2401P_HandleTypeDef hds2401;

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    
    // 初始化DS2401P,使用GPIOB, PIN5
    if (DS2401P_Init(&hds2401, GPIOB, GPIO_PIN_5) != HAL_OK) {
        Error_Handler();
    }
    
    // 读取ROM
    if (DS2401P_ReadROM(&hds2401) == HAL_OK) {
        // 打印ROM信息
        printf("DS2401P Found. ROM Code: ");
        for (int i = 0; i < 8; i++) {
            printf("%02X ", hds2401.ROM[i]);
        }
        printf("\r\n");
        
        // 检查CRC
        if (DS2401P_ValidateROM(&hds2401) == HAL_OK) {
            printf("ROM CRC Check OK\r\n");
        } else {
            printf("ROM CRC Check Failed\r\n");
        }
    } else {
        printf("DS2401P Not Found or Communication Error\r\n");
    }
    
    while (1) {
        // 主循环
    }
}

void Error_Handler(void)
{
    while (1) {
        // 错误处理
    }
}

相关文章:

基于STM32、HAL库的DS2401P安全验证及加密芯片驱动程序设计

一、简介&#xff1a; DS2401P是Maxim Integrated&#xff08;现为Analog Devices&#xff09;生产的一款1-Wire硅序列号芯片&#xff0c;具有以下特点&#xff1a; 64位唯一ROM编码&#xff08;包括8位家族码、48位序列号和8位CRC校验码&#xff09; 单总线接口&#xff0c;…...

日志收集之 logback使用

一 简介 1.1 Logback 是一个用于 Java 应用程序的强大日志框架&#xff0c;广泛应用于企业级应用中。它是由 SLF4J 的创始人开发的&#xff0c;旨在成为 Log4j 的替代品。Logback 提供更高级、更灵活的功能&#xff0c;同时还支持与 SLF4J 的无缝集成。 2.2 Logback分为下面几…...

Linux学习笔记(一):Linux下的基本指令

文章目录 Linux下的基本指令1. ls指令2. pwd指令3. cd指令4. touch指令5. mkdir指令&#xff08;牢记&#xff09;6. rmdir指令 && rm 指令&#xff08;牢记&#xff09;7. man指令&#xff08;牢记&#xff09;8. echo指令9. cp指令&#xff08;牢记&#xff09;10. m…...

Unity AI-使用Ollama本地大语言模型运行框架运行本地Deepseek等模型实现聊天对话(二)

一、使用介绍 官方网页&#xff1a;Ollama官方网址 中文文档参考&#xff1a;Ollama中文文档 相关教程&#xff1a;Ollama教程 使用版本&#xff1a;Unity 2022.3.53f1c1、Ollama 0.6.2 示例模型&#xff1a;llama3.2 二、运行示例 三、使用步骤 1、创建Canvas面板 具体…...

SDC命令详解:使用get_clocks命令进行查询

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 get_clocks命令用于创建一个时钟对象集合&#xff0c;关于设计对象和集合的更详细介绍&#xff0c;可以参考下面的博客。需要注意的是&#xff0c;在有些工具中还…...

git 修改用户名和邮箱

在 Git 中修改用户名和邮箱地址是常见的任务&#xff0c;这可以确保你的提交记录使用正确的身份信息。你可以通过简单的命令来完成这一操作。 全局配置 修改全局用户名 要修改全局的用户名&#xff0c;请执行以下命令&#xff1a; git config --global user.name "New…...

pg数据库删除模式

不能直接使用 DROP SCHEMA "app_sys" 删除&#xff0c; 这样会报错 cannot drop schema app sys 20250416 because other objects depend on it DETAlL: extension uuid-ossp depends on schema app sys 20250416sequence app sys 20250416.app sys id seq depend…...

【C++】Googletest应用

Googletest 1 配置 使用cmake配置&#xff1a; 具体文件后面上传补充 ./test.out --gtest_filterXXXTest.xxx 2 gdb 为了跟踪流程&#xff0c;可以使用gdb&#xff1b; gdb ./xxx.out gdb --args ./gtest --gtest_filterxxx.xxx设置运行参数 set args --gtest_filterxxx.…...

QgraphicsView异步线程加载地图瓦片

本节主要记录一下qt开发过程中离线地图瓦片的加载方式&#xff0c;瓦片加载选择graphicsView控件&#xff0c;同时为了不影响主线程事件和其他操作&#xff0c;这里采用了异步线程的操作&#xff0c;将地图瓦片加载的步骤放到了异步子线程之中。注&#xff1a;本记录仅为本人笔…...

机器学习day2

使用KNN算法实现机器学习 给我一个苹果的图片 我能预测出这个是一个苹果 代码&#xff1a; # 导入需要的库 # 读图 import os import cv2 # 绘图 import matplotlib.pyplot as plt import seaborn as sns # 数组 import numpy as np from skimage.feature import hog from sk…...

jquery解决谷歌浏览器自动保存加密密码是乱码

添加一个隐形的input框&#xff0c;提交隐藏input框里的数据&#xff0c;展示框展现的还是明文密码&#xff0c;并且不提交展示框的值 <formid"loginForm"class"form-signin newForm-signin"action"${ctx}/login"method"post"onsub…...

Python 如何操作数据库,让你使用 DeepSeek 开发数据库应用更加快 (Orm Bee)

Python 如何操作数据库&#xff0c;让你使用 DeepSeek 开发数据库应用更加快 操作数据库最好用 ORM 工具&#xff0c;可以提高开发效率. ORM 就是实体与数据库表的映射&#xff0c;让我们可以用面向对象的方式来操作数据库. 简单易用&#xff0c;直接上代码. 使用Orm Bee操作…...

如何解决 Linux 文件系统挂载失败的问题

以下是解决Linux文件系统挂载失败问题的系统性排查与解决方案&#xff1a; 一、设备基础检查 确认设备识别状态‌ 执行 lsblk 或 fdisk -l 查看磁盘设备列表&#xff0c;验证目标设备&#xff08;如 /dev/sdb1&#xff09;是否被系统识别。 若设备未显示&#xff0c;需排查&a…...

JVM——引入

什么是JVM&#xff1f;它与JDK、JRE的关系&#xff1f; JVM、JRE 和 JDK 是 Java 平台的三个核心组件&#xff0c;各自承担着不同的职责&#xff0c;它们之间的关系密不可分。理解它们的区别和联系有助于更好地开发、部署和运行 Java 应用程序。对于 Java 开发者来说&#xff…...

Golang|工厂模式

工厂模式是一种创建型设计模式&#xff0c;它的核心思想是&#xff1a;把对象的创建过程封装起来&#xff0c;不直接在代码中 new 一个对象&#xff0c;而是通过一个“工厂”来生成对象。这样做的好处是&#xff1a; 降低了代码之间的耦合&#xff08;依赖具体类减少&#xff0…...

Transformer数学推导——Q29 推导语音识别中流式注意力(Streaming Attention)的延迟约束优化

该问题归类到Transformer架构问题集——注意力机制——跨模态与多模态。请参考LLM数学推导——Transformer架构问题集。 在语音识别任务中&#xff0c;实时性是核心需求 —— 想象你使用语音助手时&#xff0c;每说完一个词就希望即时看到文字反馈&#xff0c;而不是等整句话说…...

dx11 龙书学习 第四章 dx11 准备工作

4.1 准备工作 Direct3D的初始化过程要求我们熟悉一些基本的Direct3D类型和基本绘图概念&#xff1b;本章第一节会向读者介绍些必要的基础知识。然后我们会详细讲解Direct3D初始化过程中的每一个必要步骤&#xff0c;并顺便介绍一下实时绘图应用程序必须使用的精确计时和时间测…...

运维打铁:域名详解及常见问题解决

文章目录 前言一、域名基础概念1. 什么是域名2. 域名结构3. 域名解析 二、域名工作原理1. DNS 服务器层次结构2. 域名解析过程 三、常见域名问题及解决办法1. 域名无法解析2. 域名解析延迟3. 域名解析结果不一致 四、总结 前言 在当今数字化的时代&#xff0c;互联网已经成为我…...

【大模型ChatGPT+R-Meta】AI赋能R-Meta分析核心技术:从热点挖掘到高级模型、助力高效科研与论文发表“

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面&#xff0c;成为Science、Nature论文的…...

ElasticSearch深入解析(五):如何将一台电脑上的Elasticsearch服务迁移到另一台电脑上

文章目录 0.安装数据迁移工具1.导出数据2.导出mapping3.导出查询模板4.拷贝插件5.拷贝配置6.导入到目标电脑上 0.安装数据迁移工具 Elasticsearch dump是一个用于将Elasticsearch索引数据导出为JSON格式的工具。你可以使用Elasticsearch dump通过命令行或编程接口来导出数据。…...

QT中的多线程

Qt中的多线程和Linux中的线程本质是相同的&#xff0c;Qt中针对系统提供的线程API进行了重新封装 QThread类 Qt中的多线程一般通过QThread类实现&#xff0c;要想创建线程就要创建这个类的实例 QThread代表一个在应用程序中可以独立控制的线程&#xff0c;也可以和进程中的其…...

Win11安装Ubuntu20.04简记

写在前面 之前装的22.04&#xff0c;不稳定&#xff0c;把22.04卸载了&#xff0c;重新安装20.04系统。这里主要把卸载和安装的过程中参考到的博客在这记录一下。 卸载ubuntu系统参考的博文 卸载参考博文1 卸载参考博文2 Ubuntu20.04安装参考博文 安装参考博文1 安装参考博…...

电子电器架构 ---电气/电子架构将在塑造未来出行方面发挥啥作用?

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界噪音的通透淡然。 生活中有两种人,一种人格外在意别人的眼光;另一种人无论…...

pdf.js移动端预览PDF文件时,支持双指缩放

在viewer.html中添加手势缩放代码 <script>// alert("Hello World");let agent navigator.userAgent.toLowerCase();// if (!agent.includes("iphone")) {let pinchZoomEnabled false;function enablePinchZoom(pdfViewer) {let startX 0, start…...

机器人--激光雷达

教程 教程 激光雷达 激光 激光&#xff08;Laser&#xff09;&#xff0c;是一种人造的、高度纯净的单色光。 雷达 激光器旋转机构雷达。 雷达根据激光探头发出激光束的数量&#xff0c;一般可以分为单线激光雷达(2D激光雷达)和多线激光雷(3D激光雷达)。 作用 测距原理 激…...

最新ios开发证书/发布证书/免费证书/企业证书制作教程

本文介绍了如何制作或者苹果开发证书p12文件&#xff0c;含开发证书&#xff0c;推送证书&#xff0c;发布证书&#xff0c;企业证书&#xff0c;免费证书&#xff0c;您在iphone和ipad开发构建 IOS App 应用和苹果ios app签名需要用到。如果嫌麻烦&#xff0c;可以使用懒人工具…...

【Keil5-开发指南】

Keil5-编程指南 ■ Keil5 介绍■ J-Flash 使用■ Keil5-Debug调试工具 Jlink---STLink---DAP仿真器■ Keil5 使用 AStyle插件格式化代码■ Keil5-编译4个阶段■ Keil5-Boot和APP配置■ Keil5-报错■ 芯片手册区别 ■ Keil5 介绍 Keil5 介绍 ■ J-Flash 使用 J-Flash 使用 ■…...

蓝桥杯 18. 机器人繁殖

机器人繁殖 原题目链接 题目描述 X 星系的机器人可以自动复制自己。它们用 1 年的时间可以复制出 2 个自己&#xff0c;然后就失去复制能力。 每年 X 星系都会选出 1 个新出生的机器人发往太空。也就是说&#xff0c;如果 X 星系原有机器人 5 个&#xff0c;1 年后总数是&a…...

从微服务到AI服务:Nacos 3.0如何重构下一代动态治理体系?

在现代微服务架构的浪潮中&#xff0c;Nacos早已成为开发者手中的“瑞士军刀”。作为阿里巴巴开源的核心中间件&#xff0c;它通过动态服务发现、统一配置管理和服务治理能力&#xff0c;为云原生应用提供了坚实的基石。从初创公司到全球500强企业&#xff0c;Nacos凭借其开箱即…...

60、微服务保姆教程(三)Sentinel---高可用流量管理框架/服务容错组件

Sentinel—高可用流量管理框架/服务容错组件 一.为什么要用Sentinel? 1.微服务架构中当某服务挂掉的时候常见的原因有哪些? 1.异常没处理 比如DB连接失败,文件读取失败等 2.突然的流量激增 比如:用户经常会在京东、淘宝、天猫、拼多多等平台上参与商品的秒杀、限时抢…...

[特殊字符] 基于Docker部署Nacos注册中心及微服务注册发现详解(含MySQL持久化配置)

&#x1f4da; 目录 项目背景与准备 Docker部署Nacos并配置MySQL持久化 微服务注册到Nacos&#xff08;item-service示例&#xff09; 微服务服务发现与调用&#xff08;cart-service示例&#xff09; 小结 1. 项目背景与准备 在微服务架构中&#xff0c;服务注册与发现是…...

CentOS 7环境配置DHCP服务器

主播多次测试&#xff0c;没有什么问题。如果有问题可以私信主播&#xff0c;主播不定时查看 目录 1. 初始配置 1.1 配置VMware workstation配置 1.2 设置虚拟机网路适配器为NAT模式 2. 环境搭建 2.1下载相应的软件包 2.2 查找下载的软件包中给出的示例代码所在目录 2.2 …...

基于常微分方程的神经网络(Neural ODE)

参考资料&#xff1a;B站的视频解析 知乎神经常微分方程总结 论文链接&#xff1a;论文 什么是常微分方程&#xff1f; 微分方程式包含未知函数及其导数的方程&#xff0c;未知函数导数的最高阶数称为给i微分方程的阶。 常微分方程(ordinary differential equation&#xff0…...

对VTK中的Volume Data体数据进行二维图像处理

文章目录 概要Cpp代码处理前效果处理后效果 概要 在 VTK 中对体数据进行二维图像处理的过程通常涉及从三维体数据中提取二维切片&#xff0c;并对这些切片进行处理。然后&#xff0c;可以选择性地将处理后的切片数据重新合并成新的体数据。 以下是对 VTK 中的体数据进行二维图…...

阿里云ftp服务器登录要怎么做?如何访问ftp服务器?

阿里云ftp服务器登录要怎么做&#xff1f;如何访问ftp服务器&#xff1f; 访问FTP服务器通常需要以下步骤&#xff0c;具体方法取决于您使用的工具和操作系统&#xff1a; 一、FTP服务器登录所需信息 服务器地址&#xff1a;通常是IP地址&#xff08;如 ftp.example.com 或 192…...

中国的国产化进程

中国的国产化进程是一个涉及国家安全、经济发展和技术自主的长期战略,其历史进程和动因可以从以下几个关键阶段和核心原因来理解: ​​一、国产化的历史进程​​ ​​1. 建国初期(1949–1978):自力更生与基础工业建设​​ ​​背景​​:新中国成立后,面临西方国家的技术…...

突破语言藩篱:从Seq2Seq到智能翻译的范式革命

## 一、语言之桥的智能进化:超越字面转换的深层理解 在慕尼黑工业大学实验室的深夜,一个搭载最新神经网络的翻译系统正逐字解析着歌德诗句的韵律。这并非简单的词语替换,而是一场跨越时空的文化解码——机器首次在《浮士德》的英译本中保留了德文诗歌特有的头韵结构。这个突…...

Java写项目前的准备工作指南(技术栈选择 环境搭建和工具配置 项目结构设计与模块划分)

前言 &#x1f4dd; 在开始编写一个 Java 项目之前&#xff0c;做好充分的准备工作是至关重要的。很多初学者可能在没有清晰规划的情况下就开始编写代码&#xff0c;导致项目开发进度缓慢、结构混乱&#xff0c;甚至最终无法按预期完成。而事实上&#xff0c;项目的成功不仅仅…...

如何使用 Redis 缓存验证码

目录 &#x1f9e0; Redis 缓存验证码的工作原理 &#x1f9f0; 实现流程 1. 安装 Redis 和 Python 客户端 2. 生成并缓存验证码 示例代码&#xff1a;生成并存储验证码 3. 发送验证码&#xff08;以短信为例&#xff09; 4. 校验验证码 示例代码&#xff1a;校验验证码…...

(八)RestAPI 毛子(Unit Testing)

文章目录 项目地址一、Unit Testing1.1 创建X unit 测试项目1. 创建项目目录2. 管理包 1.2 创建CreateEntryDtoValidator测试1.3 创建CreateEntryDtoValidator测试 二、Integration test2.1 创建Integration test环境1. 安装所需要的包 2.2 配置基础设置1. 数据库链接DevHabitW…...

德州仪器(TI)—TDA4VM芯片详解(2)—产品应用和介绍

写在前面 本系列文章主要讲解德州仪器&#xff08;TI&#xff09;TDA4VM芯片的相关知识&#xff0c;希望能帮助更多的同学认识和了解德州仪器&#xff08;TI&#xff09;TDA4VM芯片。 若有相关问题&#xff0c;欢迎评论沟通&#xff0c;共同进步。(*^▽^*) 错过其他章节的同学…...

vue2,3:v-model的语法糖

Vue2的v-model 语法糖 **1. **v-model 的作用 v-model 是 Vue 中用于实现双向数据绑定的指令&#xff0c;主要用于表单元素&#xff08;如 、、&#xff09;和自定义组件。它简化了数据与视图之间的同步&#xff0c;使得开发者可以方便地处理用户输入。 **2. **v-model 的语…...

【深度学习】#10 注意力机制

主要参考学习资料&#xff1a; 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 目录 注意力提示生物学中的注意力提示查询、键和值 注意力汇聚注意力评分函数掩蔽softmax操作加性注意力缩放点积注意力 Bahdanau注意力多头注意力自注意力和位…...

Modbus总线协议智能网关协议转换案例解析:提升系统兼容性

Modbus是一种串行通信协议&#xff0c;是Modicon公司(现在的施耐德电气,Schneider Electic)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(Defacto)&#xff0c;并日现在是工业电子设备之间常用的连接方式 Modbus是一种串行通信协…...

echarts自定义图表--仪表盘

基于仪表盘类型的自定义表盘 上图为3层结构组成 正常一个仪表盘配置要在外圈和内圈之间制造一条缝隙间隔 再创建一个仪表盘配置 背景透明 进度条拉满 进度条颜色和数据的背景相同开始处的线 又一个仪表盘配置 数值固定一个比较小的值 <!DOCTYPE html> <html><h…...

第五章:Execution Flow Framework

Chapter 5: Execution Flow Framework 从消息记忆到执行流程&#xff1a;如何让多个AI“同事”协同完成复杂任务&#xff1f; 在上一章的消息与记忆系统中&#xff0c;我们已经能让AI记住之前的对话内容。但你是否想过&#xff1a;如果用户要求“预订从北京到上海的高铁&#…...

01 C++概述

一、C语言发展史 起源与演进 • 1960s&#xff1a;剑桥大学Martin Richards开发BCPL语言&#xff0c;用于系统软件开发。 • 1970年&#xff1a;贝尔实验室Ken Thompson在BCPL基础上发明B语言。 • 1972年&#xff1a;Dennis Ritchie和Brian Kernighan设计出C语言&#xff0c;兼…...

Kotlin DSL 深度解析:从 Groovy 迁移的困惑与突破

引言 Gradle 作为现代构建工具&#xff0c;支持 Groovy 和 Kotlin 两种 DSL&#xff08;领域特定语言&#xff09;。Kotlin DSL 因其类型安全和更好的 IDE 支持逐渐流行&#xff0c;但它的语法设计却让许多开发者感到困惑&#xff0c;尤其是从 Groovy 迁移时。 本文将从 Kotl…...

2025年二级造价师考点总结

二级造价师考点总结 一、建设工程造价管理 工程造价构成&#xff1a;重点掌握建筑安装工程费&#xff08;人工费、材料费、机械费、企业管理费、利润、规费、税金&#xff09;的组成及计算。 计价依据&#xff1a;熟悉工程量清单计价规范&#xff0c;掌握定额计价与清单计价的…...

Typecho博客使用阿里云cdn和oss:handsome主题进阶版

Typecho使用阿里云cdn和oss 设置前需要保证阿里云cdn和oss已配置好且可以正常使用一、准备工作二、修改 Handsome 主题的静态资源链接方法 1&#xff1a;直接修改主题文件&#xff08;推荐&#xff09;方法 2&#xff1a;通过主题设置自定义&#xff08;方便&#xff09; 三、处…...