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