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

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

一、简介:

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

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

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

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

  • 采用TO-92或SOT-223封装

  • 通过1-Wire协议通信,仅需单数据线

二、硬件接口:

DS2411R (TO-92封装)+----------+|          |
1 -| GND      | (连接到STM32的GND)
2 -| DQ       | (连接到STM32的GPIO引脚,通过4.7kΩ上拉电阻到VDD)
3 -| VDD      | (连接到STM32的3.3V)|          |+----------+

三、头文件:

#ifndef DS2411R_H
#define DS2411R_H

#include "stm32l4xx_hal.h"

#define DS2411R_FAMILY_CODE    0x01

typedef struct {
    GPIO_TypeDef* GPIOx;
    uint16_t GPIO_Pin;
    uint8_t ROM_NO[8];
} DS2411R_HandleTypeDef;

// 函数声明
HAL_StatusTypeDef DS2411R_Init(DS2411R_HandleTypeDef *hds, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
HAL_StatusTypeDef DS2411R_ReadROM(DS2411R_HandleTypeDef *hds);
void DS2411R_PrintROM(DS2411R_HandleTypeDef *hds);
uint8_t DS2411R_CRC8(uint8_t *addr, uint8_t len);

// 底层1-Wire函数
HAL_StatusTypeDef OneWire_Reset(DS2411R_HandleTypeDef *hds);
void OneWire_WriteBit(DS2411R_HandleTypeDef *hds, uint8_t bit);
uint8_t OneWire_ReadBit(DS2411R_HandleTypeDef *hds);
void OneWire_WriteByte(DS2411R_HandleTypeDef *hds, uint8_t byte);
uint8_t OneWire_ReadByte(DS2411R_HandleTypeDef *hds);

#endif // DS2411R_H

四、源文件:

#include "ds2411r.h"
#include "stdio.h" // 仅用于调试打印

// 初始化DS2411R
HAL_StatusTypeDef DS2411R_Init(DS2411R_HandleTypeDef *hds, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
    hds->GPIOx = GPIOx;
    hds->GPIO_Pin = GPIO_Pin;
    
    // 初始化为高电平
    HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_SET);
    
    // 测试总线是否存在设备
    return OneWire_Reset(hds);
}

// 读取ROM
HAL_StatusTypeDef DS2411R_ReadROM(DS2411R_HandleTypeDef *hds) {
    if (OneWire_Reset(hds) != HAL_OK) {
        return HAL_ERROR;
    }
    
    // 发送读取ROM命令 (0x33)
    OneWire_WriteByte(hds, 0x33);
    
    // 读取8字节ROM数据
    for (uint8_t i = 0; i < 8; i++) {
        hds->ROM_NO[i] = OneWire_ReadByte(hds);
    }
    
    // 校验CRC
    if (hds->ROM_NO[7] != DS2411R_CRC8(hds->ROM_NO, 7)) {
        return HAL_ERROR;
    }
    
    // 检查家族码是否正确
    if (hds->ROM_NO[0] != DS2411R_FAMILY_CODE) {
        return HAL_ERROR;
    }
    
    return HAL_OK;
}

// 打印ROM信息 (调试用)
void DS2411R_PrintROM(DS2411R_HandleTypeDef *hds) {
    printf("DS2411R ROM Code: ");
    for (int i = 0; i < 8; i++) {
        printf("%02X ", hds->ROM_NO[i]);
    }
    printf("\r\n");
    
    printf("Family Code: 0x%02X\r\n", hds->ROM_NO[0]);
    printf("Serial Number: ");
    for (int i = 1; i < 7; i++) {
        printf("%02X", hds->ROM_NO[i]);
    }
    printf("\r\n");
    printf("CRC: 0x%02X\r\n", hds->ROM_NO[7]);
}

// CRC8计算
uint8_t DS2411R_CRC8(uint8_t *addr, uint8_t len) {
    uint8_t crc = 0;
    uint8_t i;
    
    while (len--) {
        crc ^= *addr++;
        for (i = 0; i < 8; i++) {
            if (crc & 0x01) {
                crc = (crc >> 1) ^ 0x8C;
            } else {
                crc >>= 1;
            }
        }
    }
    
    return crc;
}

// 1-Wire复位脉冲
HAL_StatusTypeDef OneWire_Reset(DS2411R_HandleTypeDef *hds) {
    uint8_t retries = 125;
    
    // 拉低总线480us
    HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_RESET);
    HAL_Delay(1); // 实际应使用精确延时,这里简化
    
    // 释放总线
    HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_SET);
    
    // 等待15-60us后设备会拉低总线60-240us
    HAL_Delay(1); // 简化
    
    // 检测存在脉冲
    while (--retries) {
        if (!HAL_GPIO_ReadPin(hds->GPIOx, hds->GPIO_Pin)) {
            break;
        }
        HAL_Delay(1);
    }
    
    if (!retries) {
        return HAL_ERROR;
    }
    
    // 等待复位完成
    retries = 240;
    while (--retries) {
        if (HAL_GPIO_ReadPin(hds->GPIOx, hds->GPIO_Pin)) {
            break;
        }
        HAL_Delay(1);
    }
    
    if (!retries) {
        return HAL_ERROR;
    }
    
    return HAL_OK;
}

