共2条
1/1 1 跳转至页
ic 关于ic卡的问题请教各位!很急!!
问
我用f1121做了一个ic卡的读写程序,用的是24c01A我对其他卡不是太了解,由于加密性能不好,现在想改用4442,不知道电路是否需要修改,如果改,如何改?
答 1:
测试通过的。
/*卡片:3V_SLE4442,SLE7442。
CLK-P6.0 需接上拉电阻
RST-P6.1
VCC-P6.2
GIO-P6.3 需接上拉电阻
*/
#include <MSP430x41x.h>
#include <math.h>
#define CLK BIT0
#define RST BIT1
#define VCC BIT2
#define GIO BIT3
unsigned int i;
unsigned char a[4];//卡的序列号
unsigned char jiaoyan=0;//密码校验结果
unsigned char outgoing_data[10];//读出数据的缓存
void init_icp(void)
{ P6OUT=0;
P6DIR|= (CLK+VCC+RST); //将clk/vcc/rst拉低
P6DIR&=~GIO;//I/O INPUT 数据线置高
P6SEL&=~(CLK+VCC+RST+GIO);
}
void delay5us (void)
{ _NOP();
_NOP();
_NOP();
}
void delay10us(void)
{ _NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
}
void StartComm(void)//开始命令模式
{
P6OUT&=~CLK;
P6DIR&=~GIO;
delay5us();
P6OUT|=CLK;
delay5us();
P6DIR|=GIO;
delay5us();
}
void StopComm(void)//功 能: 结束命令模式
{
P6OUT&=~CLK;
P6DIR|=GIO;
delay5us();
P6OUT|=CLK;
delay5us();
P6DIR&=~GIO;
delay10us();
}
void BreakOperate(void)
{
P6OUT&=~CLK;
P6OUT&=~RST;
P6DIR|=GIO;
delay5us();
P6OUT|=RST;
P6DIR&=~GIO;
delay5us();
P6OUT&=~RST;
delay5us();
}
unsigned char ReadByte(void)
{
unsigned char ch=0;
for (i = 8; i > 0; i--)
{
P6OUT&=~CLK;
delay5us();
P6OUT|=CLK;
ch = ch >> 1; //从低位读起
if(P6IN&GIO) ch |= 0x80;
delay5us();
}
return ch;
}
void WriteByte(unsigned char ch)
{
for(i = 8; i > 0; i--)
{
P6OUT&=~CLK;
if(ch&0x01)P6DIR&=~GIO;
else P6DIR|=GIO;
delay5us();
P6OUT|=CLK;
delay10us();
ch = ch >> 1; //右移一位
}
}
void ReadMode(unsigned char count)
{unsigned char j;
P6OUT&=~CLK;
delay5us();
j=0;
do
{
outgoing_data[j] = ReadByte(); //读入一个字节
j++;
}while(--count); //计数器减一,判断
}
void ProcessMode(void)
{
P6OUT&=~CLK;
delay5us();
P6DIR|=GIO;
for (i = 255; i > 0; i--)
{
P6OUT|=CLK;
delay5us();
P6OUT&=~CLK;
delay5us();
}
P6DIR&=~GIO;
}
void SendComm(unsigned char a0,unsigned char b0,unsigned char c0)
{
StartComm(); //开始发送命令
WriteByte(a0); //a: 发命令字
WriteByte(b0); //b: 发地址
WriteByte(c0); //c: 发数据
StopComm(); //结束发送命令
}
void ResetCard(void)
{ P6OUT|=VCC;
delay5us();
P6OUT&=~RST;
P6OUT&=~CLK;
P6DIR&=~GIO;
delay5us();
P6OUT|=RST;
delay5us();
P6OUT|=CLK;
delay10us();
delay10us();
delay10us();
delay10us();
P6OUT&=~CLK;
delay5us();
P6OUT&=~RST;
delay10us(); //复位和复位应答时序
// ___
//RST _| |_______________________
// _ _ __ __
//CLK __|0|_|1|_ ..._|31|_|32|_____
// _ __ __ ___ _____
// \/ \/D0\ ... \/D31\/
//I/O _/\__/\__/ /\___/
a[0] = ReadByte();//卡的序列号
a[1] = ReadByte();
a[2] = ReadByte();
a[3] = ReadByte(); //空读 32Bit (4Byte)
P6OUT&=~CLK;
delay5us(); //CLK_|31|_|32|______________
P6DIR&=~GIO;
_NOP(); // 30 \/ 31\/
P6OUT&=~CLK;
delay5us();
}
unsigned char Verify(void)
{ unsigned char i;
SendComm(0x31,0xff,0xff); //读密码存储区的命令字,第2,3个参数在此命令中被忽略
ReadMode(4); //读出
if((outgoing_data[0] & 0x07) != 0) //第一字节是错误计数器,如果错误计数器为0,直接退出
{
if((outgoing_data[0] & 0x07)==0x07) // 00000111
i = 0x06;
else if((outgoing_data[0] & 0x07)==0x06) // 00000110
i = 0x04;
else if((outgoing_data[0] & 0x07)==0x04) // 00000100
i = 0x00; //将其中一位为1的改为0
SendComm(0x39,0,i); //修改错误计数器
ProcessMode(); //处理
for (i = 1; i < 4; i++) //校对3字节的密码
{
SendComm(0x33,i,0xff); //发出校对命令,假设密码区全是1
ProcessMode(); //处理
}
SendComm(0x39,0,0xff); //擦除计数器恢复错误计数器
ProcessMode(); //处理
SendComm(0x31,0xff,0xff); //读密码存储区的命令字,第2,3个参数在此命令中被忽略
ReadMode(4); //读错误计数器的内容
if((outgoing_data[0] & 0x07)==0x07) //如果没有被成功擦除,表明校对失败
return 1 ;
else return 0;
}
return 0;
}
void WriteMainMem(unsigned char addr,unsigned data)
{
ResetCard();
SendComm(0x38, addr, data); //写主存的命令字,地址,数据
ProcessMode();
BreakOperate();
}
void ReadMainMem(unsigned char addr,unsigned num)//读addr地址开始的num个字节
{ ResetCard();
SendComm(0x30,addr,0xff);
ReadMode(num);//数据返回到OUTGOING_DATA,个数为入口值num
BreakOperate();
}
void main(void)
{ WDTCTL=WDTPW+WDTHOLD;
init_icp();
//测试
jiaoyan=Verify();//jiaoyan=1时才可以进行写操作
if(jiaoyan==1)WriteMainMem(0x31,0x11);
else _NOP();
ReadMainMem(0x31,2);
//测试
LPM3;
} 答 2: 刘工,我也凑合问一下:
430用IC卡的时候CLK到底该如何接电阻?
卡资料上说接下拉,论坛里说430作输出CLK不用接上拉,你这里又是接上拉。
/*卡片:3V_SLE4442,SLE7442。
CLK-P6.0 需接上拉电阻
RST-P6.1
VCC-P6.2
GIO-P6.3 需接上拉电阻
*/
#include <MSP430x41x.h>
#include <math.h>
#define CLK BIT0
#define RST BIT1
#define VCC BIT2
#define GIO BIT3
unsigned int i;
unsigned char a[4];//卡的序列号
unsigned char jiaoyan=0;//密码校验结果
unsigned char outgoing_data[10];//读出数据的缓存
void init_icp(void)
{ P6OUT=0;
P6DIR|= (CLK+VCC+RST); //将clk/vcc/rst拉低
P6DIR&=~GIO;//I/O INPUT 数据线置高
P6SEL&=~(CLK+VCC+RST+GIO);
}
void delay5us (void)
{ _NOP();
_NOP();
_NOP();
}
void delay10us(void)
{ _NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
}
void StartComm(void)//开始命令模式
{
P6OUT&=~CLK;
P6DIR&=~GIO;
delay5us();
P6OUT|=CLK;
delay5us();
P6DIR|=GIO;
delay5us();
}
void StopComm(void)//功 能: 结束命令模式
{
P6OUT&=~CLK;
P6DIR|=GIO;
delay5us();
P6OUT|=CLK;
delay5us();
P6DIR&=~GIO;
delay10us();
}
void BreakOperate(void)
{
P6OUT&=~CLK;
P6OUT&=~RST;
P6DIR|=GIO;
delay5us();
P6OUT|=RST;
P6DIR&=~GIO;
delay5us();
P6OUT&=~RST;
delay5us();
}
unsigned char ReadByte(void)
{
unsigned char ch=0;
for (i = 8; i > 0; i--)
{
P6OUT&=~CLK;
delay5us();
P6OUT|=CLK;
ch = ch >> 1; //从低位读起
if(P6IN&GIO) ch |= 0x80;
delay5us();
}
return ch;
}
void WriteByte(unsigned char ch)
{
for(i = 8; i > 0; i--)
{
P6OUT&=~CLK;
if(ch&0x01)P6DIR&=~GIO;
else P6DIR|=GIO;
delay5us();
P6OUT|=CLK;
delay10us();
ch = ch >> 1; //右移一位
}
}
void ReadMode(unsigned char count)
{unsigned char j;
P6OUT&=~CLK;
delay5us();
j=0;
do
{
outgoing_data[j] = ReadByte(); //读入一个字节
j++;
}while(--count); //计数器减一,判断
}
void ProcessMode(void)
{
P6OUT&=~CLK;
delay5us();
P6DIR|=GIO;
for (i = 255; i > 0; i--)
{
P6OUT|=CLK;
delay5us();
P6OUT&=~CLK;
delay5us();
}
P6DIR&=~GIO;
}
void SendComm(unsigned char a0,unsigned char b0,unsigned char c0)
{
StartComm(); //开始发送命令
WriteByte(a0); //a: 发命令字
WriteByte(b0); //b: 发地址
WriteByte(c0); //c: 发数据
StopComm(); //结束发送命令
}
void ResetCard(void)
{ P6OUT|=VCC;
delay5us();
P6OUT&=~RST;
P6OUT&=~CLK;
P6DIR&=~GIO;
delay5us();
P6OUT|=RST;
delay5us();
P6OUT|=CLK;
delay10us();
delay10us();
delay10us();
delay10us();
P6OUT&=~CLK;
delay5us();
P6OUT&=~RST;
delay10us(); //复位和复位应答时序
// ___
//RST _| |_______________________
// _ _ __ __
//CLK __|0|_|1|_ ..._|31|_|32|_____
// _ __ __ ___ _____
// \/ \/D0\ ... \/D31\/
//I/O _/\__/\__/ /\___/
a[0] = ReadByte();//卡的序列号
a[1] = ReadByte();
a[2] = ReadByte();
a[3] = ReadByte(); //空读 32Bit (4Byte)
P6OUT&=~CLK;
delay5us(); //CLK_|31|_|32|______________
P6DIR&=~GIO;
_NOP(); // 30 \/ 31\/
P6OUT&=~CLK;
delay5us();
}
unsigned char Verify(void)
{ unsigned char i;
SendComm(0x31,0xff,0xff); //读密码存储区的命令字,第2,3个参数在此命令中被忽略
ReadMode(4); //读出
if((outgoing_data[0] & 0x07) != 0) //第一字节是错误计数器,如果错误计数器为0,直接退出
{
if((outgoing_data[0] & 0x07)==0x07) // 00000111
i = 0x06;
else if((outgoing_data[0] & 0x07)==0x06) // 00000110
i = 0x04;
else if((outgoing_data[0] & 0x07)==0x04) // 00000100
i = 0x00; //将其中一位为1的改为0
SendComm(0x39,0,i); //修改错误计数器
ProcessMode(); //处理
for (i = 1; i < 4; i++) //校对3字节的密码
{
SendComm(0x33,i,0xff); //发出校对命令,假设密码区全是1
ProcessMode(); //处理
}
SendComm(0x39,0,0xff); //擦除计数器恢复错误计数器
ProcessMode(); //处理
SendComm(0x31,0xff,0xff); //读密码存储区的命令字,第2,3个参数在此命令中被忽略
ReadMode(4); //读错误计数器的内容
if((outgoing_data[0] & 0x07)==0x07) //如果没有被成功擦除,表明校对失败
return 1 ;
else return 0;
}
return 0;
}
void WriteMainMem(unsigned char addr,unsigned data)
{
ResetCard();
SendComm(0x38, addr, data); //写主存的命令字,地址,数据
ProcessMode();
BreakOperate();
}
void ReadMainMem(unsigned char addr,unsigned num)//读addr地址开始的num个字节
{ ResetCard();
SendComm(0x30,addr,0xff);
ReadMode(num);//数据返回到OUTGOING_DATA,个数为入口值num
BreakOperate();
}
void main(void)
{ WDTCTL=WDTPW+WDTHOLD;
init_icp();
//测试
jiaoyan=Verify();//jiaoyan=1时才可以进行写操作
if(jiaoyan==1)WriteMainMem(0x31,0x11);
else _NOP();
ReadMainMem(0x31,2);
//测试
LPM3;
} 答 2: 刘工,我也凑合问一下:
430用IC卡的时候CLK到底该如何接电阻?
卡资料上说接下拉,论坛里说430作输出CLK不用接上拉,你这里又是接上拉。
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |