历史上的今天
返回首页

历史上的今天

今天是:2025年01月12日(星期日)

2020年01月12日 | AVR单片机实现IC读卡的程序设计

2020-01-12 来源:elecfans

AVR单片机IC卡程序

AVR单片机实现IC读卡的程序设计

#include

#include

#defineucharunsignedchar

#defineuintunsignedint

//**********定义全局变量*******************//

//查表0123456789EFPOFF

uchartable[14]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x79,0x71,0x73,0x00};

ucharICCode[4];//定义IC卡复位时读出的4字节代码;

ucharICcontent[14];//定义IC卡有效信息;

ucharMoney[5];//定义IC卡内金额;

ucharEEEEE[5]={0x79,0x79,0x79,0x79};

ucharFFFFF[5]={0x71,0x71,0x71,0x71};

ucharIC_Flag;//定义IC卡上电标志;

ucharNum_Flag;//数标志;

ucharAdd_Flag;//加标志

ucharSub_Flag;//减标志

ucharInit_Flag;//初始化标志

ucharRepair_Flag;//修卡标志;

ucharEnter_Flag;//确认标志

ucharPoint_Flag;//。标志

ucharKey_Flag;//按键标志;

//***********IC卡引脚信号处理***************//

voidVoice(ucharPD)//Voice=PD^7

{if(PD==1)PORTD|=0x80;//Voice置1

elsePORTD&=~80;//Voice置0

}

voidRST(ucharPD)//RST=PD^6

{if(PD==1)PORTD|=0x40;//RST置1

elsePORTD&=~0x40;//RST置0

}

voidCLK(ucharPD)//CLK=PD^5

{if(PD==1)PORTD|=0x20;//CLK置1

elsePORTD&=~0x20;//CLK置0

}

voidIO(ucharPD)//IO=PD^4

{if(PD==1)PORTD|=0x10;//IO置1

elsePORTD&=~0x10;//IO置0

}

voidSetIO(uchari)//设置IO口属性

{if(i==1)DDRD=0xf0;//IO口输出:11110000

elseDDRD=0xe0;//IO口输如:11100000

PORTD=0x00;//不带上拉电阻;

}

//**********延时函数(Us数量级)*********//

//单周期指令执行时间,执行时间1/8us*分频系数(取8分频则刚好1us);

voidDelayUs(uchari)

{for(;i!=0;i--)

NOP();

}

//****************延时函数(Ms数量级)*********//

voidDelayMs(uinTI)

{ucharj,k;

for(;i!=0;i--)

{for(k=0;k《4;k++)

{for(j=250;j!=0;j--)NOP();}

}

}

//****************接收数据**************//

ucharReceivEDAta(void)

{ucharcount;

ucharvalue;

uchario_value;

value=0;

SeTIO(0);//设置IO脚为输入;

CLK(0);

//IO=1;

for(count=0;count《8;count++)

{value=value》》1;

CLK(1);

DelayUs(2);

io_value=PIND;

CLK(0);

DelayUs(2);

if(io_value&0x10==0x10)value|=0x80;//判断IO脚是否为1

elsevalue&=0x7f;

}

return(value);

}

//********************发送数据************//

voidSendData(ucharXdata)

{ucharcount;

ucharvalue;

SeTIO(1);////设置IO脚为输出;

value=Xdata;

for(count=8;count!=0;count--)

{CLK(0);

if((Xdata《《(count-1))&0x80)IO(1);

elseIO(0);

CLK(1);

DelayUs(2);

CLK(0);}

}

//****************IC卡复位************************//

voidReseTIC(uchar*Xdata)

{ucharcount;

SetIO(1);//设置IC卡引脚的属性

RST(0);

CLK(0);

IO(1);

DelayUs(5);

RST(1);

DelayUs(5);

CLK(1);

DelayUs(5);

CLK(0);

DelayUs(5);

RST(0);

for(count=4;count!=0;count--)

{*Xdata=ReceiveData();

Xdata+=2;}

}

