optical/NxFuncs/encrychip/smec98sp.c
2025-09-04 09:45:08 +08:00

905 lines
17 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//=========================== 加密芯片 SMEC98SP 接口 ===========================//
#include "smec98sp.h"
#ifdef SMEC_CHIP
#include <string.h>
#include "afxdef.h"
#include "stm32f4xx_ll_gpio.h"
//SMEC98SP IIC驱动程序IO口模拟IIC协议
#define IIC_NOACK TRUE
#define IIC_ACK FALSE
#define HIGHT TRUE
#define LOW FALSE
#define IIC_DELAYTIME 24 //bit位延时(实测最小22,可以稳定通讯)
#define ACKCHECKTIME 2000 //等待ACK超时时间
#define IIC_START_TIMES 500 //发送START信号+地址字节) 的次数
//=========================== 与SMEC98SP通讯的管脚定义 ===========================//
#define IIC_SCL_Pin LL_GPIO_PIN_8
#define IIC_SCL_GPIO_Port GPIOA
#define IIC_SCL_GPIO_Clock LL_AHB1_GRP1_PERIPH_GPIOA
#define IIC_SDA_Pin LL_GPIO_PIN_9
#define IIC_SDA_GPIO_Port GPIOC
#define IIC_SDA_GPIO_Clock LL_AHB1_GRP1_PERIPH_GPIOC
//=========================== I2C通讯相关 ===========================//
#if (1)
int initedFlag = 0; // 初始化标志
#define IIC_ADDR 0x00 //对应SMEC98SP中地址
//---------------------------------------------------------
//函数介绍:模拟端口基本配置初始化
//---------------------------------------------------------
void SMEC_I2cInit(void)
{
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LL_GPIO_SetOutputPin(IIC_SCL_GPIO_Port, IIC_SCL_Pin);
LL_GPIO_SetOutputPin(IIC_SDA_GPIO_Port, IIC_SDA_Pin);
GPIO_InitStruct.Pin = IIC_SCL_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
LL_GPIO_Init(IIC_SCL_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = IIC_SDA_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
LL_GPIO_Init(IIC_SDA_GPIO_Port, &GPIO_InitStruct);
// GPIO_InitTypeDef GPIO_InitStructure;
// GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO_Speed_2MHz;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
// GPIO_Init(IIC_PORT, &GPIO_InitStructure);
// GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO_Speed_2MHz;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//GPIO_Mode_Out_OD;//GPIO_Mode_Out_PP;
// GPIO_Init(IIC_PORT, &GPIO_InitStructure);
initedFlag = 0x5a5a; // 初始化标志
}
//数据信号设为输入模式
void SdaInputMode(void)
{
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = IIC_SDA_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
LL_GPIO_Init(IIC_SDA_GPIO_Port, &GPIO_InitStruct);
// GPIO_InitTypeDef GPIO_InitStructure;
// GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO_Speed_2MHz;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// GPIO_Init(IIC_PORT, &GPIO_InitStructure);
}
//数据信号设为输出模式
void SdaOutputMode(void)
{
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = IIC_SDA_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
LL_GPIO_Init(IIC_SDA_GPIO_Port, &GPIO_InitStruct);
// GPIO_InitTypeDef GPIO_InitStructure;
// GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO_Speed_2MHz;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
// GPIO_Init(IIC_PORT, &GPIO_InitStructure);
}
void IIC_Delay(unsigned int times)
{
u16 loop;
for(loop=0;loop<times;loop++)
{
}
}
//时钟信号输出高电平
void IIC_SetSclPin(void)
{
LL_GPIO_SetOutputPin(IIC_SCL_GPIO_Port, IIC_SCL_Pin);
//GPIO_WriteBit(IIC_PORT,IIC_SCL_PIN,Bit_SET);
}
//时钟信号输出低电平
void IIC_ClrSclPin(void)
{
LL_GPIO_ResetOutputPin(IIC_SCL_GPIO_Port, IIC_SCL_Pin);
//GPIO_WriteBit(IIC_PORT,IIC_SCL_PIN,Bit_RESET);
}
//数据信号输出高电平
void IIC_SetSdaPin(void)
{
LL_GPIO_SetOutputPin(IIC_SDA_GPIO_Port, IIC_SDA_Pin);
//GPIO_WriteBit(IIC_PORT,IIC_SDA_PIN,Bit_SET);
}
//数据信号输出低电平
void IIC_ClrSdaPin(void)
{
LL_GPIO_ResetOutputPin(IIC_SDA_GPIO_Port, IIC_SDA_Pin);
//GPIO_WriteBit(IIC_PORT,IIC_SDA_PIN,Bit_RESET);
}
//获取数据信号上的输入
u32 IIC_GetSdaStus(void)
{
return LL_GPIO_IsInputPinSet(IIC_SDA_GPIO_Port, IIC_SDA_Pin);
//return (bool)(GPIO_ReadInputDataBit(IIC_PORT,IIC_SDA_PIN));
}
//时钟信号输出HLow
void IIC_SetScl(_Bool HLow)
{
HLow?IIC_SetSclPin():IIC_ClrSclPin();
}
//数据信号输出HLow
void IIC_SetSda(_Bool HLow)
{
HLow?IIC_SetSdaPin():IIC_ClrSdaPin();
}
//---------------------------------------------------------
//函数介绍i2c起始信号产生
//参数说明:
// void
//返回值说明:
// void
//---------------------------------------------------------
void IIC_Start(void)
{
SdaOutputMode();
IIC_SetSda(HIGHT);
IIC_SetScl(HIGHT);
IIC_Delay(IIC_DELAYTIME);
IIC_SetSda(LOW);
IIC_Delay(IIC_DELAYTIME);
IIC_SetScl(LOW);
}
//---------------------------------------------------------
//函数介绍i2c停止信号产生
//参数说明:
// void
//返回值说明:
// void
//---------------------------------------------------------
void IIC_Stop(void)
{
SdaOutputMode();
IIC_SetSda(LOW);
IIC_SetScl(HIGHT);
IIC_Delay(IIC_DELAYTIME);
IIC_SetSda(HIGHT);
IIC_Delay(IIC_DELAYTIME);
}
//---------------------------------------------------------
//函数名: i2c发送一个字节
//参数说明:
// ucVal : 字节数据
//返回值说明:
// 0 - 成功
// 1 - 失败
//---------------------------------------------------------
_Bool IIC_Send(u8 ucVal)
{
_Bool Ack;
u16 AckLoop;
u8 i;
SdaOutputMode();
for(i=0;i<8;i++)
{
IIC_SetScl(LOW);
IIC_Delay(IIC_DELAYTIME);
IIC_SetSda((ucVal & 0x80)?TRUE:FALSE);
IIC_Delay(IIC_DELAYTIME);
IIC_SetScl(HIGHT);
IIC_Delay(IIC_DELAYTIME);
IIC_Delay(IIC_DELAYTIME);
ucVal<<= 1;
}
IIC_SetScl(LOW);
SdaInputMode();
IIC_Delay(IIC_DELAYTIME);
IIC_Delay(IIC_DELAYTIME);
IIC_SetScl(HIGHT);
IIC_Delay(IIC_DELAYTIME);
IIC_Delay(IIC_DELAYTIME);
Ack = IIC_NOACK;
for(AckLoop=0;AckLoop<ACKCHECKTIME;AckLoop++) //260us
{
if(IIC_GetSdaStus() == 0)
{
Ack = IIC_ACK;
break;
}
IIC_Delay(IIC_DELAYTIME);
}
IIC_SetScl(LOW);
return Ack; //return success=0 / failure=1
}
//---------------------------------------------------------
//函数名: i2c读取一个字节
//参数说明:
// bACK - 读取一个字节完成后, 设置SDA状态值
//返回值说明:
// 接收到的数据
//---------------------------------------------------------
u8 IIC_Read(_Bool bACK)
{
u8 Data;
u8 i;
SdaInputMode();
Data = 0;
for(i=0;i<8;i++)
{
Data <<= 1;
IIC_SetScl(LOW);
IIC_Delay(IIC_DELAYTIME);
IIC_Delay(IIC_DELAYTIME);
IIC_Delay(IIC_DELAYTIME);
IIC_SetScl(HIGHT);
IIC_Delay(IIC_DELAYTIME);
IIC_Delay(IIC_DELAYTIME);
if(IIC_GetSdaStus() != 0)
{
Data |= 1;
}
else
{
Data &= 0xfe;
}
}
IIC_SetScl(LOW);
SdaOutputMode();
IIC_Delay(IIC_DELAYTIME);
IIC_SetSda(bACK);
IIC_Delay(IIC_DELAYTIME);
IIC_SetScl(HIGHT);
IIC_Delay(IIC_DELAYTIME);
IIC_Delay(IIC_DELAYTIME);
IIC_SetScl(LOW);
return Data;
}
//---------------------------------------------------------
//函数名: 读出1串数据
//参数说明:
// addr - I2C地址
// buf - 要读取数据缓冲区指针
// len - 待读取长度
//返回值说明:
// 接收到的数据
//---------------------------------------------------------
_Bool IIC_ReadWithAddr(u8 addr, u8 *buf, u8 len)
{
unsigned int i;
i = IIC_START_TIMES;
if (initedFlag != 0x5a5a)
{
SMEC_I2cInit(); // 初始化
}
while (i)
{
IIC_Start();
if (IIC_Send(addr) == IIC_ACK)
{
break;
}
if (--i == 0)
{
return IIC_NOACK;
}
}
for(i = 0; i < len -1 ; i++)
{
buf[i] = IIC_Read(IIC_ACK);
}
buf[i] = IIC_Read(IIC_NOACK);
IIC_Stop();
return IIC_ACK;
}
//---------------------------------------------------------
//函数名: 写入1串数据
//参数说明:
// addr - I2C地址
// buf - 要写入数据缓冲区指针
// len - 待写入长度
//返回值说明:
// 接收到的数据
//---------------------------------------------------------
_Bool IIC_WriteWithAddr(u8 addr, u8 *buf, u8 len)
{
unsigned int i;
i = IIC_START_TIMES;
if (initedFlag != 0x5a5a)
{
SMEC_I2cInit(); // 初始化
}
while (i)
{
IIC_Start();
if (IIC_Send(addr) == IIC_ACK)
{
break;
}
if (--i == 0)
{
return IIC_NOACK;
}
}
for(i = 0; i < len; i++)
{
if(IIC_Send(buf[i]))
{
return IIC_NOACK;
}
}
IIC_Delay(IIC_DELAYTIME);
IIC_Delay(IIC_DELAYTIME);
IIC_Stop();
return IIC_ACK;
}
#endif
// 得到加密芯片软件版本号
// 返回值为0时,表示获取版本号失败.
u16 SMEC_GetVer(void)
{
u8 rst = 0;
u16 ver = 0;
u8 bBuf[128] = {0};
bBuf[0] = 0x00; //读版本号命令字
bBuf[1] = 0x00;
bBuf[2] = 0x00;
bBuf[3] = 0x00;
rst = IIC_WriteWithAddr(IIC_ADDR & 0xFE, bBuf, 4);
if (rst == 0)
{
rst = IIC_ReadWithAddr(IIC_ADDR | 0x1, bBuf, 2);
}
if (rst == 0)
{
ver = (bBuf[0]<<8)|(bBuf[1]);
}
return ver;
}
//---------------------------------------------------------
//函数名: 获取加密芯片SMEC98SP的UID
//参数说明:
// pUID - UID存放指针
//返回值说明:
// 0 - 成功
// 1 - 失败
//---------------------------------------------------------
#define UID_LEN 0x0C
u8 SMEC_GetUid(u8 * pUID)
{
u8 i = 0;
u8 rst = 0;
u8 sum = 0;
u8 bBuf[128] = {0};
u8 cnt0 = 0;
u8 cnt255 = 0;
if (pUID == NULL)
{
return 1;
}
bBuf[0] = 0x01; //读UID命令字
bBuf[1] = 0x00;
bBuf[2] = 0x00;
bBuf[3] = 0x00;
rst = IIC_WriteWithAddr(IIC_ADDR & 0xFE, bBuf, 4);
if (rst == 0)
{
rst = IIC_ReadWithAddr(IIC_ADDR | 0x1, bBuf, (UID_LEN + 2));
}
if (rst == 0)
{
for (i=0;i<(UID_LEN+2);i++)
{// 校验和
sum += bBuf[i];
}
}
for (i = 2;i<(UID_LEN + 2);i++)
{
if (bBuf[i] == 0)
{
cnt0++;
}
if (bBuf[i] == 0xFF)
{
cnt255++;
}
}
if ((rst == 0) &&
(bBuf[0] == 0x81) && // 0x81 表示执行正确, 其他表示错误
(sum == 0) && // 和校验
(cnt0 != 12) && // 全0
(cnt255 != 12) && // 全FF
1 )
{
memcpy(pUID, bBuf + 2, UID_LEN);
}
else
{
rst = 1;
}
return rst;
}
//---------------------------------------------------------
//函数名: 获取加密芯片SMEC98SP的随机数
//参数说明:
// pRandom - 随机数存放指针
//返回值说明:
// 0 - 成功
// 1 - 失败
//---------------------------------------------------------
u8 SMEC_GetRandom(u8 *pRandom, u8 bLen)
{
u8 i = 0;
u8 rst = 0;
u8 sum = 0;
u8 bBuf[128] = {0};
if ((pRandom == NULL) || (bLen > 124) || (bLen == 0))
{
return 1;
}
bBuf[0] = 0x02;
bBuf[1] = 0x00;
bBuf[2] = 0x00;
bBuf[3] = bLen ;
rst = IIC_WriteWithAddr(IIC_ADDR & 0xFE, bBuf, 4);
if (rst == 0)
{
rst = IIC_ReadWithAddr(IIC_ADDR | 0x1, bBuf, (bLen+2));
}
if (rst == 0)
{
for (i=0;i<(bLen+2);i++)
{// 校验和
sum += bBuf[i];
}
}
if ((rst == 0) &&
(bBuf[0] == 0x82) && // 0x82 表示执行正确, 其他表示错误
(sum == 0) && // 和校验
1 )
{
memcpy(pRandom, bBuf + 2, bLen);
}
else
{
rst = 1;
}
return rst;
}
//---------------------------------------------------------
//函数名: 读Flash
//参数说明:
// pbData - 读取数据存放地址
// bLen - 读取的数据长度
//返回值说明:
// 0 - 成功
// 1 - 失败
//说明:
//---------------------------------------------------------
u8 SMEC_ReadFlash(u16 wAddr, u8 *pbData, u8 bLen)
{
u8 i = 0;
u8 rst = 0;
u8 sum = 0;
u8 bBuf[128] = {0};
if ((pbData == NULL) || (bLen > 124) || (bLen == 0))
{
return 1;
}
bBuf[0] = 0x03;
bBuf[1] = (u8)(wAddr>>8);
bBuf[2] = (u8) wAddr;
bBuf[3] = bLen; //需要读取数据长度
rst = IIC_WriteWithAddr(IIC_ADDR & 0xFE, bBuf, 4);
if (rst == 0)
{
rst = IIC_ReadWithAddr(IIC_ADDR | 0x1, bBuf, (bLen+2));
}
if (rst == 0)
{
for (i=0;i<(bLen+2);i++)
{// 校验和
sum += bBuf[i];
}
}
if ((rst == 0) &&
(bBuf[0] == 0x83) && // 0x83 表示执行正确, 其他表示错误
(sum == 0) && // 和校验
1 )
{
memcpy(pbData, bBuf + 2, bLen);
}
else
{
rst = 1;
}
return rst;
}
//---------------------------------------------------------
//函数名: 擦擦Flash
//参数说明:
// wAddr - 擦擦地址
//返回值说明:
// 0 - 成功
// 1 - 失败
//说明:
//---------------------------------------------------------
u8 SMEC_EraseFlash(u16 wAddr)
{
u8 i = 0;
u8 rst = 0;
u8 sum = 0;
u8 bBuf[128] = {0};
bBuf[0] = 0x04;
bBuf[1] = (u8)(wAddr>>8);
bBuf[2] = (u8) wAddr;
bBuf[3] = 0x00;
rst = IIC_WriteWithAddr(IIC_ADDR & 0xFE, bBuf, 4);
if (rst == 0)
{
rst = IIC_ReadWithAddr(IIC_ADDR | 0x1, bBuf, 2);
}
if (rst == 0)
{
for (i=0;i<2;i++)
{// 校验和
sum += bBuf[i];
}
}
if ((rst == 0) &&
(bBuf[0] == 0x84) && // 0x84 表示执行正确, 其他表示错误
(sum == 0) && // 和校验
1 )
{
}
else
{
rst = 1;
}
return rst;
}
//---------------------------------------------------------
//函数名: 写Flash
//参数说明:
// pbData - 写入数据存放地址
// bLen - 写入的数据长度
//返回值说明:
// 0 - 成功
// 1 - 失败
//说明:
//---------------------------------------------------------
u8 SMEC_WriteFlash(u16 wAddr, u8 *pbData, u8 bLen)
{
u8 i = 0;
u8 rst = 0;
u8 sum = 0;
u8 bBuf[128] = {0};
if ((pbData == NULL) || (bLen > 124) || (bLen == 0))
{
return 1;
}
bBuf[0] = 0x05;
bBuf[1] = (u8)(wAddr>>8);
bBuf[2] = (u8) wAddr;
bBuf[3] = bLen; //需要读取数据长度
memcpy(&bBuf[4], pbData, bLen);
rst = IIC_WriteWithAddr(IIC_ADDR & 0xFE, bBuf, bLen + 4);
if (rst == 0)
{
rst = IIC_ReadWithAddr(IIC_ADDR | 0x1, bBuf, 2);
}
if (rst == 0)
{
for (i=0;i<2;i++)
{// 校验和
sum += bBuf[i];
}
}
if ((rst == 0) &&
(bBuf[0] == 0x85) && // 0x85 表示执行正确, 其他表示错误
(sum == 0) && // 和校验
1 )
{
}
else
{
rst = 1;
}
return rst;
}
//---------------------------------------------------------
//函数名: 加密数据
//参数说明:
// key - 加密因子 (0~127)
// pbData - 写入数据存放地址
// bLen - 写入的数据长度
//返回值说明:
// 0 - 成功
// 1 - 失败
//说明:
//---------------------------------------------------------
u8 SMEC_EncryptionData(u8 key, u8 *pbData, u8 bLen)
{
u8 i = 0;
u8 rst = 0;
u8 sum = 0;
u8 bBuf[128] = {0};
if ((pbData == NULL) || (key > 127) || (bLen >= 124) || (bLen == 0))
{
return 1;
}
bBuf[0] = 0x06;
bBuf[1] = 0x00;
bBuf[2] = key;
bBuf[3] = bLen; //需要读取数据长度
memcpy(&bBuf[4], pbData, bLen);
sum = 0;
for (i=0;i<(bLen+4);i++)
{// 校验和
sum += bBuf[i];
}
bBuf[1] = 0 - sum;
rst = IIC_WriteWithAddr(IIC_ADDR & 0xFE, bBuf, bLen + 4);
if (rst == 0)
{
rst = IIC_ReadWithAddr(IIC_ADDR | 0x1, bBuf, (bLen+2));
}
if (rst == 0)
{
sum = 0;
for (i=0;i<(bLen+2);i++)
{// 校验和
sum += bBuf[i];
}
}
if (rst == 0)
{
if (sum != 0)
{
rst |= 4;
}
else if (bBuf[0] != 0x86)
{
rst = bBuf[0];
}
}
if (rst == 0)
{
memcpy(pbData, bBuf + 2, bLen);
}
return rst;
}
//---------------------------------------------------------
//函数名: 解密数据
//参数说明:
// key - 加密因子 (0~127)
// pbData - 写入数据存放地址
// bLen - 写入的数据长度
//返回值说明:
// 0 - 成功
// 1 - 失败
//说明:
//---------------------------------------------------------
u8 SMEC_DecryptionData(u8 key, u8 *pbData, u8 bLen)
{
u8 i = 0;
u8 rst = 0;
u8 sum = 0;
u8 bBuf[128] = {0};
if ((pbData == NULL) || (key > 127) || (bLen >= 124) || (bLen == 0))
{
return 1;
}
bBuf[0] = 0x07;
bBuf[1] = 0x00;
bBuf[2] = key;
bBuf[3] = bLen; //需要读取数据长度
memcpy(&bBuf[4], pbData, bLen);
sum = 0;
for (i=0;i<(bLen+4);i++)
{// 校验和
sum += bBuf[i];
}
bBuf[1] = 0 - sum;
rst = IIC_WriteWithAddr(IIC_ADDR & 0xFE, bBuf, bLen + 4);
if (rst == 0)
{
rst = IIC_ReadWithAddr(IIC_ADDR | 0x1, bBuf, (bLen+2));
}
if (rst == 0)
{
sum = 0;
for (i=0;i<(bLen+2);i++)
{// 校验和
sum += bBuf[i];
}
}
if (rst == 0)
{
if (sum != 0)
{
rst |= 4;
}
else if (bBuf[0] != 0x87)
{
rst = bBuf[0];
}
}
if (rst == 0)
{
memcpy(pbData, bBuf + 2, bLen);
}
return rst;
}
// 加密芯片验证
int SMEC_Detection(void)
{
int rslt = 0;
u8 dat1[12] = {0};
u8 dat2[12] = {0};
rslt = SMEC_GetUid(dat1);
if (rslt == 0)
{
rslt = SMEC_GetRandom(dat1,12);
}
if (rslt == 0)
{
memcpy(dat2, dat1, 12);
rslt = SMEC_EncryptionData(0, dat2, 12);
}
if (rslt == 0)
{
rslt = SMEC_DecryptionData(0, dat2, 12);
}
if (rslt == 0)
{
for (int i=0;i<12;i++)
{
if (dat2[i] != dat1[i])
{
rslt = 1;
}
}
}
return rslt;
}
#endif