// 写1位
void OneWire_WriteBit(DS2411R_HandleTypeDef *hds, uint8_t bit) {
    if (bit) {
        // 写"1"
        HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_RESET);
        HAL_Delay(1); // 实际应为1us
        HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_SET);
        HAL_Delay(60); // 实际应为60us
    } else {
        // 写"0"
        HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_RESET);
        HAL_Delay(60); // 实际应为60us
        HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_SET);
        HAL_Delay(1); // 恢复时间
    }
}

// 读1位
uint8_t OneWire_ReadBit(DS2411R_HandleTypeDef *hds) {
    uint8_t bit = 0;
    
    // 拉低总线1us
    HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_RESET);
    HAL_Delay(1);
    
    // 释放总线
    HAL_GPIO_WritePin(hds->GPIOx, hds->GPIO_Pin, GPIO_PIN_SET);
    HAL_Delay(1);
    
    // 采样总线状态
    if (HAL_GPIO_ReadPin(hds->GPIOx, hds->GPIO_Pin)) {
        bit = 1;
    }
    
    HAL_Delay(60);
    
    return bit;
}

// 写1字节
void OneWire_WriteByte(DS2411R_HandleTypeDef *hds, uint8_t byte) {
    for (uint8_t i = 0; i < 8; i++) {
        OneWire_WriteBit(hds, byte & 0x01);
        byte >>= 1;
    }
}

// 读1字节
uint8_t OneWire_ReadByte(DS2411R_HandleTypeDef *hds) {
    uint8_t byte = 0;
    
    for (uint8_t i = 0; i < 8; i++) {
        byte >>= 1;
        if (OneWire_ReadBit(hds)) {
            byte |= 0x80;
        }
    }
    
    return byte;
}

五、应用:

#include "main.h"
#include "ds2411r.h"

DS2411R_HandleTypeDef hds2411;

int main(void) {
    HAL_Init();
    SystemClock_Config();
    
    // 初始化DS2411R,使用GPIOB, PIN0
    if (DS2411R_Init(&hds2411, GPIOB, GPIO_PIN_0) != HAL_OK) {
        printf("DS2411R not found!\r\n");
        while (1);
    }
    
    // 读取ROM
    if (DS2411R_ReadROM(&hds2411) != HAL_OK) {
        printf("Failed to read DS2411R ROM!\r\n");
        while (1);
    }
    
    // 打印ROM信息
    DS2411R_PrintROM(&hds2411);
    
    while (1) {
        HAL_Delay(1000);
    }
}

相关文章:

  • HarmonyOS NEXT 诗词元服务项目开发上架全流程实战(一、项目介绍及实现效果展示)
  • 蓝桥杯Python组高频考点与解题策略
  • Axios 传参与 Spring Boot 接收参数完全指南
  • Visual Studio 技能:调整软件界面布局
  • SoapUi测试1——REST(WebAPi、Json协议/HTTP、Post通讯方式)接口测试
  • C语言基础—(函数,指针与形参实参,字符串与指针,结构体)
  • 在另外一台可以科学下载的电脑用ollama下载模型后,怎么导入到另外一台服务器的ollama使用
  • (一)Linux的历史与环境搭建
  • 云原生--核心组件-容器篇-6-Docker核心之-镜像仓库(公共仓库,私有仓库,第三方仓库)
  • 香橙派打包qt文件报错“xcb 插件无法加载”与“QObject::moveToThread”线程错误的解决方案
  • 2.2.1goweb内置的 HTTP 处理程序
  • uniapp做app,使用v-for遍历渲染第二层的时候,打包到手机上渲染不出第二层的数据
  • 5G与边缘计算:协同发展,开启智慧世界新篇章
  • (云计算HCIP)HCIP全笔记(十三)本篇介绍虚拟化技术,内容包含:虚拟化资源、虚拟化过程、I/O虚拟化、虚拟化架构KVM和Xen介绍、主流虚拟化技术介绍
  • 终端管理系统如何助力企业简化IT管理?
  • stm32wb55rg (2) 阅读资料手册
  • 近地卫星网络 (Low Earth Orbit Satellite Networks)入门学习笔记
  • C++23 std::bind_back:一种调用包装器 (P2387R3)
  • Scratch——第20课 辗转相除法/绳子算法
  • FTP-网络文件服务器
  • 船只深夜撞上海上风机后沉没1死1失踪,调查报告公布
  • 中纪报:五一节前公开通报释放强烈信号,以铁律狠刹歪风邪气
  • 我国首个核电工业操作系统发布,将在华龙一号新机组全面应用
  • 影子调查丨起底“三无”拖拉机产销链:出口掩内销,监管如虚设
  • 上海论坛2025年会聚焦创新的时代,9份复旦智库报告亮相
  • 共话城市自然之美,“微观黄浦”自媒体网络大V沙龙首场活动举行