//*******************Start条件****************//

voidStart(void)

{SetIO(1);

CLK(0);

IO(0);

DelayUs(2);

CLK(1);

IO(1);

DelayUs(2);

IO(0);

CLK(0);

}

//*******************Stop条件****************//

voidStop(void)

{CLK(0);

IO(0);

DelayUs(2);

CLK(1);

IO(0);

DelayUs(2);

IO(1);

DelayUs(2);

IO(0);

}

//******************处理过程**************//

voidProcess(void)

{uintj;

SetIO(1);//设置IO脚为输出脚

CLK(0);

DelayUs(5);

IO(0);

for(j=255;j》0;j--)

{CLK(1);

DelayUs(5);

CLK(0);

DelayUs(5);

}

IO(1);

}

//****************说明*********************//

//*********输出模式接口命令,包括读主存储器30H,读保护存储器34H,读安全代码的接口命令31H***********//

//******处理模式数据接口命令,包括写主存储器38H,写保护存储器3CH,写安全代码39H,校验安全代码33H*******//

voidCommand(ucharByte1,ucharByte2,ucharByte3)

{Start();

SendData(Byte1);

SendData(Byte2);

SendData(Byte3);

Stop();

}

/**********读主存储器**************/

voidReaDMAinMemory(ucharaddr,uchar*p,ucharN)

{Command(0x30,addr,0xff);

do{*p=ReceiveData();

p++;}while(--N);

}

/**********读保护存储器***********/

voidReadProtectMemory(uchar*p)

{uchari=4;

Command(0x34,0xff,0xff);

do{*p=ReceiveData();

p++;}while(i--);

}

/************写主存储器************/

voidWriteMainMemory(ucharAddress,ucharData)

{Command(0x38,Address,Data);

Process();

}

/**************写保护存储器**********/

voidWriteProtectMemory(ucharAddress,ucharData)

{Command(0x3c,Address,Data);

Process();

}

/**************读安全存储器************/

voidReadSafeMemory(uchar*p)

{uchari;

Command(0x31,0xff,0xff);

for(i=0;i《4;i++)

{*p=ReceiveData();

p++;}

}

/*************写安全存储器***************/

voidWriteSafeMemory(ucharAddress,ucharData)

{Command(0x39,Address,Data);//Address=0,1,2,3

Process();

}

/**************校验密码*******************/

ucharVerifyPassword(uchar*p)

{uchartemp[4];//暂存4字节保护密码;

uchari;

ReadSafeMemory(temp);//读安全代码以取得错误计数器

if((temp[0]&0x07)!=0)

{if((temp[0]&0x07)==0x07)i=0x06;

if((temp[0]&0x07)==0x06)i=0x04;

if((temp[0]&0x07)==0x04)i=0x00;

WriteSafeMemory(0,i);

for(i=1;i《4;i++,p++)

{Command(0x33,i,*p);

Process();}

WriteSafeMemory(0,0xff);

ReadSafeMemory(temp);

if((temp[0]&0x07)==0x07)return(0x1);

}

return(0);

}

//*************SLE4442函数结束*****************//

//*************数据变换**********//

voidChange(uchar*Source,uchar*Destination,ucharN)

