最近搞一个智能卡的项目,焦头烂额了@正点原子
自己写的程序,读RAM没有问题,读出数据前48Byte如下:
a2 13 10 91 ff ff 81 15 ff ff ff ff ff ff ff ff
ff ff ff ff ff d2 76 0 0 4 0 ff ff ff ff ff
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff (后面全FF)
读密码计数器为0x07 00 00 00
在进行密码校验的时候,写密码计数器一位为0,也是正常的,但是写校验和后面恢复密码计数器的时候就总不成功,用原子哥之前提供的读写程序(原帖
http://www.openedv.com/forum.php ... &highlight=4442),读书全是FF,密码校验也不对。贴出程序,给大家看一下,帮忙研究一下,谢谢诸位
[mw_shl_code=applescript,true]
#include "ic_card.h"
#include "delay.h"
//通讯接口初始化
void IC_CardInit()
{
GPIO_InitTypeDef GPIO_InitStructre;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructre.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_11|GPIO_Pin_12;
GPIO_InitStructre.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructre.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructre);
PCout(4)=0;
PCout(11)=0;
PCout(12)=0;
delay_ms(20);
IC_Rest();
}
//通讯起始信号
void IC_Start(void)
{
SDA_OUT(); //设置IO为输出
CLK=1;
SDO=1;
delay_us(4);
SDO=0; //在CLK为高电平时,IO由高到低变化为起始
delay_us(4);
CLK=0;
}
//结束信号
void IC_Stop(void)
{
SDA_OUT(); //设置IO为输出
CLK=1;
SDO=0;
delay_us(4);
SDO=1; //在CLK为高的时候,IO由低到高变化为结束
delay_us(4);
CLK=0;
}
//发送一个字节数据
//data:要发送的数据
void IC_SendData(u8 data)
{
u8 t;
SDA_OUT(); //设置IO为输出模式
for(t=0;t<8;t++)
{
CLK=0;
if(data&0x01)
SDO=1;
else SDO=0;
data>>=1; //低位先发
delay_us(2);
CLK=1;
delay_us(2);
CLK=0;
delay_us(2);
}
}
//读一个字节数据
//返回值:读取的数据
u8 IC_ReadData(void)
{
u8 t,temp=0;
SDA_IN();
for(t=0;t<8;t++)
{
temp>>=1;
CLK=0;
delay_us(2);
CLK=1;
if(SDI)
temp|=0x80;
delay_us(2);
CLK=0;
}
return temp;
}
//操作终止函数
void IC_Break(void)
{
SDA_OUT();
SDO=0;
CLK=0;
RST=0;
delay_us(2);
RST=1;
SDO=1;
delay_us(10);
RST=0; //在CLK为低电平时,RST由高(保持5us)到低变化,产生复位
}
//芯片复位信号,ISO7816-3标准
//开始时,IO保持低电平,RST由低电瓶变为高电平,在高电平期间,给予一个CLK脉冲。
//此时,IO输出了一个有效的低电平信号,伺候连续读取4个Byte字节数据,读出EEPROM中
//4个字节标头数据,最后再给予一个CLK脉冲,使IO进入高阻状态
void IC_Rest(void)
{
SDA_OUT();
CLK=0;
SDO=1;
RST=0;
delay_us(5);
RST=1;
delay_us(5);
CLK=1;
delay_us(20);
CLK=0;
delay_us(5);
RST=0;
delay_us(5);
IC_ReadData();
IC_ReadData();
IC_ReadData();
IC_ReadData();
CLK=1;
delay_us(5);
CLK=0;
SDA_OUT();
}
//等待内部处理函数,开始时,有外部拉低,处理完成后拉高
//擦除和写入(5ms) 相当于255个CLK
//只写不擦(2.5) 相当于124个CLK
//只擦不写(2.5) 相当于124个CLK
u8 IC_WaitProcessing(void)
{
u16 i;
SDA_IN();
while(SDI)
{
i++;
CLK=0;
delay_us(2);
CLK=1;
delay_us(2);
if(i>255)
return 1;
}
SDA_OUT();
return 0;
}
//写入一个字节命令
//command:写入模式命令
//add:写入地址
//data:写入数据
void IC_WriteOneByte(u8 command,u8 add,u8 data)
{
IC_Start();
IC_SendData(command);
IC_SendData(add);
IC_SendData(data); //连续发送24bit数据
IC_Stop();
IC_WaitProcessing(); //内部处理中
}
//连续写内存
//command:写入模式命令
//add:写入起始地址
//data:写入数据存放数组地址
//len:要写入长度
void IC_WrtieRAM(u8 command,u8 add,u8* data,u8 len)
{
u8 i;
for(i=0;i<len;i++)
{
IC_WriteOneByte(command,add,data
);
add++;
}
}
//读取一个字节数据
//command:读取模式命令
//add:读取地址
//返回值:读取数据
u8 IC_ReadOneByte(u8 command,u8 add)
{
u8 temp;
IC_Start();
IC_SendData(command);
IC_SendData(add);
IC_SendData(0xFF); //该字节数据无效
temp=IC_ReadData();
IC_Stop();
IC_Break(); //结束等待下次通讯
return temp;
}
//连续读取多个字节数据
//command:读取模式命令
//add:读取目标首地址
//table:存放读取数据的数组首地址
//len:要读取的数据长度
void IC_ReadRAM(u8 command,u8 add,u8* table,u16 len)
{
u16 i;
IC_Start();
IC_SendData(command);
IC_SendData(add);
IC_SendData(0xFF); //该字节无效
IC_Stop();
for(i=0;i<len;i++) //可连续读取数据
{
table=IC_ReadData();
}
IC_Break(); //结束等待下次通讯
}
//输入密码比较
//password:24位密码
//返回值:0,密码错误;1,密码正确
u8 IC_PasswordCheck(u32 password)
{
u8 temp[4];
u8 t;
u8 p;
IC_ReadRAM(ReadSafRAM,0xFF,temp,4); //读取保护区4个字节数据,后三个为密码
if((temp[0]&0x07)!=0) //第一个数据为密码计数器,如果密码计数器不为0,可进行比对
{
if((temp[0]&0x07)==0x07) //每比对一次,密码计数器减少一次,从最低位开始减
t=0x06;
else if((temp[0]&0x07)==0x06)
t=0x04;
else if((temp[0]&0x07)==0x04)
t=0;
// IC_Rest();
IC_WriteOneByte(WriteSafRAM,0,t); //减少一次的密码计数器写入到存储器中
for(t=1;t<4;t++) //将输入的密码写入安全校验寄存器中进行校验
{
IC_WriteOneByte(0x33,t,0xFF);
}
IC_WriteOneByte(WriteSafRAM,0,0xFF);
IC_WriteOneByte(WriteSafRAM,0,0xFF);
IC_ReadOneByte(ReadSafRAM,0);
IC_ReadRAM(ReadSafRAM,0xFF,temp,4);
p=temp[0];
if((p&0x07)==0x07)
return 1;
}
return 0;
}
[/mw_shl_code]
另外还有一种卡接口芯片TDA8024、DS8113等,有没有谁使用过,我看了半天表示不知道单片机和芯片怎么通讯的,芯片和单片机的接口数据只有一个IO脚没有CLK,有没有大神给个提示
搞定了
一周热门 更多>