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

基于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);
    }
}

http://www.xdnf.cn/news/2933.html

相关文章:

  • RPO与RTO
  • 代码随想录第30天:动态规划3
  • Foreign Trade Process
  • 9.Excel:条件格式
  • torch.nn.Parameter 与 torch.Tensor
  • 微机控制电液伺服钢轨滚动疲劳试验机
  • 17:00开始面试,17:08就出来了,问的问题有点变态。。。
  • TransactionTemplate 与@Transactional 注解的使用
  • python22-元组、列表、字典、集合推导式
  • 清洁电力转换技术全球引领者——阳光电源,如何搭建数字化业务平台?
  • 代码随想录打卡|Day29 动态规划Part02(不同路径、不同路径2、整数拆分、不同的二叉树搜索)
  • 第十二届蓝桥杯 2021 C/C++组 空间
  • 什么是数据中心代理IP?有哪些用途?
  • Spring之IoC控制反转
  • 【Maven】子POM与父POM
  • C++23/26 静态反射机制深度解析:编译时元编程的新纪元
  • 一文读懂布隆过滤器:特性、应用与局限
  • docker存储
  • 在g2o图优化框架中,顶点(Vertex)和边(Edge)的定义与功能的区别
  • 基于Python镜像创建docker镜像时pip install一直出现NewConnectionError的一种解决办法
  • AGV、AMR机器人控制器x86/RK3588/NV各有什么优劣势?
  • 【Stable Diffusion】使用教程:从原理到实战,全面掌握AI绘画
  • VMware安装Ubuntu实战分享
  • 白光干涉技术在高精度表面形貌测量中的实际应用
  • 永磁同步电机控制算法-转速环电流环SMC控制器
  • 漫反射实现+逐像素漫反射+逐像素漫反射实现
  • 机器学习分类模型性能评估:应对类别不平衡的策略与指标
  • 数据结构 RBT 插入操作的 Python 代码实现
  • EMB量产首航!炯熠电子引领「线控底盘革命」
  • SOLIDWORKS修改模型默认颜色教程