{uchari,temp;

for(i=0;i{temp=Source[i];

Destination[i]=temp》》4;

Destination[2*i+1]=temp&0x0f;}

}

//***********密码错误报警***********************//

voidBuzzle_Password(void)

{uchari;

for(i=0;i《2;i++)

{Voice(0);

DelayMs(1000);

Voice(1);

DelayMs(1000);}

}

//**********非法卡错误报警*************************//

voidBuzzle_Card(void)

{uchari;

for(i=0;i《2;i++)

{Voice(0);

DelayMs(3000);}

}

//*************余额不足报警**********************//

voidBuzzle_Money(void)

{uchari;

for(i=0;i《1;i++)

{Buzzle_Password();

Buzzle_Card();}

}

//*********************读卡函数********************//

//说明:

//函数使用的数组参数用来存放读出的余额值;

//返回值信息:

//0:卡坏!

//1:非法卡(特征值不正确)

//2:非法卡(特征值正确,帐号不正确)

//3:读卡成功!

ucharRead_Card(uchar*p)

{uchari,tag=0,temp[4];

ReadSafeMemory(temp);

if(temp[0]==0x07)

{ReadMainMemory(32,p,14);//读主存储器14字节:32-35特征码;36-3A帐号;3B-3F余额

if(p[0]==0x00&&p[1]==0x0f&&p[2]==0xf0&&p[3]==0xff)//特征码:0x00,0x0f,0xf0,0xff

{for(i=0;i《10;i++)

if((p[i+4]》=0&&p[i+4]《=9))tag=tag+1;

if(tag!=10)return(2);

elsereturn(3);

}

else

return(1);

}

elsereturn(0);

}

//*********************卡初始化函数********************//

//说明:

//函数使用的数组参数用来存放写入的的ID值;

//返回值信息:

//2:初始化失败!

//3:初始化成功!

ucharInitial_Card(uchar*p)

{ucharPsw[3]={0xff,0xff,0xff};

uchari,j,temp=0;

uchartp[20];

//ResetIC(ICcode);//IC卡复位,读出复位后的厂家信息代码A2131091;

j=VerifyPassword(Psw);

WriteMainMemory(32,0x00);//写特征码:

WriteMainMemory(33,0x0f);

WriteMainMemory(34,0xf0);

WriteMainMemory(35,0xff);

for(i=0;i《5;i++)//写帐号

WriteMainMemory(36+i,p[i]);//从32+i地址开始写5字节帐号;

for(i=0;i《5;i++)

WriteMainMemory(41+i,0);//从32+i地址开始写5字节初始化金额0000.0

j=Read_Card(tp);

if(j==3)

{for(i=0;i《10;i++)

if(p[i]==tp[i+4])temp=temp+1;

}

if(temp==10)return(3);

elsereturn(2);

}

//***************卡修复函数********************//

//说明:

//返回值信息:

//0:修复失败!

//1:修复成功!

ucharRepair_Card(void)

{ucharPsw[3]={0xff,0xff,0xff};

uchari,j,temp;

i=VerifyPassword(Psw);

return(i);

}

//********************加卡函数***********//

voidAdd_Card(uchar*p)

{uchari;

uchartemp[14];

i=Read_Card(temp);

if(i==3)

{temp[13]=temp[13]+p[4];

if(temp[13]》9){temp[13]=temp[13]-10;temp[12]=temp[12]+1;}

temp[12]=temp[12]+p[3];

if(temp[12]》9){temp[12]=temp[12]-10;temp[11]=temp[11]+1;}

temp[11]=temp[11]+p[2];

if(temp[11]》9){temp[11]=temp[11]-10;temp[10]=temp[10]+1;}

temp[10]=temp[10]+p[1];

if(temp[10]》9){temp[10]=temp[10]-10;temp[9]=temp[9]+1;}

WriteMainMemory(41,temp[9]);

WriteMainMemory(42,temp[10]);

WriteMainMemory(43,temp[11]);

WriteMainMemory(44,temp[12]);

WriteMainMemory(45,temp[13]);

}

}

//********************减卡函数***********//

voidSub_Card(uchar*p)

{uchari,B_Flag;

uchartemp[14];

i=Read_Card(temp);

if((i==3)&&(!(temp[9]{if(temp[13]elsetemp[13]=temp[13]-p[4];

//以上处理小数点右边的数字;

if(B_Flag==1)

{if(temp[12]==0){temp[12]=9;B_Flag=0;}

elsetemp[12]=temp[12]-1;}

//以上对存在借位情况时对小数点左边第一位进行预处理;

if(temp[12]elsetemp[12]=temp[12]-p[3];

//以上处理小数点小数点左边第一位数字;

if(B_Flag==1)

{if(temp[11]==0){temp[11]=9;B_Flag=0;}

elsetemp[11]=temp[11]-1;}

//以上对存在借位情况时对小数点左边第二位进行预处理;

if(temp[11]elsetemp[11]=temp[11]-p[2];

//以上处理小数点小数点左边第二位数字;

if(B_Flag==1)

{if(temp[10]==0){temp[10]=9;B_Flag=0;}

elsetemp[10]=temp[10]-1;}

//以上对存在借位情况时对小数点左边第三位进行预处理;

if(temp[10]elsetemp[10]=temp[10]-p[1];

//以上处理小数点小数点左边第三位数字;

if(B_Flag==1)

{if(temp[9]==0){temp[9]=0;B_Flag=0;}

elsetemp[9]=temp[9]-1;}

//以上对存在借位情况时对小数点左边第二位进行预处理;

temp[9]=temp[9]-p[0];

//以上处理小数点小数点左边第二位数字;

WriteMainMemory(41,temp[9]);

WriteMainMemory(42,temp[10]);

WriteMainMemory(43,temp[11]);

WriteMainMemory(44,temp[12]);

WriteMainMemory(45,temp[13]);

}

}

//*****************数码管显示函数********************//

voidDisplay(uchar*p)

{ucharsel,i;

sel=0x01;

for(i=0;i《6;i++)

{PORTA=table[p[i]];

PORTB=sel;

DelayMs(2);

sel=sel《《1;}

}

//****************键盘扫描函数***********************//

ucharKey_SCAN(void)

{ucharsccode,recode;

PORTC=0xf0;

if((PINC&0xf0)!=0xf0)

{DelayMs(10);

if((PINC&0xf0)!=0xf0)

{sccode=0xfe;

while(sccode&0x10!=0x00)

{PORTC=sccode;//对第一行键盘测试

if((PINC&0xf0)!=0xf0)

{recode=(PINC&0xf0)|0x0f;

return((~sccode)+(~recode));}

else

sccode=(sccode《《1)|0x01;

}

}

}

return(0x00);

}

//******************按键处理函数*******************//

voidKey_Process(uchar*p)

{uchartemp,value;

temp=Key_Scan();

switch(temp)

{case0x11:value=9;Num_Flag=1;break;

case0x21:value=8;Num_Flag=1;break;

case0x41:value=7;Num_Flag=1;break;

case0x12:value=6;Num_Flag=1;break;

case0x22:value=5;Num_Flag=1;break;

case0x42:value=4;Num_Flag=1;break;

case0x14:value=3;Num_Flag=1;break;

case0x24:value=2;Num_Flag=1;break;

case0x44:value=1;Num_Flag=1;break;

case0x18:value=0;Num_Flag=1;break;

case0x28:Point_Flag=1;break;

case0x82:Add_Flag=1;Sub_Flag=0;Key_Flag=1;break;

case0x84:Sub_Flag=1;Add_Flag=0;Key_Flag=1;break;

case0x48:Repair_Flag=1;Key_Flag=1;break;

case0x81:Init_Flag=1;Key_Flag=1;break;

case0x88:Enter_Flag=1;Key_Flag=0;break;

default:NOP();

}

if(Num_Flag==1){p[4]=p[3];p[3]=p[2];p[2]=p[1];p[1]=value;Num_Flag=0;}

if(Point_Flag==1){p[0]=value;Point_Flag=0;}

if(Add_Flag==1){Add_Flag=1;Sub_Flag=0;}

if(Sub_Flag==1){Sub_Flag=1;Add_Flag=0;}

if(Init_Flag==1){Init_Flag=1;}

if(Repair_Flag==1){Repair_Card();Repair_Flag=0;}

if(Enter_Flag==1)

{if(Add_Flag==1){Add_Card(p);Enter_Flag=0;Add_Flag=0;}

if(Sub_Flag==1){Sub_Card(p);Enter_Flag=0;Sub_Flag=0;}

if(Init_Flag==1){Initial_Card(p);Init_Flag=0;}}

}

//***************中断处理********************//

//**********定时器2:16ms中断显示一次*******//

#pragmainterrupt_handlerTIMER1_INT:9

voidTIMER1_INT(void)

{uchartemp[5],i;

for(i=0;i《5;i++)

temp[i]=ICcontent[9+i];

if(IC_Flag==0)Display(EEEEE);

if(IC_Flag==1)Display(FFFFF);

if(IC_Flag==3)

{if(Key_Flag==1)//显示此次操作金额;

{Money[1]|=0x80;//显示时加上小数点;

Display(Money);}

else//显示卡内余额;

{temp[4]|=0x80;

Display(temp);}

}

}

//*************系统初始化*************//

voidInitial_System(void)

{//系统初始化

//SPL=0x5f;//AT90S8535的堆栈指针指向最高RAM地址;

//SPH=0x02;

//IO口初始化;

DDRA=0xff;//A口输出高电平

PORTA=0xff;

DDRB=0xff;//B口输出低电平

PORTB=0x00;

DDRC=0x0f;//C口高四位输入(不带上拉电阻)低四位输出0

PORTC=0xf0;

DDRD=0xff;//D口输出低电平

PORTD=0x00;

//中断系统初始化(定时器1中断)

SREG=SREG|0x80;//I(SREG^7)全局中断使能置位

TIMSK=TIMSK|0x40;//TOIE1(TIMSK^2)T/C1溢出中断使能置位

TIFR=TIFR|0x40;//TOV1(TIFR^2)T/C1溢出中断标志位写“1”清0

//定时器初始化

TCCR1B=TCCR1B|0x20;//定时器时钟分频=CLK/8(1uS计数)

TCNT1H=0xc1;//需要计数16000=0x3E80次,

TCNT1L=0x7f;//计数初值0xff-0x3e80=0xc17f;

推荐阅读

史海拾趣

Defense Supply Center Columbus公司的发展小趣事

在电子行业,产品质量是企业生存和发展的关键。Defense Supply Center Columbus公司始终将质量管理放在首位,建立起一套完善的质量管理体系。公司严格按照国际标准进行生产和检测,确保每一件产品都符合质量要求。同时,公司还注重员工的培训和教育,提高员工的质量意识和操作技能。这些措施的实施,使得公司的产品质量得到了显著提升,赢得了客户的广泛赞誉。

ELM [ELM Electronics]公司的发展小趣事

随着产品线的不断扩张,ELM开始积极拓展市场,寻求更广阔的发展空间。公司制定了国际化战略,通过参加国际展会、建立海外销售渠道等方式,成功将产品打入国际市场。同时,ELM还积极与国际知名电子企业开展合作,共同研发新产品、开拓新市场。这些举措不仅为ELM带来了更多的商业机会,也提升了公司的国际影响力。

EFINIX公司的发展小趣事

为了加速Quantum™可编程加速器技术的商业化进程,EFINIX公司与中芯国际集成电路制造有限公司展开合作。中芯国际是世界领先的集成电路晶圆代工企业之一,其先进的制造能力为EFINIX公司提供了强有力的支持。双方合作仅用了不到六个月的时间,就成功交付了首批Quantum™可编程加速器产品样本,创造了行业内的里程碑。

CT [ Central Technologies ]公司的发展小趣事

CT公司成立于电子行业的黄金时期,起初只是一个小型研发团队,专注于研发新型半导体技术。创始人凭借对技术的敏锐洞察和不懈追求,带领团队攻克了一个又一个技术难题。然而,资金短缺、市场竞争激烈以及技术迭代的快速性给初创期的CT公司带来了巨大的挑战。公司多次面临生死存亡的边缘,但创始人始终坚持技术创新的初心,不断寻求合作伙伴和投资,逐渐在市场中站稳了脚跟。

Austek Microsystems公司的发展小趣事

Austek Microsystems成立之初,便以研发创新为核心驱动力。面对竞争激烈的市场环境,公司团队凭借深厚的技术积累,成功开发出了一款具有高性能和低功耗特点的微控制器芯片。这款芯片不仅满足了当时市场对高效能计算的需求,也为Austek Microsystems在电子行业中赢得了初步的市场认可。

FTDI公司的发展小趣事

面对行业技术的快速迭代,Austek Microsystems始终保持敏锐的洞察力。公司不断投入研发资金,引进先进的生产设备和技术人才,进行技术升级和产品迭代。通过不断地优化产品性能、提升生产效率,Austek Microsystems逐渐在市场中树立起了技术领先的形象。

问答坊 | AI 解惑

SHLoadDIBitmap这个函数并不是所有bmp结尾的图片都能显示?

我发现在我的wince5.0系统里,只有一个像素32位的图片才能显示,其他的都不行?…

查看全部问答>

FT232的虚拟COM问题

板子上面使用了FT232芯片做USB转UART,板子通过USB连接到电脑时,电脑在设备管理器中显示的是COM口 请问如果要在写一个程序和板子通讯的话,那么是不是作为COM口通讯就可以了…

查看全部问答>

如何通过单片机控制AD9851中D0~D7引脚调节频率大小

麻烦高手讲解详细点!!谢谢了,急用…

查看全部问答>

请问如何在AT91SAM9260上开发过ISI驱动马?

本人需要在AT91SAM9260上开发ISI驱动,已经在网上下载到AVR32的源码,不知道如何进一步开发,请指教…

查看全部问答>

wince 读写 u盘死机

wince 下.net 的程序,读写U盘。大部分时间正常。 偶尔会发生写文件的时候,程序死在那里的情况。 现象是,writefile 的时候,函数一直不返回。有时候插拔下 U 盘就自动返回了。而且,里面的内容写成功的。 观察发现,在读写U 判断的时候,.net ...…

查看全部问答>

WindowsMobile6SDK如何开发MIPS,Xscale和x86的应用?

我使用的是Visual Studio 2005 + Windows Mobile 6 SDK。打开工程后,在“活动解决方案平台”中只有“Windows Mobile 6 Professional SDK (ARMV4I)”,“Pocket PC 2003 (ARM4)”和“Smartphone 2003 (ARM4)”。这样的话只能编译ARM的应用程序了, ...…

查看全部问答>

ad转换在开发板与自己焊的板子上的区别

做了个ad转换的最小系统,在开发板上运行时正常,速度挺快的,但是放到自己焊的板子上就变得很慢,ad转换大概会慢10s左右,有人知道是为什么吗?(接线没问题,按照开发板接的,一样的程序)。…

查看全部问答>

有谁买过特权同学设计的SF-NIOS2开发板?我最近使用发现存在缺陷

最近使用了配置芯片,但是.sof和。elf文件下载到芯片中,下电后然后上电,板子不运行。。在CPU中已近把复位向量还成了epcs控制器,异常向量改成了SDRAM````````````````````````现在这个板子都已近下架了,找不到售后了,我擦,悲剧。。。花了我480 ...…

查看全部问答>

【一起学器件指标】——第一弹【ADC】资料汇总

【活动贴】一起学器件指标第一弹https://bbs.eeworld.com.cn/thread-319290-1-1.html 【活动贴】ADC性能指标之INL和DNL讨论https://bbs.eeworld.com.cn/thread-319915-1-1.html 【一起学器件指标】ADC基础知识https://bbs.eeworld.com.cn/thread- ...…

查看全部问答>

launchpad串口接12864液晶显示问题

最近在弄launch pad 串行接12864液晶屏, 但就是出不来,跪求大神们前来指导。//P2.6为SID 接R/W, P2.7为SCLK, 接E, cs端接vcc, psb接gnd.#include <msp430g2433.h>unsigned char array1[]={\"hello world\"};void delay(unsigned char n){ u ...…

查看全部问答>